<commit_before>module.exports = {

    incoming: function (message, bot, builder) {
        console.log('conversations/state')
        console.log(global.conversations);
        console.log('************');
        console.log('users');
        console.log(global.users);
        console.log('agents');
        console.log(global.agent);

        if (message.text) { // saves a ping from adding a user/agent

            if (message.text === 'help') {
                // user initiated connect to agent
                global.conversations[message.address.conversation.id] = Object.assign({}, global.conversations[message.address.conversation.id], { 'status': 'Finding_Agent' });
                message.text = 'hold on while I connect you';
                // return message
            };

            // find out who is talking / add new convo if not found
            if (message.user.isStaff) { // move logic to an API for agents
                console.log('is staff');
                var agentId = message.address.conversation.id;
                var thisAgent = global.conversations[agentId];
                if (typeof thisAgent === 'undefined') { // agent not in state yet, add them ****This will happen for each conversation, not agent.
                    global.agent.push(agentId);
                    global.conversations[agentId].address = message.address;
                }
            }
            // End Agent

            // Setting User state logic
            else {
                console.log('not staff');
                var userId = message.address.conversation.id;
                var thisUser = global.conversations[userId];
                // Add a user not yet in state

                if (typeof thisUser === 'undefined') {
                    console.log('got undefined');
                    global.users.push(userId);
                    global.conversations[userId] = { transcript: [message], address: message.address, status: 'Talking_To_Bot' };
                    return
                }
                // if in state, update transcript for the user
                global.conversations[userId] = Object.assign({}, global.conversations[userId], { transcript: global.conversations[userId].transcript.push(message) });

                // Check for choices to be made
                console.log(global.conversations[userId].status);
                switch (global.conversations[userId].status) {
                    case 'Finding_Agent':
                        message.text = 'getting agent';
                        var myAgent = global.conversations[global.agent[0]];
                        global.conversations[userId] = Object.assign({}, global.conversations[message.address.conversation.id], { agentAddress: myAgent.address, 'status': 'Talking_To_Agent' });
                        return message;
                        break;
                    case 'Talking_To_Agent':
                        message.text = 'talking to agent';
                        break;
                    case 'Talking_To_Bot':
                        message.text = 'talk to bot';
                        return message;
                        break;
                    default:
                        message.text = 'defaulting';
                        return message;
                        break;

                }

            }
        }

        // who should they be talking to
        // make it so
        // if talking to Agent/waiting for agent, suppress default bot functionality (how if on a prompt and it's looking for a certain response? override somehow)

    }
}
<commit_msg>so odd<commit_after>module.exports = {

    incoming: function (message, bot, builder) {
        console.log('conversations/state')
        console.log(global.conversations);
        console.log('************');
        console.log('users');
        console.log(global.users);
        console.log('agents');
        console.log(global.agent);

        if (message.text) { // saves a ping from adding a user/agent

            if (message.text === 'help') {
                // user initiated connect to agent
                global.conversations[message.address.conversation.id] = Object.assign({}, global.conversations[message.address.conversation.id], { 'status': 'Finding_Agent' });
                message.text = 'hold on while I connect you';
                // return message
            };

            // find out who is talking / add new convo if not found
            if (message.user.isStaff) { // move logic to an API for agents
                console.log('is staff');
                var agentId = message.address.conversation.id;
                var thisAgent = global.conversations[agentId];
                if (typeof thisAgent === 'undefined') { // agent not in state yet, add them ****This will happen for each conversation, not agent.
                    global.agent.push(agentId);
                    global.conversations[agentId].address = message.address;
                }
            }
            // End Agent

            // Setting User state logic
            else {
                console.log('not staff');
                var userId = message.address.conversation.id;
                var thisUser = global.conversations[userId];
                // Add a user not yet in state

                if (typeof thisUser === 'undefined') {
                    console.log('got undefined');
                    global.users.push(userId);
                    global.conversations[userId] = { transcript: [message], address: message.address, status: 'Talking_To_Bot' };
                    return
                }
                // if in state, update transcript for the user
                // global.conversations[userId] = Object.assign({}, global.conversations[userId], { transcript: global.conversations[userId].transcript.push(message) });

                // Check for choices to be made
                console.log('about to make the switch')
                console.log(global.conversations[userId].status);
                switch (global.conversations[userId].status) {
                    case 'Finding_Agent':
                        message.text = 'getting agent';
                        var myAgent = global.conversations[global.agent[0]];
                        global.conversations[userId] = Object.assign({}, global.conversations[message.address.conversation.id], { agentAddress: myAgent.address, 'status': 'Talking_To_Agent' });
                        return message;
                        break;
                    case 'Talking_To_Agent':
                        message.text = 'talking to agent';
                        break;
                    case 'Talking_To_Bot':
                        message.text = 'talk to bot';
                        return message;
                        break;
                    default:
                        message.text = 'defaulting';
                        return message;
                        break;

                }

            }
        }

        // who should they be talking to
        // make it so
        // if talking to Agent/waiting for agent, suppress default bot functionality (how if on a prompt and it's looking for a certain response? override somehow)

    }
}
<|endoftext|>


<commit_before>'use strict';

var React = require('react'),
    Router = require('react-router'),
    runRouter = require('./runRouter')

// Client side rendering
var renderPage = function(Handler, data) {
    React.render(React.createElement(Handler, {data: cleanData(data)}), document)
}

module.exports = function(routes) {
    runRouter(routes, Router.HistoryLocation, function(Handler, data) {
        renderPage(Handler, data)
    })
}
<commit_msg>Fix cleanData<commit_after>'use strict';

var React = require('react'),
    Router = require('react-router'),
    runRouter = require('./runRouter')

// Client side rendering
var renderPage = function(Handler, data) {
    React.render(React.createElement(Handler, {data: data}), document)
}

module.exports = function(routes) {
    runRouter(routes, Router.HistoryLocation, function(Handler, data) {
        renderPage(Handler, data)
    })
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011 Vinay Pulim <vinay@milewise.com>
 * MIT Licensed
 */

"use strict";

function findKey(obj, val) {
  for (var n in obj)
    if (obj[n] === val)
      return n;
}

var HttpClient = require('./http'),
  assert = require('assert'),
  events = require('events'),
  util = require('util'),
  debug = require('debug')('node-soap'),
  url = require('url');

var Client = function(wsdl, endpoint, options) {
  events.EventEmitter.call(this);

  options = options || {};
  this.wsdl = wsdl;
  this._initializeOptions(options);
  this._initializeServices(endpoint);
  this.httpClient = options.httpClient || new HttpClient(options);
};
util.inherits(Client, events.EventEmitter);

Client.prototype.addSoapHeader = function(soapHeader, name, namespace, xmlns) {
  if (!this.soapHeaders) {
    this.soapHeaders = [];
  }
  if (typeof soapHeader === 'object') {
    soapHeader = this.wsdl.objectToXML(soapHeader, name, namespace, xmlns, true);
  }
  this.soapHeaders.push(soapHeader);
};

Client.prototype.getSoapHeaders = function() {
  return this.soapHeaders;
};

Client.prototype.clearSoapHeaders = function() {
  this.soapHeaders = null;
};

Client.prototype.addBodyAttribute = function(bodyAttribute, name, namespace, xmlns) {
  if (!this.bodyAttributes) {
    this.bodyAttributes = [];
  }
  if (typeof bodyAttribute === 'object') {
    var composition = '';
    Object.getOwnPropertyNames(bodyAttribute).forEach(function(prop, idx, array) {
      composition += ' ' + prop + '="' + bodyAttribute[prop] + '"';
    });
    bodyAttribute = composition;
  }
  if (bodyAttribute.substr(0, 1) !== ' ') bodyAttribute = ' ' + bodyAttribute;
  this.bodyAttributes.push(bodyAttribute);
};

Client.prototype.getBodyAttributes = function() {
  return this.bodyAttributes;
};

Client.prototype.clearBodyAttributes = function() {
  this.bodyAttributes = null;
};

Client.prototype.setEndpoint = function(endpoint) {
  this.endpoint = endpoint;
  this._initializeServices(endpoint);
};

Client.prototype.describe = function() {
  var types = this.wsdl.definitions.types;
  return this.wsdl.describeServices();
};

Client.prototype.setSecurity = function(security) {
  this.security = security;
};

Client.prototype.setSOAPAction = function(SOAPAction) {
  this.SOAPAction = SOAPAction;
};

Client.prototype._initializeServices = function(endpoint) {
  var definitions = this.wsdl.definitions,
    services = definitions.services;
  for (var name in services) {
    this[name] = this._defineService(services[name], endpoint);
  }
};

Client.prototype._initializeOptions = function(options) {
  this.wsdl.options.attributesKey = options.attributesKey || 'attributes';
};

Client.prototype._defineService = function(service, endpoint) {
  var ports = service.ports,
    def = {};
  for (var name in ports) {
    def[name] = this._definePort(ports[name], endpoint ? endpoint : ports[name].location);
  }
  return def;
};

Client.prototype._definePort = function(port, endpoint) {
  var location = endpoint,
    binding = port.binding,
    methods = binding.methods,
    def = {};
  for (var name in methods) {
    def[name] = this._defineMethod(methods[name], location);
    this[name] = def[name];
  }
  return def;
};

Client.prototype._defineMethod = function(method, location) {
  var self = this;
  return function(args, callback, options, extraHeaders) {
    if (typeof args === 'function') {
      callback = args;
      args = {};
    }
    self._invoke(method, args, location, function(error, result, raw, soapHeader) {
      callback(error, result, raw, soapHeader);
    }, options, extraHeaders);
  };
};

Client.prototype._invoke = function(method, args, location, callback, options, extraHeaders) {
  var self = this,
    name = method.$name,
    input = method.input,
    output = method.output,
    style = method.style,
    defs = this.wsdl.definitions,
    ns = defs.$targetNamespace,
    encoding = '',
    message = '',
    xml = null,
    req = null,
    soapAction,
    alias = findKey(defs.xmlns, ns),
    headers = {
      'Content-Type': "text/xml; charset=utf-8"
    };

  if (this.SOAPAction) {
    soapAction = this.SOAPAction;
  } else if (method.soapAction !== undefined && method.soapAction !== null) {
    soapAction = method.soapAction;
  } else {
    soapAction = ((ns.lastIndexOf("/") !== ns.length - 1) ? ns + "/" : ns) + name;
  }

  headers.SOAPAction = '"' + soapAction + '"';

  options = options || {};

  //Add extra headers
  for (var attr in extraHeaders) { headers[attr] = extraHeaders[attr]; }

  // Allow the security object to add headers
  if (self.security && self.security.addHeaders)
    self.security.addHeaders(headers);
  if (self.security && self.security.addOptions)
    self.security.addOptions(options);

  if (input.parts) {
    assert.ok(!style || style === 'rpc', 'invalid message definition for document style binding');
    message = self.wsdl.objectToRpcXML(name, args, alias, ns);
    (method.inputSoap === 'encoded') && (encoding = 'soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" ');
  } else if (typeof (args) === 'string') {
    message = args;
  } else if (args === null) {
    message = "<" + name + " />";
  } else {
    assert.ok(!style || style === 'document', 'invalid message definition for rpc style binding');
    // pass `input.$lookupType` if `input.$type` could not be found
    message = self.wsdl.objectToDocumentXML(input.$name, args, input.targetNSAlias, input.targetNamespace, (input.$type || input.$lookupType));
  }
  xml = "<soap:Envelope " +
    "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" " +
    "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
    encoding +
    this.wsdl.xmlnsInEnvelope + '>' +
    ((self.soapHeaders || (self.security && self.security.toXML())) ?
      (
        "<soap:Header>" +
        (self.soapHeaders ? self.soapHeaders.join("\n") : "") +
        (self.security ? self.security.toXML() : "") +
        "</soap:Header>"
      )
      :
        ''
      ) +
    "<soap:Body" +
    (self.bodyAttributes ? self.bodyAttributes.join(' ') : '') +
    ">" +
    message +
    "</soap:Body>" +
    "</soap:Envelope>";

  self.lastMessage = message;
  self.lastRequest = xml;

  self.emit('message', message);
  self.emit('request', xml);

  req = self.httpClient.request(location, xml, function(err, response, body) {
    var result;
    var obj;
    self.lastResponse = body;
    self.lastResponseHeaders = response && response.headers;
    self.emit('response', body);

    if (err) {
      callback(err);
    } else {
      try {
        obj = self.wsdl.xmlToObject(body);
      } catch (error) {
        //When the output element cannot be looked up in the wsdl,
        //Then instead of sending the error, We pass the body in the response.
        if(output && !output.$lookupTypes) {
          debug('Response element is not present. Unable to convert response xml to json.');
          return callback(null,response,body,null);
        }
        error.response = response;
        error.body = body;
        self.emit('soapError', error);
        return callback(error, response, body, null);
      }

      if (!output){
        // one-way, no output expected
        return callback(null, null, body, obj.Header);
      }

      if( typeof obj.Body !== 'object' ) {
        var error = new Error('Cannot parse response');
        error.response = response;
        error.body = body;
        return callback(error, obj, body, null);
      }

      result = obj.Body[output.$name];
      // RPC/literal response body may contain elements with added suffixes I.E.
      // 'Response', or 'Output', or 'Out'
      // This doesn't necessarily equal the ouput message name. See WSDL 1.1 Section 2.4.5
      if(!result){
        result = obj.Body[output.$name.replace(/(?:Out(?:put)?|Response)$/, '')];
      }
      if (!result) {
        ['Response', 'Out', 'Output'].forEach(function (term) {
          if (obj.Body.hasOwnProperty(name + term)) {
            return result = obj.Body[name + term];
          }
        });
      }

      callback(null, result, body, obj.Header);
    }
  }, headers, options, self);

  // Added mostly for testability, but possibly useful for debugging
  self.lastRequestHeaders = req.headers;
};

exports.Client = Client;
<commit_msg>store xml and body on context objects<commit_after>/*
 * Copyright (c) 2011 Vinay Pulim <vinay@milewise.com>
 * MIT Licensed
 */

"use strict";

function findKey(obj, val) {
  for (var n in obj)
    if (obj[n] === val)
      return n;
}

var HttpClient = require('./http'),
  assert = require('assert'),
  events = require('events'),
  util = require('util'),
  debug = require('debug')('node-soap'),
  url = require('url');

var Client = function(wsdl, endpoint, options) {
  events.EventEmitter.call(this);

  options = options || {};
  this.wsdl = wsdl;
  this._initializeOptions(options);
  this._initializeServices(endpoint);
  this.httpClient = options.httpClient || new HttpClient(options);
};
util.inherits(Client, events.EventEmitter);

Client.prototype.addSoapHeader = function(soapHeader, name, namespace, xmlns) {
  if (!this.soapHeaders) {
    this.soapHeaders = [];
  }
  if (typeof soapHeader === 'object') {
    soapHeader = this.wsdl.objectToXML(soapHeader, name, namespace, xmlns, true);
  }
  this.soapHeaders.push(soapHeader);
};

Client.prototype.getSoapHeaders = function() {
  return this.soapHeaders;
};

Client.prototype.clearSoapHeaders = function() {
  this.soapHeaders = null;
};

Client.prototype.addBodyAttribute = function(bodyAttribute, name, namespace, xmlns) {
  if (!this.bodyAttributes) {
    this.bodyAttributes = [];
  }
  if (typeof bodyAttribute === 'object') {
    var composition = '';
    Object.getOwnPropertyNames(bodyAttribute).forEach(function(prop, idx, array) {
      composition += ' ' + prop + '="' + bodyAttribute[prop] + '"';
    });
    bodyAttribute = composition;
  }
  if (bodyAttribute.substr(0, 1) !== ' ') bodyAttribute = ' ' + bodyAttribute;
  this.bodyAttributes.push(bodyAttribute);
};

Client.prototype.getBodyAttributes = function() {
  return this.bodyAttributes;
};

Client.prototype.clearBodyAttributes = function() {
  this.bodyAttributes = null;
};

Client.prototype.setEndpoint = function(endpoint) {
  this.endpoint = endpoint;
  this._initializeServices(endpoint);
};

Client.prototype.describe = function() {
  var types = this.wsdl.definitions.types;
  return this.wsdl.describeServices();
};

Client.prototype.setSecurity = function(security) {
  this.security = security;
};

Client.prototype.setSOAPAction = function(SOAPAction) {
  this.SOAPAction = SOAPAction;
};

Client.prototype._initializeServices = function(endpoint) {
  var definitions = this.wsdl.definitions,
    services = definitions.services;
  for (var name in services) {
    this[name] = this._defineService(services[name], endpoint);
  }
};

Client.prototype._initializeOptions = function(options) {
  this.wsdl.options.attributesKey = options.attributesKey || 'attributes';
};

Client.prototype._defineService = function(service, endpoint) {
  var ports = service.ports,
    def = {};
  for (var name in ports) {
    def[name] = this._definePort(ports[name], endpoint ? endpoint : ports[name].location);
  }
  return def;
};

Client.prototype._definePort = function(port, endpoint) {
  var location = endpoint,
    binding = port.binding,
    methods = binding.methods,
    def = {};
  for (var name in methods) {
    def[name] = this._defineMethod(methods[name], location);
    this[name] = def[name];
  }
  return def;
};

Client.prototype._defineMethod = function(method, location) {
  var self = this;
  return function(args, callback, options, extraHeaders) {
    if (typeof args === 'function') {
      callback = args;
      args = {};
    }
    self._invoke(method, args, location, function(error, result, raw, soapHeader) {
      callback(error, result, raw, soapHeader);
    }, options, extraHeaders);
  };
};

Client.prototype._invoke = function(method, args, location, callback, options, extraHeaders) {
  var self = this,
    name = method.$name,
    input = method.input,
    output = method.output,
    style = method.style,
    defs = this.wsdl.definitions,
    ns = defs.$targetNamespace,
    encoding = '',
    message = '',
    xml = null,
    req = null,
    soapAction,
    alias = findKey(defs.xmlns, ns),
    headers = {
      'Content-Type': "text/xml; charset=utf-8"
    };

  if (this.SOAPAction) {
    soapAction = this.SOAPAction;
  } else if (method.soapAction !== undefined && method.soapAction !== null) {
    soapAction = method.soapAction;
  } else {
    soapAction = ((ns.lastIndexOf("/") !== ns.length - 1) ? ns + "/" : ns) + name;
  }

  headers.SOAPAction = '"' + soapAction + '"';

  options = options || {};

  //Add extra headers
  for (var attr in extraHeaders) { headers[attr] = extraHeaders[attr]; }

  // Allow the security object to add headers
  if (self.security && self.security.addHeaders)
    self.security.addHeaders(headers);
  if (self.security && self.security.addOptions)
    self.security.addOptions(options);

  if (input.parts) {
    assert.ok(!style || style === 'rpc', 'invalid message definition for document style binding');
    message = self.wsdl.objectToRpcXML(name, args, alias, ns);
    (method.inputSoap === 'encoded') && (encoding = 'soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" ');
  } else if (typeof (args) === 'string') {
    message = args;
  } else if (args === null) {
    message = "<" + name + " />";
  } else {
    assert.ok(!style || style === 'document', 'invalid message definition for rpc style binding');
    // pass `input.$lookupType` if `input.$type` could not be found
    message = self.wsdl.objectToDocumentXML(input.$name, args, input.targetNSAlias, input.targetNamespace, (input.$type || input.$lookupType));
  }
  xml = "<soap:Envelope " +
    "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" " +
    "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
    encoding +
    this.wsdl.xmlnsInEnvelope + '>' +
    ((self.soapHeaders || (self.security && self.security.toXML())) ?
      (
        "<soap:Header>" +
        (self.soapHeaders ? self.soapHeaders.join("\n") : "") +
        (self.security ? self.security.toXML() : "") +
        "</soap:Header>"
      )
      :
        ''
      ) +
    "<soap:Body" +
    (self.bodyAttributes ? self.bodyAttributes.join(' ') : '') +
    ">" +
    message +
    "</soap:Body>" +
    "</soap:Envelope>";

  self.lastMessage = message;
  self.lastRequest = xml;

  self.emit('message', message);
  var ctx = {}
  ctx.xml = xml
  self.emit('request', ctx);

  req = self.httpClient.request(location, ctx.xml, function(err, response, body) {
    var result;
    var obj;
    self.lastResponse = body;
    self.lastResponseHeaders = response && response.headers;
    var resCtx = {}
    resCtx.body = body
    self.emit('response', resCtx);

    if (err) {
      callback(err);
    } else {
      try {
        obj = self.wsdl.xmlToObject(resCtx.body);
      } catch (error) {
        //When the output element cannot be looked up in the wsdl,
        //Then instead of sending the error, We pass the body in the response.
        if(output && !output.$lookupTypes) {
          debug('Response element is not present. Unable to convert response xml to json.');
          return callback(null,response,resCtx.body,null);
        }
        error.response = response;
        error.body = body;
        self.emit('soapError', error);
        return callback(error, response, resCtx.body, null);
      }

      if (!output){
        // one-way, no output expected
        return callback(null, null, resCtx.body, obj.Header);
      }

      if( typeof obj.Body !== 'object' ) {
        var error = new Error('Cannot parse response');
        error.response = response;
        error.body = body;
        return callback(error, obj, resCtx.body, null);
      }

      result = obj.Body[output.$name];
      // RPC/literal response body may contain elements with added suffixes I.E.
      // 'Response', or 'Output', or 'Out'
      // This doesn't necessarily equal the ouput message name. See WSDL 1.1 Section 2.4.5
      if(!result){
        result = obj.Body[output.$name.replace(/(?:Out(?:put)?|Response)$/, '')];
      }
      if (!result) {
        ['Response', 'Out', 'Output'].forEach(function (term) {
          if (obj.Body.hasOwnProperty(name + term)) {
            return result = obj.Body[name + term];
          }
        });
      }

      callback(null, result, resCtx.body, obj.Header);
    }
  }, headers, options, self);

  // Added mostly for testability, but possibly useful for debugging
  self.lastRequestHeaders = req.headers;
};

exports.Client = Client;
<|endoftext|>


<commit_before>var Util, DOM, CloudFunc, join;

(function(scope, Util, DOM, CloudFunc) {
    'use strict';

    scope.CloudCmd = new CloudCmdProto(Util, DOM, CloudFunc);

    function CloudCmdProto(Util, DOM, CloudFunc) {
        var Key,
            Debug,
            log                     = function(str) {
                if (Debug)
                    console.log(str);
            },

            TITLE,
            Listeners,
            Files                   = DOM.Files,
            Images                  = DOM.Images,
            Info                    = DOM.CurrentInfo,
            CloudCmd                = this,
            Storage                 = DOM.Storage,
            type                    = Util.type;

        this.log                    = log,
        this.PREFIX                 = '',
        this.PREFIX_URL             = '',
        this.LIBDIR                 = '/lib/';
        this.LIBDIRCLIENT           = '/lib/client/';
        this.MIN_ONE_PANEL_WIDTH    = 1155;
        this.HOST                   = location.origin ||
                                      location.protocol + '//' + location.host;

        this.TITLE                  = 'Cloud Commander';

        TITLE                       = this.TITLE;

        log.enable     = function() {
            Debug = true;
        };

        log.disable    = function() {
            Debug = false;
        };

        /**
         * Функция привязываеться ко всем ссылкам и
         *  загружает содержимое каталогов
         *
         * @param params - {
         *          paramLink - ссылка
         *          needRefresh - необходимость обязательной загрузки данных с сервера
         *          panel
         *      }
         * @param callback
         */
        this.loadDir                = function(params, callback) {
            var imgPosition, panelChanged,
                noCurrent,
                isRefresh, panel, history,
                p               = params;

            if (params) {
                isRefresh       = p.isRefresh;
                panel           = p.panel;
                history         = p.history;
                noCurrent       = p.noCurrent;
            }

            if (!noCurrent)
                if (panel && panel !== Info.panel) {
                    DOM.changePanel();
                    panelChanged = true;
                }

            if (panelChanged || isRefresh || !history)
                imgPosition = 'top';

            Images.show.load(imgPosition, panel);

            /* загружаем содержимое каталога */
            ajaxLoad(p.path, {
                refresh     : isRefresh,
                history     : history,
                noCurrent   : noCurrent
            }, panel, callback);
        };

        /**
         * function load modules
         * @pParams = {name, path, func, dobefore, arg}
         */
        function loadModule(params) {
            var name, path, func, doBefore,
                funcName, isContain;

            if (params) {
                name        = params.name,
                path        = params.path,
                func        = params.func,
                funcName    = params.funcName,
                doBefore    = params.dobefore;

                if (path && !name) {
                    name = getStrBigFirst(path);
                    name = name.replace(/.js$/, '');
                }

                isContain   = /\.js/.test(path);

                if (!isContain)
                    path += '.js';

                if (!CloudCmd[name]) {
                    CloudCmd[name] = function() {
                        var prefix      = CloudCmd.PREFIX,
                            pathFull    = prefix + CloudCmd.LIBDIRCLIENT + path,
                            args        = arguments;

                        Util.exec(doBefore);

                        return DOM.load.js(pathFull, func ||
                            function(error) {
                                var Proto = CloudCmd[name];

                                if (!error && type.function(Proto))
                                    CloudCmd[name] = applyConstructor(Proto, args);
                            });
                    };

                    CloudCmd[name][funcName] = CloudCmd[name];
                }
            }
        }

        /*
         * apply arguemnts to constructor
         *
         * @param constructor
         * @param args
         */
        function applyConstructor(constructor, args) {
            var F = function () {
                return constructor.apply(this, args);
            };

            F.prototype = constructor.prototype;
            return new F();
        }

        /** Конструктор CloudClient, который
         * выполняет весь функционал по
         * инициализации
         */
        this.init                    = function(prefix) {
            var func        = function() {
                    Util.exec.series([
                        initModules,
                        baseInit,
                        function() {
                            CloudCmd.route(location.hash);
                        }
                    ]);
                },

                funcBefore  = function(callback) {
                    var src = prefix + '/join:' + [
                            CloudCmd.LIBDIRCLIENT + 'polyfill.js',
                            '/modules/domtokenlist-shim/dist/domtokenlist.min.js',
                        ].join(':');

                    DOM.loadJquery(function() {
                        DOM.load.js(src, callback);
                    });
                };

            CloudCmd.PREFIX     = prefix;
            CloudCmd.PREFIX_URL = prefix + CloudFunc.apiURL;

            DOM.Files.get('config', function(error, config) {
                var options = {
                    htmlDialogs: !error && config.htmlDialogs
                };

                if (error)
                    CloudCmd.log(error);

                DOM.Dialog = new DOM.Dialog(prefix, options);
            });

            Util.exec.if(document.body.scrollIntoViewIfNeeded, func, funcBefore);
        };

        this.join                   = function(urls) {
            var prefix  = CloudCmd.PREFIX;

            if (!Array.isArray(urls))
                throw Error('urls should be array!');

            urls = urls.map(function(url) {
                return url.replace(prefix, '');
            });

            return prefix + join(urls);
        };

        this.route                   = function(path) {
            var module, file, current, msg,
                query   = path.split('/');

            if (path) {
                module      = query[0];
                module      = module.slice(1).join('');
                module      = getStrBigFirst(module);

                file        = query[1];
                current     = DOM.getCurrentByName(file);

                if (file && !current) {
                    msg = CloudFunc.formatMsg('set current file', file, 'error');
                    CloudCmd.log(msg);
                } else {
                    DOM.setCurrentFile(current);
                    CloudCmd.execFromModule(module, 'show');
                }
            }
        };

        this.logOut = function() {
            DOM.load.ajax({
                url: CloudCmd.PREFIX + '/logout',
                error: function() {
                    document.location.reload();
                }
            });
        };

        function initModules(callback) {
            Util.exec.if(CloudCmd.Key, function() {
                Key          = new CloudCmd.Key();
                CloudCmd.Key = Key;
                Key.bind();
            }, function(callback) {
                loadModule({
                    /* привязываем клавиши к функциям */
                    path    : 'key.js',
                    func    : callback
                });
            });

            Files.get('modules', function(error, modules) {
                var storageObj, mod, path,
                    STORAGE     = 'storage',
                    showLoad    = Images.show.load,

                    doBefore    = {
                        'edit'                  : showLoad,
                        'menu'                  : showLoad,
                        'storage/_filepicker'   : showLoad
                    },

                    load = function(name, path, func) {
                        var isTmpl = path === 'template';

                        loadModule({
                            name        : name,
                            funcName    : isTmpl ? 'get' : 'show',
                            path        : path,
                            dobefore    : func
                        });
                    };

                if (!modules)
                    modules = [];

                modules.forEach(function(module) {
                    var isStr = type.string(module);

                    if (isStr)
                        load(null, module, doBefore[module]);
                });

                storageObj = Util.findObjByNameInArr(modules, STORAGE),
                mod        = Util.getNamesFromObjArray(storageObj);

                mod.forEach(function(name) {
                    path = STORAGE + '/_' + name.toLowerCase();

                    load(name, path, doBefore[path]);
                });

                callback();
            });
        }

        function baseInit(callback) {
            var dirPath = '',
                files   = DOM.getFiles();

            /* выделяем строку с первым файлом */
            if (files)
                DOM.setCurrentFile(files[0]);

            dirPath     = DOM.getCurrentDirPath(),
            Listeners   = CloudCmd.Listeners;
            Listeners.init();

            Listeners.setOnPanel('left');
            Listeners.setOnPanel('right');

            Listeners.initKeysPanel();

            Storage.get(dirPath, function(error, data) {
                if (!data) {
                    data    = getJSONfromFileTable();
                    Storage.set(dirPath, data);
                }
            });

            callback();
        }

        this.execFromModule         = function(moduleName, funcName) {
            var args    = [].slice.call(arguments, 2),
                obj     = CloudCmd[moduleName],
                isObj   = Util.type.object(obj);

            Util.exec.if(isObj,
                function() {
                    var obj     = CloudCmd[moduleName],
                        func    = obj[funcName];

                    func.apply(null, args);
                }, obj);
        };

        this.refresh                =  function(panelParam, options, callback) {
            var panel           = panelParam || Info.panel,
                noCurrent,
                NEEDREFRESH     = true,
                path            = DOM.getCurrentDirPath(panel);

            if (options)
                noCurrent       = options.noCurrent;

            if (!callback && typeof options === 'function') {
                callback    = options;
                options     = {};
            }

            CloudCmd.loadDir({
                path        : path,
                isRefresh   : NEEDREFRESH,
                history     : false,
                panel       : panel,
                noCurrent   : noCurrent
            }, callback);
        };

        /**
         * Функция загружает json-данные о Файловой Системе
         * через ajax-запрос.
         * @param path - каталог для чтения
         * @param options
         * { refresh, history } - необходимость обновить данные о каталоге
         * @param panel
         * @param callback
         *
         */
        function ajaxLoad(path, options, panel, callback) {
            var create = function(error, json) {
                var RESTful     = DOM.RESTful,
                    name        = Info.name,
                    obj         = Util.json.parse(json),
                    isRefresh   = options.refresh,
                    noCurrent   = options.noCurrent;

                if (!isRefresh && json)
                    createFileTable(obj, panel, options, callback);
                else
                    RESTful.read(path, 'json', function(error, obj) {
                        if (!error) {
                            Storage.set(path, obj);

                            createFileTable(obj, panel, options, function() {
                                var current;

                                if (isRefresh && !noCurrent) {
                                    current = DOM.getCurrentByName(name);
                                    DOM.setCurrentFile(current);
                                }

                                Util.exec(callback);
                            });
                        }
                    });
            };

            if (!options)
                options    = {};

            CloudCmd.log('reading dir: "' + path + '";');

            Files.get('config', function(error, config) {
                var dirStorage,
                    Dialog = DOM.Dialog;

                if (error)
                    Dialog.alert(TITLE, error);
                else
                    dirStorage = config.dirStorage;

                if (dirStorage)
                    Storage.get(path, create);
                else
                    create();
            });
        }

        /**
         * Функция строит файловую таблицу
         * @param json  - данные о файлах
         * @param panelParam
         * @param history
         * @param callback
         */
        function createFileTable(json, panelParam, options, callback) {
            var history     = options.history,
                noCurrent   = options.noCurrent,
                names       = ['file', 'path', 'link', 'pathLink'];

            Files.get(names, function(error, templFile, templPath, templLink, templPathLink) {
                var childNodes, i,
                    Dialog      = DOM.Dialog,
                    current,
                    panel       = panelParam || DOM.getPanel(),

                    dir         = Info.dir,
                    name        = Info.name;

                if (error) {
                    Dialog.alert(TITLE, error.responseText);
                } else {
                    childNodes  = panel.childNodes;
                    i           = childNodes.length;

                    while (i--)
                        panel.removeChild(panel.lastChild);

                    panel.innerHTML = CloudFunc.buildFromJSON({
                        data        : json,
                        id          : panel.id,
                        prefix      : CloudCmd.PREFIX,
                        template    : {
                            file        : templFile,
                            path        : templPath,
                            pathLink    : templPathLink,
                            link        : templLink
                        }
                    });

                    Listeners.setOnPanel(panel);

                    if (!noCurrent) {
                        if (name === '..' && dir !== '/')
                            current = DOM.getCurrentByName(dir);

                        if (!current)
                            current = DOM.getFiles(panel)[0];

                        DOM.setCurrentFile(current, {
                            history: history
                        });
                    }

                    Util.exec(callback);
                }
            });
        }

        /**
         * Функция генерирует JSON из html-таблицы файлов и
         * используеться при первом заходе в корень
         */
        function getJSONfromFileTable() {
            var name, size, owner, mode, ret,
                path        = DOM.getCurrentDirPath(),
                infoFiles   = Info.files || [],

                fileTable   = {
                    path    : path,
                    files   : []
                },

                files       = fileTable.files;

            [].forEach.call(infoFiles, function(current) {
                name        = DOM.getCurrentName(current);
                size        = DOM.getCurrentSize(current);
                owner       = DOM.getCurrentOwner(current);
                mode        = DOM.getCurrentMode(current);

                if (name !== '..')
                    files.push({
                        name    : name,
                        size    : size,
                        mode    : mode,
                        owner   : owner
                    });
            });

            ret = Util.json.stringify(fileTable);

            return ret;
        }

        this.goToParentDir          = function() {
            var path        = Info.dirPath,
                dir         = Info.dir,
                parentPath  = Info.parentDirPath;

            if (path !== parentPath) {
                path    = parentPath;

                CloudCmd.loadDir({
                    path: path,
                }, function() {
                    var current,
                        panel   = Info.panel;

                    current = DOM.getCurrentByName(dir);

                    if (!current)
                        current = DOM.getFiles(panel)[0];

                    DOM.setCurrentFile(current, {
                        history: history
                    });
                });
            }
        };

        function getStrBigFirst(str) {
            var first;

            if (!str)
                throw Error('str could not be empty!');

            first   = str[0].toUpperCase();
            str     = first + str.slice(1);

            return str;
        }

    }
})(this, Util, DOM, CloudFunc);
<commit_msg>chore(client) "," -> ";"<commit_after>var Util, DOM, CloudFunc, join;

(function(scope, Util, DOM, CloudFunc) {
    'use strict';

    scope.CloudCmd = new CloudCmdProto(Util, DOM, CloudFunc);

    function CloudCmdProto(Util, DOM, CloudFunc) {
        var Key,
            Debug,
            log                     = function(str) {
                if (Debug)
                    console.log(str);
            },

            TITLE,
            Listeners,
            Files                   = DOM.Files,
            Images                  = DOM.Images,
            Info                    = DOM.CurrentInfo,
            CloudCmd                = this,
            Storage                 = DOM.Storage,
            type                    = Util.type;

        this.log                    = log;
        this.PREFIX                 = '';
        this.PREFIX_URL             = '';
        this.LIBDIR                 = '/lib/';
        this.LIBDIRCLIENT           = '/lib/client/';
        this.MIN_ONE_PANEL_WIDTH    = 1155;
        this.HOST                   = location.origin ||
                                      location.protocol + '//' + location.host;

        this.TITLE                  = 'Cloud Commander';

        TITLE                       = this.TITLE;

        log.enable     = function() {
            Debug = true;
        };

        log.disable    = function() {
            Debug = false;
        };

        /**
         * Функция привязываеться ко всем ссылкам и
         *  загружает содержимое каталогов
         *
         * @param params - {
         *          paramLink - ссылка
         *          needRefresh - необходимость обязательной загрузки данных с сервера
         *          panel
         *      }
         * @param callback
         */
        this.loadDir                = function(params, callback) {
            var imgPosition, panelChanged,
                noCurrent,
                isRefresh, panel, history,
                p               = params;

            if (params) {
                isRefresh       = p.isRefresh;
                panel           = p.panel;
                history         = p.history;
                noCurrent       = p.noCurrent;
            }

            if (!noCurrent)
                if (panel && panel !== Info.panel) {
                    DOM.changePanel();
                    panelChanged = true;
                }

            if (panelChanged || isRefresh || !history)
                imgPosition = 'top';

            Images.show.load(imgPosition, panel);

            /* загружаем содержимое каталога */
            ajaxLoad(p.path, {
                refresh     : isRefresh,
                history     : history,
                noCurrent   : noCurrent
            }, panel, callback);
        };

        /**
         * function load modules
         * @pParams = {name, path, func, dobefore, arg}
         */
        function loadModule(params) {
            var name, path, func, doBefore,
                funcName, isContain;

            if (params) {
                name        = params.name,
                path        = params.path,
                func        = params.func,
                funcName    = params.funcName,
                doBefore    = params.dobefore;

                if (path && !name) {
                    name = getStrBigFirst(path);
                    name = name.replace(/.js$/, '');
                }

                isContain   = /\.js/.test(path);

                if (!isContain)
                    path += '.js';

                if (!CloudCmd[name]) {
                    CloudCmd[name] = function() {
                        var prefix      = CloudCmd.PREFIX,
                            pathFull    = prefix + CloudCmd.LIBDIRCLIENT + path,
                            args        = arguments;

                        Util.exec(doBefore);

                        return DOM.load.js(pathFull, func ||
                            function(error) {
                                var Proto = CloudCmd[name];

                                if (!error && type.function(Proto))
                                    CloudCmd[name] = applyConstructor(Proto, args);
                            });
                    };

                    CloudCmd[name][funcName] = CloudCmd[name];
                }
            }
        }

        /*
         * apply arguemnts to constructor
         *
         * @param constructor
         * @param args
         */
        function applyConstructor(constructor, args) {
            var F = function () {
                return constructor.apply(this, args);
            };

            F.prototype = constructor.prototype;
            return new F();
        }

        /** Конструктор CloudClient, который
         * выполняет весь функционал по
         * инициализации
         */
        this.init                    = function(prefix) {
            var func        = function() {
                    Util.exec.series([
                        initModules,
                        baseInit,
                        function() {
                            CloudCmd.route(location.hash);
                        }
                    ]);
                },

                funcBefore  = function(callback) {
                    var src = prefix + '/join:' + [
                            CloudCmd.LIBDIRCLIENT + 'polyfill.js',
                            '/modules/domtokenlist-shim/dist/domtokenlist.min.js',
                        ].join(':');

                    DOM.loadJquery(function() {
                        DOM.load.js(src, callback);
                    });
                };

            CloudCmd.PREFIX     = prefix;
            CloudCmd.PREFIX_URL = prefix + CloudFunc.apiURL;

            DOM.Files.get('config', function(error, config) {
                var options = {
                    htmlDialogs: !error && config.htmlDialogs
                };

                if (error)
                    CloudCmd.log(error);

                DOM.Dialog = new DOM.Dialog(prefix, options);
            });

            Util.exec.if(document.body.scrollIntoViewIfNeeded, func, funcBefore);
        };

        this.join                   = function(urls) {
            var prefix  = CloudCmd.PREFIX;

            if (!Array.isArray(urls))
                throw Error('urls should be array!');

            urls = urls.map(function(url) {
                return url.replace(prefix, '');
            });

            return prefix + join(urls);
        };

        this.route                   = function(path) {
            var module, file, current, msg,
                query   = path.split('/');

            if (path) {
                module      = query[0];
                module      = module.slice(1).join('');
                module      = getStrBigFirst(module);

                file        = query[1];
                current     = DOM.getCurrentByName(file);

                if (file && !current) {
                    msg = CloudFunc.formatMsg('set current file', file, 'error');
                    CloudCmd.log(msg);
                } else {
                    DOM.setCurrentFile(current);
                    CloudCmd.execFromModule(module, 'show');
                }
            }
        };

        this.logOut = function() {
            DOM.load.ajax({
                url: CloudCmd.PREFIX + '/logout',
                error: function() {
                    document.location.reload();
                }
            });
        };

        function initModules(callback) {
            Util.exec.if(CloudCmd.Key, function() {
                Key          = new CloudCmd.Key();
                CloudCmd.Key = Key;
                Key.bind();
            }, function(callback) {
                loadModule({
                    /* привязываем клавиши к функциям */
                    path    : 'key.js',
                    func    : callback
                });
            });

            Files.get('modules', function(error, modules) {
                var storageObj, mod, path,
                    STORAGE     = 'storage',
                    showLoad    = Images.show.load,

                    doBefore    = {
                        'edit'                  : showLoad,
                        'menu'                  : showLoad,
                        'storage/_filepicker'   : showLoad
                    },

                    load = function(name, path, func) {
                        var isTmpl = path === 'template';

                        loadModule({
                            name        : name,
                            funcName    : isTmpl ? 'get' : 'show',
                            path        : path,
                            dobefore    : func
                        });
                    };

                if (!modules)
                    modules = [];

                modules.forEach(function(module) {
                    var isStr = type.string(module);

                    if (isStr)
                        load(null, module, doBefore[module]);
                });

                storageObj = Util.findObjByNameInArr(modules, STORAGE);
                mod        = Util.getNamesFromObjArray(storageObj);

                mod.forEach(function(name) {
                    path = STORAGE + '/_' + name.toLowerCase();

                    load(name, path, doBefore[path]);
                });

                callback();
            });
        }

        function baseInit(callback) {
            var dirPath = '',
                files   = DOM.getFiles();

            /* выделяем строку с первым файлом */
            if (files)
                DOM.setCurrentFile(files[0]);

            dirPath     = DOM.getCurrentDirPath(),
            Listeners   = CloudCmd.Listeners;
            Listeners.init();

            Listeners.setOnPanel('left');
            Listeners.setOnPanel('right');

            Listeners.initKeysPanel();

            Storage.get(dirPath, function(error, data) {
                if (!data) {
                    data    = getJSONfromFileTable();
                    Storage.set(dirPath, data);
                }
            });

            callback();
        }

        this.execFromModule         = function(moduleName, funcName) {
            var args    = [].slice.call(arguments, 2),
                obj     = CloudCmd[moduleName],
                isObj   = Util.type.object(obj);

            Util.exec.if(isObj,
                function() {
                    var obj     = CloudCmd[moduleName],
                        func    = obj[funcName];

                    func.apply(null, args);
                }, obj);
        };

        this.refresh                =  function(panelParam, options, callback) {
            var panel           = panelParam || Info.panel,
                noCurrent,
                NEEDREFRESH     = true,
                path            = DOM.getCurrentDirPath(panel);

            if (options)
                noCurrent       = options.noCurrent;

            if (!callback && typeof options === 'function') {
                callback    = options;
                options     = {};
            }

            CloudCmd.loadDir({
                path        : path,
                isRefresh   : NEEDREFRESH,
                history     : false,
                panel       : panel,
                noCurrent   : noCurrent
            }, callback);
        };

        /**
         * Функция загружает json-данные о Файловой Системе
         * через ajax-запрос.
         * @param path - каталог для чтения
         * @param options
         * { refresh, history } - необходимость обновить данные о каталоге
         * @param panel
         * @param callback
         *
         */
        function ajaxLoad(path, options, panel, callback) {
            var create = function(error, json) {
                var RESTful     = DOM.RESTful,
                    name        = Info.name,
                    obj         = Util.json.parse(json),
                    isRefresh   = options.refresh,
                    noCurrent   = options.noCurrent;

                if (!isRefresh && json)
                    createFileTable(obj, panel, options, callback);
                else
                    RESTful.read(path, 'json', function(error, obj) {
                        if (!error) {
                            Storage.set(path, obj);

                            createFileTable(obj, panel, options, function() {
                                var current;

                                if (isRefresh && !noCurrent) {
                                    current = DOM.getCurrentByName(name);
                                    DOM.setCurrentFile(current);
                                }

                                Util.exec(callback);
                            });
                        }
                    });
            };

            if (!options)
                options    = {};

            CloudCmd.log('reading dir: "' + path + '";');

            Files.get('config', function(error, config) {
                var dirStorage,
                    Dialog = DOM.Dialog;

                if (error)
                    Dialog.alert(TITLE, error);
                else
                    dirStorage = config.dirStorage;

                if (dirStorage)
                    Storage.get(path, create);
                else
                    create();
            });
        }

        /**
         * Функция строит файловую таблицу
         * @param json  - данные о файлах
         * @param panelParam
         * @param history
         * @param callback
         */
        function createFileTable(json, panelParam, options, callback) {
            var history     = options.history,
                noCurrent   = options.noCurrent,
                names       = ['file', 'path', 'link', 'pathLink'];

            Files.get(names, function(error, templFile, templPath, templLink, templPathLink) {
                var childNodes, i,
                    Dialog      = DOM.Dialog,
                    current,
                    panel       = panelParam || DOM.getPanel(),

                    dir         = Info.dir,
                    name        = Info.name;

                if (error) {
                    Dialog.alert(TITLE, error.responseText);
                } else {
                    childNodes  = panel.childNodes;
                    i           = childNodes.length;

                    while (i--)
                        panel.removeChild(panel.lastChild);

                    panel.innerHTML = CloudFunc.buildFromJSON({
                        data        : json,
                        id          : panel.id,
                        prefix      : CloudCmd.PREFIX,
                        template    : {
                            file        : templFile,
                            path        : templPath,
                            pathLink    : templPathLink,
                            link        : templLink
                        }
                    });

                    Listeners.setOnPanel(panel);

                    if (!noCurrent) {
                        if (name === '..' && dir !== '/')
                            current = DOM.getCurrentByName(dir);

                        if (!current)
                            current = DOM.getFiles(panel)[0];

                        DOM.setCurrentFile(current, {
                            history: history
                        });
                    }

                    Util.exec(callback);
                }
            });
        }

        /**
         * Функция генерирует JSON из html-таблицы файлов и
         * используеться при первом заходе в корень
         */
        function getJSONfromFileTable() {
            var name, size, owner, mode, ret,
                path        = DOM.getCurrentDirPath(),
                infoFiles   = Info.files || [],

                fileTable   = {
                    path    : path,
                    files   : []
                },

                files       = fileTable.files;

            [].forEach.call(infoFiles, function(current) {
                name        = DOM.getCurrentName(current);
                size        = DOM.getCurrentSize(current);
                owner       = DOM.getCurrentOwner(current);
                mode        = DOM.getCurrentMode(current);

                if (name !== '..')
                    files.push({
                        name    : name,
                        size    : size,
                        mode    : mode,
                        owner   : owner
                    });
            });

            ret = Util.json.stringify(fileTable);

            return ret;
        }

        this.goToParentDir          = function() {
            var path        = Info.dirPath,
                dir         = Info.dir,
                parentPath  = Info.parentDirPath;

            if (path !== parentPath) {
                path    = parentPath;

                CloudCmd.loadDir({
                    path: path,
                }, function() {
                    var current,
                        panel   = Info.panel;

                    current = DOM.getCurrentByName(dir);

                    if (!current)
                        current = DOM.getFiles(panel)[0];

                    DOM.setCurrentFile(current, {
                        history: history
                    });
                });
            }
        };

        function getStrBigFirst(str) {
            var first;

            if (!str)
                throw Error('str could not be empty!');

            first   = str[0].toUpperCase();
            str     = first + str.slice(1);

            return str;
        }

    }
})(this, Util, DOM, CloudFunc);
<|endoftext|>


<commit_before>/**
 * client.js
 * Google Data API client
 *
 * @author Amir Malik
 */

var querystring = require('querystring'),
    OAuth       = require('oauth').OAuth;

var Feed = require('./feed').Feed;

var GDClient = function(consumer_key, consumer_secret) {
  this.consumer_key = consumer_key;
  this.consumer_secret = consumer_secret;
  this.access_token = undefined;
  this.access_token_secret = undefined;
  this.oauth = new OAuth('https://www.google.com/accounts/OAuthGetRequestToken', 'https://www.google.com/accounts/OAuthGetAccessToken', consumer_key, consumer_secret, '1.0', null, 'HMAC-SHA1');
  this.oauth._headers['GData-Version'] = '2.0'; // HACK
};

GDClient.prototype.getAccessToken = function(email, password, cb) {
  if(!email || !password)
    return cb(new Error('getAccessToken(email, password, cb) expected'));

  cb(new Error('TODO'));
};

GDClient.prototype.setAccessToken = function setAccessToken(token, token_secret) {
  this.access_token = token;
  this.access_token_secret = token_secret;
};

GDClient.prototype.get = function get(url, optargs, cb) {
  if(typeof optargs == 'function') cb = optargs, optargs = {};

  // always request JSON output instead of XML
  // TODO: try adding header: Accept: application/json to force JSON
  if(url.lastIndexOf('alt=json') == -1) {
    if(url.lastIndexOf('?') > -1) {
      url += '&alt=json';
    } else {
      url += '?alt=json';
    }
  }

  this.oauth.get(url,
                 optargs.token || this.access_token,
                 optargs.secret || this.access_token_secret,
                 function(err, data, res) {
                   if(err) {
                     cb(err);
                   } else {
                     try {
                       cb(null, new Feed(JSON.parse(data)));
                     } catch(e) {
                       cb(e);
                     }
                   }
                 });
};

exports.GDClient = GDClient;
<commit_msg>send GData-Version: 3.0 header<commit_after>/**
 * client.js
 * Google Data API client
 *
 * @author Amir Malik
 */

var querystring = require('querystring'),
    OAuth       = require('oauth').OAuth;

var Feed = require('./feed').Feed;

var GDClient = function(consumer_key, consumer_secret) {
  this.consumer_key = consumer_key;
  this.consumer_secret = consumer_secret;
  this.access_token = undefined;
  this.access_token_secret = undefined;
  this.oauth = new OAuth('https://www.google.com/accounts/OAuthGetRequestToken', 'https://www.google.com/accounts/OAuthGetAccessToken', consumer_key, consumer_secret, '1.0', null, 'HMAC-SHA1');
  this.oauth._headers['GData-Version'] = '3.0'; // HACK
};

GDClient.prototype.getAccessToken = function(email, password, cb) {
  if(!email || !password)
    return cb(new Error('getAccessToken(email, password, cb) expected'));

  cb(new Error('TODO'));
};

GDClient.prototype.setAccessToken = function setAccessToken(token, token_secret) {
  this.access_token = token;
  this.access_token_secret = token_secret;
};

GDClient.prototype.get = function get(url, optargs, cb) {
  if(typeof optargs == 'function') cb = optargs, optargs = {};

  // always request JSON output instead of XML
  // TODO: try adding header: Accept: application/json to force JSON
  if(url.lastIndexOf('alt=json') == -1) {
    if(url.lastIndexOf('?') > -1) {
      url += '&alt=json';
    } else {
      url += '?alt=json';
    }
  }

  this.oauth.get(url,
                 optargs.token || this.access_token,
                 optargs.secret || this.access_token_secret,
                 function(err, data, res) {
                   if(err) {
                     cb(err);
                   } else {
                     try {
                       cb(null, new Feed(JSON.parse(data)));
                     } catch(e) {
                       cb(e);
                     }
                   }
                 });
};

exports.GDClient = GDClient;
<|endoftext|>


<commit_before>/**
 * Created by godong on 2016. 3. 9..
 */
/*jshint browser:false*/
/**
 * Require modules
 */
var _ = require('underscore'),
  fetch = require('node-fetch'),
  logger =  require('log4js').getLogger('sole-node'),
  QueryString = require('querystring'),
  Query = require('./query');

/**
 * Solr Node Client
 *
 * @constructor
 *
 * @param {Object} options
 * @param {String} [options.host] - host address of Solr server
 * @param {Number|String} [options.port] - port number of Solr server
 * @param {String} [options.core] - client core name
 * @param {String} [options.rootPath] - solr root path
 * @param {String} [options.protocol] - request protocol ('http'|'https')
 * @param {String} [options.debugLevel] - log4js debug level ('ALL'|'DEBUG'|'INFO'|'ERROR'|...)
 */
function Client(options) {
  this.options = {
    host: options.host || '127.0.0.1',
    port: options.port || '8983',
    core: options.core || '',
    rootPath: options.rootPath || 'solr',
    protocol: options.protocol || 'http'
  };

  if (options.debugLevel) {
    logger.setLevel(options.debugLevel);
  }

  // Path Constants List
  this.SEARCH_PATH = 'select';
  this.TERMS_PATH = 'terms';
  this.SPELL_PATH = 'spell';
  this.MLT_PATH = 'mlt';
  this.UPDATE_PATH = 'update';
  this.UPDATE_EXTRACT_PATH = 'update/extract';
  this.PING_PATH = 'admin/ping';
}

/**
 * Make host url
 * @private
 *
 * @param {String} protocol - protocol ('http'|'https')
 * @param {String} host - host address
 * @param {String|Number} port - port number
 *
 * @returns {String}
 */
Client.prototype._makeHostUrl = function(protocol, host, port) {
  if (port) {
    return protocol + '://' + host + ':' + port;
  } else {
    return protocol + '://' + host;
  }
};

/**
 * Request get
 *
 * @param {String} path - target path
 * @param {Object|String} query - query
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {undefined|Promise} - When there's no callback function it returns a PromiseŰ
 */
Client.prototype._requestGet = function(path, query, finalCallback) {
  var params, options, requestPrefixUrl, requestFullPath;

  if (query instanceof Query) {
    params = query.toString();
  } else if (_.isString(query)) {
    params = query;
  } else {
    params = 'q=*:*';
  }
  requestPrefixUrl = this._makeHostUrl(this.options.protocol, this.options.host, this.options.port);
  requestPrefixUrl += '/' + [this.options.rootPath, this.options.core, path].join('/');

  requestFullPath = requestPrefixUrl + '?' + params;

  logger.debug('[_requestGet] requestFullPath: ', requestFullPath);

  options = {
    method: 'GET',
    headers: {
      'accept' : 'application/json; charset=utf-8'
    }
  };
  var result = fetch(requestFullPath, options)
    .then(function(res) {
      if (res.status !== 200) {
        logger.error(res);
        throw new Error('Solr server error: ' + res.status);
      } else {
        return res.json();
      }
    });
  if (typeof finalCallback === 'function') {
    result
      .then(function(json) {
        finalCallback(null,json);
      })
      .catch(function (err) {
        finalCallback(err.message);
      });
  } else {
    return result;
  }
};

/**
 * Request post
 *
 * @param {String} path - target path
 * @param {Object} data - json data
 * @param {Object|String} urlOptions - url options
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {undefined|Promise} - When there's no callback function it returns a PromiseŰ
 */
Client.prototype._requestPost = function(path, data, urlOptions, finalCallback) {
  var params, options, requestPrefixUrl, requestFullPath;

  if (_.isString(urlOptions)) {
    params = urlOptions;
  } else if (_.isObject(urlOptions)) {
    params = QueryString.stringify(urlOptions);
  } else {
    params = '';
  }

  requestPrefixUrl = this._makeHostUrl(this.options.protocol, this.options.host, this.options.port);
  requestPrefixUrl += '/' + [this.options.rootPath, this.options.core, path].join('/');

  requestFullPath = requestPrefixUrl + '?' + params;

  logger.debug('[_requestPost] requestFullPath: ', requestFullPath);
  logger.debug('[_requestPost] data: ', data);

  options = {
    method: 'POST',
    body: JSON.stringify(data),
    headers: {
      'accept' : 'application/json; charset=utf-8',
      'content-type' : 'application/json; charset=utf-8'
    }
  };
  var result = fetch(requestFullPath, options)
    .then(function(res) {
      if (res.status !== 200) {
        throw new Error('Solr server error: ' + res.status);
      } else {
        return res.json();
      }
    });

  if (typeof finalCallback === 'function') {
    result
      .then(function(json) {
        finalCallback(null,json);
      })
      .catch(function (err) {
        finalCallback(err.message);
      });
  } else {
    return result;
  }
};

/**
 * Make Query instance and return
 *
 * @returns {Object}
 */
Client.prototype.query = function() {
  return new Query();
};

/**
 * Search
 *
 * @param {Object|String} query
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.search = function(query, finalCallback) {
  if (typeof finalCallback === 'function') {
    this._requestGet(this.SEARCH_PATH, query, finalCallback);
  } else {
    return this._requestGet(this.SEARCH_PATH, query);
  }
};
/**
 * Terms
 *
 * @param {Object|String} query
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.terms = function(query, finalCallback) {
  if (typeof finalCallback === 'function') {
    this._requestGet(this.TERMS_PATH, query, finalCallback);
  } else {
    return this._requestGet(this.TERMS_PATH, query);
  }
};

/**
 * Mlt
 *
 * @param {Object|String} query
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.mlt = function(query, finalCallback) {
  if (typeof finalCallback === 'function') {
    this._requestGet(this.MLT_PATH, query, finalCallback);
  } else {
    return this._requestGet(this.MLT_PATH, query);
  }
};

/**
 * Spell
 *
 * @param {Object|String} query
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.spell = function(query, finalCallback) {
  if (typeof finalCallback === 'function') {
    this._requestGet(this.SPELL_PATH, query, finalCallback);
  } else {
    return this._requestGet(this.SPELL_PATH, query);
  }
};

/**
 * Update
 *
 * @param {Object} data - json data
 * @param {Object|Function} [options] - update options
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.update = function(data, options, finalCallback) {
  var bodyData;
  if (arguments.length < 3 && _.isFunction(options)) {
    finalCallback = options;
    options = { commit: true }; // 'commit:true' option is default
  }
  bodyData = {
    add: {
      doc: data,
      overwrite: true
    }
  };
  if (typeof finalCallback === 'function') {
    this._requestPost(this.UPDATE_PATH, bodyData, options, finalCallback);
  } else {
    return this._requestPost(this.UPDATE_PATH, bodyData, options);
  }
};

/**
 * Update Extract (files to be indexed via Tika using stream.* param)
 *
 * @param {Object|Function} [options] - update options
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.updateExtract = function(options, finalCallback) {
  var bodyData;
  if (arguments.length < 2 && _.isFunction(options)) {
    finalCallback = options;
    options = { commit: true }; // 'commit:true' option is default
  }
  bodyData = {
    add: {
      doc: null,
      overwrite: true,
      wt: "json"
    }
  };
  if (typeof finalCallback === 'function') {
    this._requestPost(this.UPDATE_EXTRACT_PATH, bodyData, options, finalCallback);
  } else {
    return this._requestPost(this.UPDATE_EXTRACT_PATH, bodyData, options);
  }
};

/**
 * Delete
 *
 * @param {String|Object} query - query
 * @param {Object|Function} [options] - delete options
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.delete = function(query, options, finalCallback) {
  var bodyData, bodyQuery;
  if (arguments.length < 3 && _.isFunction(options)) {
    finalCallback = options;
    options = { commit: true }; // 'commit:true' option is default
  }

  if (_.isString(query)) {
    bodyQuery = query;
  } else if (_.isObject(query)) {
    bodyQuery = QueryString.stringify(query, ' AND ', ':');
  } else {
    bodyQuery = '';
  }

  bodyData = {
    'delete': {
      query: bodyQuery
    }
  };

  if (typeof finalCallback === 'function') {
    this._requestPost(this.UPDATE_PATH, bodyData, options, finalCallback);
  } else {
    return this._requestPost(this.UPDATE_PATH, bodyData, options);
  }
};

/**
 * Ping
 *
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.ping = function(finalCallback) {
  if (typeof finalCallback === 'function') {
    this._requestGet(this.PING_PATH, '', finalCallback);
  } else {
    return this._requestGet(this.PING_PATH, '');
  }
};

/**
 * Commit
 *
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.commit = function(finalCallback) {
  if (typeof finalCallback === 'function') {
    this._requestPost(this.UPDATE_PATH, {}, {commit: true}, finalCallback);
  } else {
    return this._requestPost(this.UPDATE_PATH, {}, {commit: true});
  }
};

/**
 * SoftCommit
 *
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.softCommit = function(finalCallback) {
  if (typeof finalCallback === 'function') {
    this._requestPost(this.UPDATE_PATH, {}, {softCommit: true}, finalCallback);
  } else {
    return this._requestPost(this.UPDATE_PATH, {}, {softCommit: true});
  }
};

module.exports = Client;<commit_msg>Fix per errore posizione parametro wt<commit_after>/**
 * Created by godong on 2016. 3. 9..
 */
/*jshint browser:false*/
/**
 * Require modules
 */
var _ = require('underscore'),
  fetch = require('node-fetch'),
  logger =  require('log4js').getLogger('sole-node'),
  QueryString = require('querystring'),
  Query = require('./query');

/**
 * Solr Node Client
 *
 * @constructor
 *
 * @param {Object} options
 * @param {String} [options.host] - host address of Solr server
 * @param {Number|String} [options.port] - port number of Solr server
 * @param {String} [options.core] - client core name
 * @param {String} [options.rootPath] - solr root path
 * @param {String} [options.protocol] - request protocol ('http'|'https')
 * @param {String} [options.debugLevel] - log4js debug level ('ALL'|'DEBUG'|'INFO'|'ERROR'|...)
 */
function Client(options) {
  this.options = {
    host: options.host || '127.0.0.1',
    port: options.port || '8983',
    core: options.core || '',
    rootPath: options.rootPath || 'solr',
    protocol: options.protocol || 'http'
  };

  if (options.debugLevel) {
    logger.setLevel(options.debugLevel);
  }

  // Path Constants List
  this.SEARCH_PATH = 'select';
  this.TERMS_PATH = 'terms';
  this.SPELL_PATH = 'spell';
  this.MLT_PATH = 'mlt';
  this.UPDATE_PATH = 'update';
  this.UPDATE_EXTRACT_PATH = 'update/extract';
  this.PING_PATH = 'admin/ping';
}

/**
 * Make host url
 * @private
 *
 * @param {String} protocol - protocol ('http'|'https')
 * @param {String} host - host address
 * @param {String|Number} port - port number
 *
 * @returns {String}
 */
Client.prototype._makeHostUrl = function(protocol, host, port) {
  if (port) {
    return protocol + '://' + host + ':' + port;
  } else {
    return protocol + '://' + host;
  }
};

/**
 * Request get
 *
 * @param {String} path - target path
 * @param {Object|String} query - query
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {undefined|Promise} - When there's no callback function it returns a PromiseŰ
 */
Client.prototype._requestGet = function(path, query, finalCallback) {
  var params, options, requestPrefixUrl, requestFullPath;

  if (query instanceof Query) {
    params = query.toString();
  } else if (_.isString(query)) {
    params = query;
  } else {
    params = 'q=*:*';
  }
  requestPrefixUrl = this._makeHostUrl(this.options.protocol, this.options.host, this.options.port);
  requestPrefixUrl += '/' + [this.options.rootPath, this.options.core, path].join('/');

  requestFullPath = requestPrefixUrl + '?' + params;

  logger.debug('[_requestGet] requestFullPath: ', requestFullPath);

  options = {
    method: 'GET',
    headers: {
      'accept' : 'application/json; charset=utf-8'
    }
  };
  var result = fetch(requestFullPath, options)
    .then(function(res) {
      if (res.status !== 200) {
        logger.error(res);
        throw new Error('Solr server error: ' + res.status);
      } else {
        return res.json();
      }
    });
  if (typeof finalCallback === 'function') {
    result
      .then(function(json) {
        finalCallback(null,json);
      })
      .catch(function (err) {
        finalCallback(err.message);
      });
  } else {
    return result;
  }
};

/**
 * Request post
 *
 * @param {String} path - target path
 * @param {Object} data - json data
 * @param {Object|String} urlOptions - url options
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {undefined|Promise} - When there's no callback function it returns a PromiseŰ
 */
Client.prototype._requestPost = function(path, data, urlOptions, finalCallback) {
  var params, options, requestPrefixUrl, requestFullPath;

  if (_.isString(urlOptions)) {
    params = urlOptions;
  } else if (_.isObject(urlOptions)) {
    params = QueryString.stringify(urlOptions);
  } else {
    params = '';
  }

  requestPrefixUrl = this._makeHostUrl(this.options.protocol, this.options.host, this.options.port);
  requestPrefixUrl += '/' + [this.options.rootPath, this.options.core, path].join('/');

  requestFullPath = requestPrefixUrl + '?' + params;

  logger.debug('[_requestPost] requestFullPath: ', requestFullPath);
  logger.debug('[_requestPost] data: ', data);

  options = {
    method: 'POST',
    body: JSON.stringify(data),
    headers: {
      'accept' : 'application/json; charset=utf-8',
      'content-type' : 'application/json; charset=utf-8'
    }
  };
  var result = fetch(requestFullPath, options)
    .then(function(res) {
      if (res.status !== 200) {
        throw new Error('Solr server error: ' + res.status);
      } else {
        return res.json();
      }
    });

  if (typeof finalCallback === 'function') {
    result
      .then(function(json) {
        finalCallback(null,json);
      })
      .catch(function (err) {
        finalCallback(err.message);
      });
  } else {
    return result;
  }
};

/**
 * Make Query instance and return
 *
 * @returns {Object}
 */
Client.prototype.query = function() {
  return new Query();
};

/**
 * Search
 *
 * @param {Object|String} query
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.search = function(query, finalCallback) {
  if (typeof finalCallback === 'function') {
    this._requestGet(this.SEARCH_PATH, query, finalCallback);
  } else {
    return this._requestGet(this.SEARCH_PATH, query);
  }
};
/**
 * Terms
 *
 * @param {Object|String} query
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.terms = function(query, finalCallback) {
  if (typeof finalCallback === 'function') {
    this._requestGet(this.TERMS_PATH, query, finalCallback);
  } else {
    return this._requestGet(this.TERMS_PATH, query);
  }
};

/**
 * Mlt
 *
 * @param {Object|String} query
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.mlt = function(query, finalCallback) {
  if (typeof finalCallback === 'function') {
    this._requestGet(this.MLT_PATH, query, finalCallback);
  } else {
    return this._requestGet(this.MLT_PATH, query);
  }
};

/**
 * Spell
 *
 * @param {Object|String} query
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.spell = function(query, finalCallback) {
  if (typeof finalCallback === 'function') {
    this._requestGet(this.SPELL_PATH, query, finalCallback);
  } else {
    return this._requestGet(this.SPELL_PATH, query);
  }
};

/**
 * Update
 *
 * @param {Object} data - json data
 * @param {Object|Function} [options] - update options
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.update = function(data, options, finalCallback) {
  var bodyData;
  if (arguments.length < 3 && _.isFunction(options)) {
    finalCallback = options;
    options = { commit: true }; // 'commit:true' option is default
  }
  bodyData = {
    add: {
      doc: data,
      overwrite: true
    }
  };
  if (typeof finalCallback === 'function') {
    this._requestPost(this.UPDATE_PATH, bodyData, options, finalCallback);
  } else {
    return this._requestPost(this.UPDATE_PATH, bodyData, options);
  }
};

/**
 * Update Extract (files to be indexed via Tika using stream.* param)
 *
 * @param {Object|Function} [options] - update options
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.updateExtract = function(options, finalCallback) {
  var bodyData;
  if (arguments.length < 2 && _.isFunction(options)) {
    finalCallback = options;
    options = { commit: true }; // 'commit:true' option is default
  }
  // We need JSON response
  options.wt = "json";
  bodyData = {
    add: {
      doc: null,
      overwrite: true
    }
  };
  if (typeof finalCallback === 'function') {
    this._requestPost(this.UPDATE_EXTRACT_PATH, bodyData, options, finalCallback);
  } else {
    return this._requestPost(this.UPDATE_EXTRACT_PATH, bodyData, options);
  }
};

/**
 * Delete
 *
 * @param {String|Object} query - query
 * @param {Object|Function} [options] - delete options
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.delete = function(query, options, finalCallback) {
  var bodyData, bodyQuery;
  if (arguments.length < 3 && _.isFunction(options)) {
    finalCallback = options;
    options = { commit: true }; // 'commit:true' option is default
  }

  if (_.isString(query)) {
    bodyQuery = query;
  } else if (_.isObject(query)) {
    bodyQuery = QueryString.stringify(query, ' AND ', ':');
  } else {
    bodyQuery = '';
  }

  bodyData = {
    'delete': {
      query: bodyQuery
    }
  };

  if (typeof finalCallback === 'function') {
    this._requestPost(this.UPDATE_PATH, bodyData, options, finalCallback);
  } else {
    return this._requestPost(this.UPDATE_PATH, bodyData, options);
  }
};

/**
 * Ping
 *
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.ping = function(finalCallback) {
  if (typeof finalCallback === 'function') {
    this._requestGet(this.PING_PATH, '', finalCallback);
  } else {
    return this._requestGet(this.PING_PATH, '');
  }
};

/**
 * Commit
 *
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.commit = function(finalCallback) {
  if (typeof finalCallback === 'function') {
    this._requestPost(this.UPDATE_PATH, {}, {commit: true}, finalCallback);
  } else {
    return this._requestPost(this.UPDATE_PATH, {}, {commit: true});
  }
};

/**
 * SoftCommit
 *
 * @param {Function} finalCallback - (err, result)
 *
 * @returns {Undefined|Promise}
 */
Client.prototype.softCommit = function(finalCallback) {
  if (typeof finalCallback === 'function') {
    this._requestPost(this.UPDATE_PATH, {}, {softCommit: true}, finalCallback);
  } else {
    return this._requestPost(this.UPDATE_PATH, {}, {softCommit: true});
  }
};

module.exports = Client;<|endoftext|>


<commit_before>describe('the stack spec', () => {
  it('shows the infrastructure works', () => {
    true.should.be.true();
  });

  const makeStack = () => {
    let size = 0;

    return {
      pop: () => {},
      push: () => size++,
      isEmpty: () => size === 0,
      size: () => size
    };
  };

  let stack;

  describe('a stack should', () => {
    beforeEach(() => {
      stack = makeStack();
    });

    it('start empty', () => {
      stack.isEmpty().should.be.true();
    });

    it('start with stack size 0', () => {
      stack.size().should.equal(0);
    });

    it('not be empty when pushed', () => {
      stack.push();
      stack.isEmpty().should.be.false();
    });

    it('leave stack size 1 when pushed', () => {
      stack.push();
      stack.size().should.equal(1);
    });

    it('leave stack empty when pushed and popped', () => {
      stack.push();
      stack.pop();
      stack.isEmpty().should.be.true();
    });

    it('leave stack size 0 when pushed and popped');

    it('overflow');

    it('underflow');

    it('pop the same one pushed');

    it('pop the same two pushed');

    it('accept only positive capacity');
  });
}
);
<commit_msg>(1) - pass the tests<commit_after>describe('the stack spec', () => {
  it('shows the infrastructure works', () => {
    true.should.be.true();
  });

  const makeStack = () => {
    let size = 0;

    return {
      pop: () => size--,
      push: () => size++,
      isEmpty: () => size === 0,
      size: () => size
    };
  };

  let stack;

  describe('a stack should', () => {
    beforeEach(() => {
      stack = makeStack();
    });

    it('start empty', () => {
      stack.isEmpty().should.be.true();
    });

    it('start with stack size 0', () => {
      stack.size().should.equal(0);
    });

    it('not be empty when pushed', () => {
      stack.push();
      stack.isEmpty().should.be.false();
    });

    it('leave stack size 1 when pushed', () => {
      stack.push();
      stack.size().should.equal(1);
    });

    it('leave stack empty when pushed and popped', () => {
      stack.push();
      stack.pop();
      stack.isEmpty().should.be.true();
    });

    it('leave stack size 0 when pushed and popped');

    it('overflow');

    it('underflow');

    it('pop the same one pushed');

    it('pop the same two pushed');

    it('accept only positive capacity');
  });
}
);
<|endoftext|>