<commit_before>'use strict';

var util = require('util'),
    EventEmitter = require('events').EventEmitter,
    Docker = require('dockerode'),
    Promise = require('bluebird'),
    uuid = require('uuid'),
    debug = require('debug')('docker-runner');

var DockerExec = function (options) {

    // linux
    options = options ||  {
        socketPath: '/var/run/docker.sock'
    };

    this.docker = new Docker(options);

    this.container = null;
};

util.inherits(DockerExec, EventEmitter);

/**
 * Creates a new docker container
 */
DockerExec.prototype.createContainer = function (options) {
    debug('create a new container');

    var docker = this.docker;
    return new Promise(function (resolve, reject) {
        docker.createContainer(options, function handler(err, container) {
            if (err) {
                reject(err);
            } else {
                resolve(container);
            }
        });
    });
};

/**
 * attaches a stream to a docker container
 */
DockerExec.prototype.attachContainer = function (container) {
    debug('attach to a container');

    var self = this;

    var attach_opts = {
        stream: true,
        stdin: true,
        stdout: true,
        stderr: true
    };

    return new Promise(function (resolve, reject) {
        container.attach(attach_opts, function handler(err, stream) {
            if (err) {
                reject(err);
            } else {

                // attach stream to stdout
                // stream.pipe(process.stdout);

                /*stream.on('data', function(data){
                    debug(data.toString('utf8'));
                });*/

                self.emit('container:attach');
                resolve(stream);
            }
        });
    });
};

/**
 * starts a docker container
 */
DockerExec.prototype.startContainer = function (container) {
    debug('start a new container');

    var self = this;

    return new Promise(function (resolve, reject) {
        container.start({}, function handler(err, data) {
            if (err) {
                reject(err);
            } else {
                self.emit('container:start');
                resolve(data);
            }
        });
    });
};

/**
 * register for container end
 */
DockerExec.prototype.waitContainer = function (container) {
    debug('register wait event for a new container');

    var self = this;
    container.wait(function handler(err) {
        if (err) {
            self.emit('error', err);
            self.emit('container:stop');
            debug(err);
        } else {
            // emit stream end event;
            self.emit('container:stop');
        }
    });

};

DockerExec.prototype.pullContainer = function (image) {
    debug('download operating system');

    var docker = this.docker;

    return new Promise(function (resolve, reject) {
        docker.pull(image, function (err, stream) {
            if(err) {
                reject(err);
            } else {
                resolve();
            }
        });
    });
};

DockerExec.prototype.streamEnd = function () {
    if (this.stream) {
        this.stream.end();
    }
};

/*
 * Starts a new docker container
 */
DockerExec.prototype.start = function () {
    debug('start a new container');

    var optsc = {
        'Hostname': '',
        'User': '',
        'AttachStdin': true,
        'AttachStdout': true,
        'AttachStderr': true,
        'Tty': true,
        'OpenStdin': true,
        'StdinOnce': false,
        'Env': null,
        'Cmd': ['bash'], // run a bash shell
        'Dns': ['8.8.8.8', '8.8.4.4'], // use google dns
        'Image': 'ubuntu:14.04', // TODO make os configurable
        'Volumes': {},
        'VolumesFrom': ''
    };

    var self = this;

    return new Promise(function (resolve, reject) {
        console.log('prepare new container');

        // attach a volume to docker to copy the files afterwards
        self.pullContainer(optsc.Image).then(function() {
            return self.createContainer(optsc);
        }).then(function (container) {
            self.container = container;
            return self.attachContainer(self.container);
        }).then(function (stream) {
            self.stream = stream;
            return self.startContainer(self.container);
        }).then(function () {
            self.waitContainer(self.container);
        }).then(function () {
            console.log('container ready');
            resolve(self.stream);
        }).
        catch(function (err) {
            console.log(err);
            reject(err);
        });
    });
};

/**
 * execute one command
 * @param command a cli command like "apt-get update\n"
 */
DockerExec.prototype.run = function (command) {
    debug('run + ' + command);

    // generate process id
    var id = uuid.v4();

    // add exit code to command
    var cmd2 = command + ';echo exit task ' + id + ' $?\n';

    var self = this;
    return new Promise(function (resolve) {
        self.stream.write(cmd2);

        // wait for exit from process
        self.stream.on('data', function (data) {
            // wait for exit event
            // make abort condition with var exit = 'task ' + id;
            var match = data.toString('utf8').match(/((;echo\s)?exit)/i);
            if (match && match.length > 0 && match[0] === 'exit') {
                // TODO use buffer of 10 events
                // TODO make more robust
                // console.log('detected exit' + JSON.stringify(match));
                resolve();
            }
        });
    });
};

DockerExec.prototype.removeContainer = function (container) {
    return new Promise(function (resolve, reject) {
        container.remove(function handler(err) {
            if (err) {
                reject(err);
            } else {
                resolve();
            }
        });
    });
};

DockerExec.prototype.killContainer = function (container) {
    return new Promise(function (resolve, reject) {
        container.kill(function handler(err) {
            if (err) {
                reject(err);
            } else {
                resolve();
            }
        });
    });
};

/**
 * stops the docker container
 */
DockerExec.prototype.stop = function () {
    debug('stops the container');
    var self = this;
    var container = this.container;

    return new Promise(function (resolve, reject) {
        self.killContainer(container).then(function () {
            return self.removeContainer(container);
        }).then(function () {
            resolve();
        }).
        catch(function (err) {
            reject(err);
        });
    });
};

module.exports = DockerExec;<commit_msg>allow more options at startup<commit_after>'use strict';

var util = require('util'),
    EventEmitter = require('events').EventEmitter,
    Docker = require('dockerode'),
    Promise = require('bluebird'),
    uuid = require('uuid'),
    debug = require('debug')('docker-runner');

var DockerExec = function (options) {

    // linux
    options = options ||  {
        socketPath: '/var/run/docker.sock'
    };

    this.docker = new Docker(options);

    this.container = null;
};

util.inherits(DockerExec, EventEmitter);

/**
 * Creates a new docker container
 */
DockerExec.prototype.createContainer = function (options) {
    debug('create a new container');

    var docker = this.docker;
    return new Promise(function (resolve, reject) {
        docker.createContainer(options, function handler(err, container) {
            if (err) {
                reject(err);
            } else {
                resolve(container);
            }
        });
    });
};

/**
 * attaches a stream to a docker container
 */
DockerExec.prototype.attachContainer = function (container) {
    debug('attach to a container');

    var self = this;

    var attach_opts = {
        stream: true,
        stdin: true,
        stdout: true,
        stderr: true
    };

    return new Promise(function (resolve, reject) {
        container.attach(attach_opts, function handler(err, stream) {
            if (err) {
                reject(err);
            } else {

                // attach stream to stdout
                // stream.pipe(process.stdout);

                /*stream.on('data', function(data){
                    debug(data.toString('utf8'));
                });*/

                self.emit('container:attach');
                resolve(stream);
            }
        });
    });
};

/**
 * starts a docker container
 */
DockerExec.prototype.startContainer = function (container) {
    debug('start a new container');

    var self = this;

    return new Promise(function (resolve, reject) {
        container.start({}, function handler(err, data) {
            if (err) {
                reject(err);
            } else {
                self.emit('container:start');
                resolve(data);
            }
        });
    });
};

/**
 * register for container end
 */
DockerExec.prototype.waitContainer = function (container) {
    debug('register wait event for a new container');

    var self = this;
    container.wait(function handler(err) {
        if (err) {
            self.emit('error', err);
            self.emit('container:stop');
            debug(err);
        } else {
            // emit stream end event;
            self.emit('container:stop');
        }
    });

};

DockerExec.prototype.pullContainer = function (image) {
    debug('download operating system');

    var docker = this.docker;

    return new Promise(function (resolve, reject) {
        docker.pull(image, function (err, stream) {
            if(err) {
                reject(err);
            } else {
                resolve();
            }
        });
    });
};

DockerExec.prototype.streamEnd = function () {
    if (this.stream) {
        this.stream.end();
    }
};

/*
 * Starts a new docker container
 */
DockerExec.prototype.start = function (options) {
    debug('start a new container');

    options = options || {};

    var optsc = {
        'Hostname': '',
        'User': '',
        'AttachStdin': true,
        'AttachStdout': true,
        'AttachStderr': true,
        'Tty': true,
        'OpenStdin': true,
        'StdinOnce': false,
        'Env': null,
        'Cmd': ['bash'], // run a bash shell
        'Dns': ['8.8.8.8', '8.8.4.4'], // use google dns
        'Image': options.Image || 'ubuntu:14.04', // TODO make os configurable
        'Volumes': options.Volumes || {},
        'VolumesFrom': options.VolumesFrom || ''
    };

    var self = this;

    return new Promise(function (resolve, reject) {
        console.log('prepare new container');

        // attach a volume to docker to copy the files afterwards
        self.pullContainer(optsc.Image).then(function() {
            return self.createContainer(optsc);
        }).then(function (container) {
            self.container = container;
            return self.attachContainer(self.container);
        }).then(function (stream) {
            self.stream = stream;
            return self.startContainer(self.container);
        }).then(function () {
            self.waitContainer(self.container);
        }).then(function () {
            console.log('container ready');
            resolve(self.stream);
        }).
        catch(function (err) {
            console.log(err);
            reject(err);
        });
    });
};

/**
 * execute one command
 * @param command a cli command like "apt-get update\n"
 */
DockerExec.prototype.run = function (command) {
    debug('run + ' + command);

    // generate process id
    var id = uuid.v4();

    // add exit code to command
    var cmd2 = command + ';echo exit task ' + id + ' $?\n';

    var self = this;
    return new Promise(function (resolve) {
        self.stream.write(cmd2);

        // wait for exit from process
        self.stream.on('data', function (data) {
            // wait for exit event
            // make abort condition with var exit = 'task ' + id;
            var match = data.toString('utf8').match(/((;echo\s)?exit)/i);
            if (match && match.length > 0 && match[0] === 'exit') {
                // TODO use buffer of 10 events
                // TODO make more robust
                // console.log('detected exit' + JSON.stringify(match));
                resolve();
            }
        });
    });
};

DockerExec.prototype.removeContainer = function (container) {
    return new Promise(function (resolve, reject) {
        container.remove(function handler(err) {
            if (err) {
                reject(err);
            } else {
                resolve();
            }
        });
    });
};

DockerExec.prototype.killContainer = function (container) {
    return new Promise(function (resolve, reject) {
        container.kill(function handler(err) {
            if (err) {
                reject(err);
            } else {
                resolve();
            }
        });
    });
};

/**
 * stops the docker container
 */
DockerExec.prototype.stop = function () {
    debug('stops the container');
    var self = this;
    var container = this.container;

    return new Promise(function (resolve, reject) {
        self.killContainer(container).then(function () {
            return self.removeContainer(container);
        }).then(function () {
            resolve();
        }).
        catch(function (err) {
            reject(err);
        });
    });
};

module.exports = DockerExec;<|endoftext|>


<commit_before>exports.read = read;

var q = require("q");
var unzip = require("./unzip");
var path = require("path");
var fs = require("fs");

var officeXmlReader = require("./office-xml-reader");
var documents = require("./documents");
var DocumentXmlReader = require("./document-xml-reader").DocumentXmlReader;
var Result = require("./results").Result;

function read(options) {
    var docxFile;
    if (options.path) {
        docxFile = unzip.unzipStream(fs.createReadStream(options.path));
    } else if (options.file) {
        docxFile = options.file;
    } else if (options.uint8Array) {
        docxFile = unzip.unzipUint8Array(options.uint8Array);
    } else {
        return q.reject(new Error("Could not find file in options"));
    }
    return q.when(docxFile, function(docxFile) {

        return q.all([
            readXmlFile(docxFile, "word/_rels/document.xml.rels"),
            readXmlFile(docxFile, "word/document.xml")
        ]).spread(function(relationshipsXml, documentXml) {
            var relationships = relationshipsXml ? readRelationships(relationshipsXml) : {};
            var reader = new DocumentXmlReader(relationships, docxFile);
            return reader.convertXmlToDocument(documentXml);
        });
    });
}

function readXmlFile(docxFile, path) {
    if (docxFile.exists(path)) {
        return docxFile.read(path, "utf-8")
            .then(officeXmlReader.read);
    } else {
        return null;
    }
}

function readRelationships(relationshipsXml) {
    var relationships = {};
    relationshipsXml.root.children.forEach(function(child) {
        if (child.name === "{http://schemas.openxmlformats.org/package/2006/relationships}:Relationship") {
            relationships[child.attributes.Id] = {
                target: child.attributes.Target
            };
        }
    });
    return relationships;
}

function parseXml(string) {
    return xmlreader.read(string);
}
<commit_msg>Remove unused function<commit_after>exports.read = read;

var q = require("q");
var unzip = require("./unzip");
var path = require("path");
var fs = require("fs");

var officeXmlReader = require("./office-xml-reader");
var documents = require("./documents");
var DocumentXmlReader = require("./document-xml-reader").DocumentXmlReader;
var Result = require("./results").Result;

function read(options) {
    var docxFile;
    if (options.path) {
        docxFile = unzip.unzipStream(fs.createReadStream(options.path));
    } else if (options.file) {
        docxFile = options.file;
    } else if (options.uint8Array) {
        docxFile = unzip.unzipUint8Array(options.uint8Array);
    } else {
        return q.reject(new Error("Could not find file in options"));
    }
    return q.when(docxFile, function(docxFile) {

        return q.all([
            readXmlFile(docxFile, "word/_rels/document.xml.rels"),
            readXmlFile(docxFile, "word/document.xml")
        ]).spread(function(relationshipsXml, documentXml) {
            var relationships = relationshipsXml ? readRelationships(relationshipsXml) : {};
            var reader = new DocumentXmlReader(relationships, docxFile);
            return reader.convertXmlToDocument(documentXml);
        });
    });
}

function readXmlFile(docxFile, path) {
    if (docxFile.exists(path)) {
        return docxFile.read(path, "utf-8")
            .then(officeXmlReader.read);
    } else {
        return null;
    }
}

function readRelationships(relationshipsXml) {
    var relationships = {};
    relationshipsXml.root.children.forEach(function(child) {
        if (child.name === "{http://schemas.openxmlformats.org/package/2006/relationships}:Relationship") {
            relationships[child.attributes.Id] = {
                target: child.attributes.Target
            };
        }
    });
    return relationships;
}
<|endoftext|>


<commit_before>var CachedPage = {
  clear: function(event) {
    event.preventDefault();
    $.ajax({
      url: this.href,
      type: 'delete',
      dataType: 'script'
    });
  }
}

$(document).ready(function() {
  $('td.actions a.clear').click(CachedPage.clear);
})<commit_msg>Commented out cached pages JS which causes JS to break in production. Concerns #299.<commit_after>/*var CachedPage = {
  clearAll: function(event) {
    event.preventDefault();
    $.ajax({
      url: this.href,
      type: 'delete',
      dataType: 'script'
    });
  }
}

$(document).ready(function() {
  $('td.actions a.clear').click(CachedPage.clearAll);
})*/<|endoftext|>


<commit_before>'use babel';

import WipAtomView from './dynapp-atom-view';
import {
  CompositeDisposable
} from 'atom';

const request = require('request')
const fs = require('fs');
const {File} = require('atom')
const {Project} = require('atom')
const path = require('path')
var editedFiles = {}
var datasourceHandeler = require('./../DatasourceHandeler.js')
var dataitemsHandeler = require('./../DataitemsHandeler.js')
var filelistHandeler = require('./../filelistHandeler.js')
var dataObjectsHandeler = require('./../DataObjectsHandeler.js')

// download only json, css, html and js
var validateFilesToDownload = function(files) {
  for (file in files.fileList) {
    if (file.indexOf('.json') != -1) {

    } else if (file.indexOf('.css') != -1) {

    } else if (file.indexOf('.html') != -1) {

    } else if (file.indexOf('.js') != -1) {

    } else {
      delete files.fileList[file];
    }
  }
  return files;
}

// add listerens for all files
var addListeners = function(){
  dataitemsHandeler.addOnDeleteListener();
  datasourceHandeler.addOnDeleteListener();
  dataObjectsHandeler.addOnDeleteListener();

  try{
    atom.workspace.observeTextEditors(function(editor){
      editor.onDidSave(function(cb){
        if(cb.path.indexOf('.files') != -1 || cb.path.indexOf('dynappconfig') != -1){
          return;
        }
          if(editedFiles[cb.path] === undefined){
            editedFiles[cb.path] = true
            var filepath = atom.project.getPaths()[0]
            var fileObject = JSON.parse(fs.readFileSync(filepath + '/.files.json', 'utf8'));

            if(cb.path.indexOf('data-source-items') != -1){
              if(fileObject.dataSources[path.basename(cb.path, '.py')] != undefined){
                console.log("making dirty")
                fileObject.dataSources[path.basename(cb.path, '.py')]['dirty'] = true
                fs.writeFile(filepath + '/.files.json', JSON.stringify(fileObject, null, 4));
              }
              else if(fileObject.dataSources[path.basename(cb.path, '.json')] != undefined){
                console.log("making dirty")
                fileObject.dataSources[path.basename(cb.path, '.json')]['dirty'] = true
                fs.writeFile(filepath + '/.files.json', JSON.stringify(fileObject, null, 4));
              }
            }
            else if(cb.path.indexOf('data-objects') != -1){
              if(fileObject.dataObjects[path.basename(cb.path, '.py')] != undefined){
                console.log("making dirty")
                fileObject.dataObjects[path.basename(cb.path, '.py')]['dirty'] = true
                fs.writeFile(filepath + '/.files.json', JSON.stringify(fileObject, null, 4));
              }
              else if(fileObject.dataObjects[path.basename(cb.path, '.json')] != undefined){
                console.log("making dirty")
                fileObject.dataObjects[path.basename(cb.path, '.json')]['dirty'] = true
                fs.writeFile(filepath + '/.files.json', JSON.stringify(fileObject, null, 4));
              }
            }
            else if(fileObject.fileList[path.basename(cb.path)] != undefined){
              console.log("making dirty")
              fileObject.fileList[path.basename(cb.path)]['dirty'] = true;
              fs.writeFile(filepath + '/.files.json', JSON.stringify(fileObject, null, 4));
            } else if(path.basename(cb.path) != 'dynappconfig.json' && path.basename(cb.path) != ".files.json"){
              console.log(path.basename(cb.path))
              dataitemsHandeler.postFile(path.basename(cb.path)).then(function(){
                atom.notifications.addInfo("Filen: " + path.basename(cb.path) + " finns nu på serven", null)
              })

            }
          }
      })
    })
  } catch(ex){}
}

// get project credentials
var getCred = function(){
  var filepath = atom.project.getPaths()[0] + '/dynappconfig.json'
  var content = fs.readFileSync(filepath, 'utf8')
  var cred = JSON.parse(content)
  return cred
}

export default {

  wipAtomView: null,
  modalPanel: null,
  subscriptions: null,

  activate(state) {
    this.wipAtomView = new WipAtomView(state.wipAtomViewState);
    this.modalPanel = atom.workspace.addModalPanel({
      item: this.wipAtomView.getElement(),
      visible: false
    });

    // Events subscribed to in atom's system can be easily cleaned up with a CompositeDisposable
    this.subscriptions = new CompositeDisposable();
    this.start()

    // Register command that toggles this view
    this.subscriptions.add(atom.commands.add('atom-workspace', {
      'dynapp-atom:downloadProject': () => this.download(),
      'dynapp-atom:createConfig': () => this.createConfig(),
      'dynapp-atom:uploadItems': () => this.uploadItems(),
      'dynapp-atom:newItem': () => this.newItem(),
      'dynapp-atom:newObject': () => this.newObject(),
      'dynapp-atom:newSource': () => this.newSource()

    }));
  },
  newSource(){
    var InputDialog = require('./../Input-dialog.js')

    var dialog = new InputDialog({
      labelText:"Filename",
      callback:function(text){
        filepath = atom.project.getPaths()[0]
        text = path.parse(text)
        text = text.name
        filepath = atom.project.getPaths()[0]
        var obj = {
          "name": "",
          "stylesheet": "",
          "dataSourceUri": "",
          "cacheSeconds": 0,
          "jtidy": false,
          "category": 2,
          "key": "",
          "cron": false
        }

        let python = "#!/usr/bin/env python \n\nimport json \n\ndef transform(logger, item, username, password, parameterMap): \n    response = {} \n    return 200, json.dumps(response)"
        var b64String = new Buffer(python).toString('base64');
        obj.stylesheet = b64String;
        obj.name = text;
        fs.writeFileSync(filepath + '/data-source-items/' + text + '.json', JSON.stringify(obj, null, 4));

        fs.writeFileSync(filepath + '/data-source-items/' + text + '.py', python, 'binary', function(err) {});
        datasourceHandeler.postFile(path.basename(text)).then(function(){
          atom.notifications.addInfo("Filen: " + path.basename(text) + " finns nu på serven", null)
        })

      }
    });

    dialog.attach()
  },
  newObject(){
    var InputDialog = require('./../Input-dialog.js')

    var dialog = new InputDialog({
      labelText:"Filename",
      callback:function(text){
        filepath = atom.project.getPaths()[0]
        text = path.parse(text)
        text = text.name
        console.log(text)
        var obj = {
          "name": "",
          "stylesheet": "",
          "backendUri": ""
        }
        let python = "#!/usr/bin/env python \n\nimport json \n\ndef process(fullUrl, method, inHeaders, inputStream, remoteAddr, protocol): \n    responseHeaders = {'Content-Type': ['application/json']} \n    return json.dumps({}), responseHeaders, 200"
        var b64String = new Buffer(python).toString('base64');
        obj.stylesheet = b64String;
        obj.name = text
        fs.writeFileSync(filepath + '/data-objects/' + text + '.json', JSON.stringify(obj, null, 4));

        fs.writeFileSync(filepath + '/data-objects/' + text + '.py', python, 'binary', function(err) {});
        dataObjectsHandeler.postFile(path.basename(text)).then(function(){
          atom.notifications.addInfo("Filen: " + path.basename(text) + " finns nu på serven", null)
        })

      }
    });

    dialog.attach()
  },
  newItem(){
    var InputDialog = require('./../Input-dialog.js')

    var dialog = new InputDialog({
      labelText:"Filename",
      callback:function(text){
        filepath = atom.project.getPaths()[0]
        var obj = {}

        fs.writeFile(filepath + '/data-items/' + text, "", 'binary', function(err) {});
        dataitemsHandeler.postFile(path.basename(text)).then(function(){
          atom.notifications.addInfo("Filen: " + path.basename(text) + " finns nu på serven", null)
        })
      }
    });

    dialog.attach()
  },
  start() {
    addListeners()

  },
  uploadItems() {
    atom.notifications.addInfo("Filerna sparas", null)
    filepath = atom.project.getPaths()[0]
    var oldList = JSON.parse(fs.readFileSync(filepath + '/.files.json', 'utf8'));
    var oldSources = oldList.dataSources
    var oldObjects = oldList.dataObjects
    oldList = oldList.fileList
    filelistHandeler.getFileList().then(function(newList) {
      var newSources = newList.dataSources
      var newObjects = newList.dataObjects
      newList = newList.fileList

      let promises = []

      // for data items
      var serverFilesHasBeenEdited = false;
      for (listItem in oldList) {
        if (newList[listItem] == undefined || oldList[listItem]['etag'] !== newList[listItem]['etag']) {
          serverFilesHasBeenEdited = true;
        }
        promises.push(dataitemsHandeler.uploadFile(oldList[listItem], listItem))

      }

      // for data sources
      for (source in oldSources) {
        if (newSources[source] == undefined || oldSources[source]['etag'] !== newSources[source]['etag']) {
          serverFilesHasBeenEdited = true;
          break;
        }
        promises.push(datasourceHandeler.uploadSource(source, oldSources[source]))

      }

      // for data objects
      for (object in oldObjects) {
        if (newObjects[object] == undefined || oldObjects[object]['etag'] !== newObjects[object]['etag']) {
          serverFilesHasBeenEdited = true;
          break;
        }
        promises.push(dataObjectsHandeler.uploadObject(object, oldObjects[object]))

      }

      if(!serverFilesHasBeenEdited){
        Promise.all(promises).then(function(obj){
          filelistHandeler.getFileList().then(function(result) {
            var filepath = atom.project.getPaths()[0]
            fs.writeFile(filepath + '/.files.json', JSON.stringify(result, null, 4));
            atom.notifications.addInfo("Filerna är nu uppladdade", null)
          });
        });
      }

      editedFiles = {}
    });
  },
  createConfig() {
    console.log('Creating config file')
    atom.notifications.addInfo("Config-fil skapas", null)

    var dynappconfig = {
      "username": "<username>/<devgroups>",
      "password": "<password>",
      "group": "<projectGroup>",
      "app": "<appname>",
      "baseUrl":"https://dynappbeta.wip.se/"
    }

    var filepath = atom.project.getPaths()[0]
    if (!fs.existsSync(filepath)) {
      // Do something
      fs.writeFile(filepath + '/dynappconfig.json', JSON.stringify(dynappconfig, null, 4));
    }

    try{
      fs.mkdirSync(filepath + '/data-source-items');

    }catch(ex){
      console.log("data-source-items already exists")
    }
    try{
        fs.mkdirSync(filepath + '/data-objects');

      }catch(ex){
        console.log("data-objects already exists")
      }

      try{
        fs.mkdirSync(filepath + '/data-items');

      }catch(ex){
        console.log("data-items already exists")
      }
  },
  deactivate() {
    this.modalPanel.destroy();
    this.subscriptions.dispose();
    this.wipAtomView.destroy();
  },

  serialize() {
    return {
      wipAtomViewState: this.wipAtomView.serialize()
    };
  },
  // download the project
  download() {
    console.log("Downloading files")
    atom.notifications.addInfo("Downloading project", null)
    filelistHandeler.getFileList().then(function(result) {
      var files = validateFilesToDownload(result)
      var filepath = atom.project.getPaths()[0]
      fs.writeFile(filepath + '/.files.json', JSON.stringify(files, null, 4));
      var promises = []
      for (file in files.fileList) {
        promises.push(dataitemsHandeler.downloadFile(file))
      }
      for(source in files.dataSources){
        promises.push(datasourceHandeler.downloadSource(source))
      }

      for(object in files.dataObjects){
        promises.push(dataObjectsHandeler.downloadObject(object));
      }
      Promise.all(promises).then(function(){
        addListeners()

        atom.notifications.addInfo("Project downloaded", null)
        console.log("adding listeners")
      })

    });
  }
};
<commit_msg>minor changes<commit_after>'use babel';

import WipAtomView from './dynapp-atom-view';
import {
  CompositeDisposable
} from 'atom';

const request = require('request')
const fs = require('fs');
const {File} = require('atom')
const {Project} = require('atom')
const path = require('path')
var editedFiles = {}
var datasourceHandeler = require('./../DatasourceHandeler.js')
var dataitemsHandeler = require('./../DataitemsHandeler.js')
var filelistHandeler = require('./../filelistHandeler.js')
var dataObjectsHandeler = require('./../DataObjectsHandeler.js')

// download only json, css, html and js
var validateFilesToDownload = function(files) {
  for (file in files.fileList) {
    if (file.indexOf('.json') != -1) {

    } else if (file.indexOf('.css') != -1) {

    } else if (file.indexOf('.html') != -1) {

    } else if (file.indexOf('.js') != -1) {

    } else {
      delete files.fileList[file];
    }
  }
  return files;
}

// add listeners for all files
var addListeners = function(){
  dataitemsHandeler.addOnDeleteListener();
  datasourceHandeler.addOnDeleteListener();
  dataObjectsHandeler.addOnDeleteListener();

  try{
    atom.workspace.observeTextEditors(function(editor){
      editor.onDidSave(function(cb){
        if(cb.path.indexOf('.files') != -1 || cb.path.indexOf('dynappconfig') != -1){
          return;
        }
          if(editedFiles[cb.path] === undefined){
            editedFiles[cb.path] = true
            var filepath = atom.project.getPaths()[0]
            var fileObject = JSON.parse(fs.readFileSync(filepath + '/.files.json', 'utf8'));

            if(cb.path.indexOf('data-source-items') != -1){
              if(fileObject.dataSources[path.basename(cb.path, '.py')] != undefined){
                console.log("making dirty")
                fileObject.dataSources[path.basename(cb.path, '.py')]['dirty'] = true
                fs.writeFile(filepath + '/.files.json', JSON.stringify(fileObject, null, 4));
              }
              else if(fileObject.dataSources[path.basename(cb.path, '.json')] != undefined){
                console.log("making dirty")
                fileObject.dataSources[path.basename(cb.path, '.json')]['dirty'] = true
                fs.writeFile(filepath + '/.files.json', JSON.stringify(fileObject, null, 4));
              }
            }
            else if(cb.path.indexOf('data-objects') != -1){
              if(fileObject.dataObjects[path.basename(cb.path, '.py')] != undefined){
                console.log("making dirty")
                fileObject.dataObjects[path.basename(cb.path, '.py')]['dirty'] = true
                fs.writeFile(filepath + '/.files.json', JSON.stringify(fileObject, null, 4));
              }
              else if(fileObject.dataObjects[path.basename(cb.path, '.json')] != undefined){
                console.log("making dirty")
                fileObject.dataObjects[path.basename(cb.path, '.json')]['dirty'] = true
                fs.writeFile(filepath + '/.files.json', JSON.stringify(fileObject, null, 4));
              }
            }
            else if(fileObject.fileList[path.basename(cb.path)] != undefined){
              console.log("making dirty")
              fileObject.fileList[path.basename(cb.path)]['dirty'] = true;
              fs.writeFile(filepath + '/.files.json', JSON.stringify(fileObject, null, 4));
            } else if(path.basename(cb.path) != 'dynappconfig.json' && path.basename(cb.path) != ".files.json"){
              console.log(path.basename(cb.path))
              dataitemsHandeler.postFile(path.basename(cb.path)).then(function(){
                atom.notifications.addInfo("Filen: " + path.basename(cb.path) + " finns nu på serven", null)
              })

            }
          }
      })
    })
  } catch(ex){}
}

// get project credentials
var getCred = function(){
  var filepath = atom.project.getPaths()[0] + '/dynappconfig.json'
  var content = fs.readFileSync(filepath, 'utf8')
  var cred = JSON.parse(content)
  return cred
}

export default {

  wipAtomView: null,
  modalPanel: null,
  subscriptions: null,

  activate(state) {
    this.wipAtomView = new WipAtomView(state.wipAtomViewState);
    this.modalPanel = atom.workspace.addModalPanel({
      item: this.wipAtomView.getElement(),
      visible: false
    });

    // Events subscribed to in atom's system can be easily cleaned up with a CompositeDisposable
    this.subscriptions = new CompositeDisposable();
    this.start()

    // Register command that toggles this view
    this.subscriptions.add(atom.commands.add('atom-workspace', {
      'dynapp-atom:downloadProject': () => this.download(),
      'dynapp-atom:createConfig': () => this.createConfig(),
      'dynapp-atom:uploadItems': () => this.uploadItems(),
      'dynapp-atom:newItem': () => this.newItem(),
      'dynapp-atom:newObject': () => this.newObject(),
      'dynapp-atom:newSource': () => this.newSource()

    }));
  },
  newSource(){
    var InputDialog = require('./../Input-dialog.js')

    var dialog = new InputDialog({
      labelText:"Filename",
      callback:function(text){
        filepath = atom.project.getPaths()[0]
        text = path.parse(text)
        text = text.name
        filepath = atom.project.getPaths()[0]
        var obj = {
          "name": "",
          "stylesheet": "",
          "dataSourceUri": "",
          "cacheSeconds": 0,
          "jtidy": false,
          "category": 2,
          "key": "",
          "cron": false
        }

        let python = "#!/usr/bin/env python \n\nimport json \n\ndef transform(logger, item, username, password, parameterMap): \n    response = {} \n    return 200, json.dumps(response)"
        var b64String = new Buffer(python).toString('base64');
        obj.stylesheet = b64String;
        obj.name = text;
        fs.writeFileSync(filepath + '/data-source-items/' + text + '.json', JSON.stringify(obj, null, 4));

        fs.writeFileSync(filepath + '/data-source-items/' + text + '.py', python, 'binary', function(err) {});
        datasourceHandeler.postFile(path.basename(text)).then(function(){
          atom.notifications.addInfo("Filen: " + path.basename(text) + " finns nu på serven", null)
        })

      }
    });

    dialog.attach()
  },
  newObject(){
    var InputDialog = require('./../Input-dialog.js')

    var dialog = new InputDialog({
      labelText:"Filename",
      callback:function(text){
        filepath = atom.project.getPaths()[0]
        text = path.parse(text)
        text = text.name
        console.log(text)
        var obj = {
          "name": "",
          "stylesheet": "",
          "backendUri": ""
        }
        let python = "#!/usr/bin/env python \n\nimport json \n\ndef process(fullUrl, method, inHeaders, inputStream, remoteAddr, protocol): \n    responseHeaders = {'Content-Type': ['application/json']} \n    return json.dumps({}), responseHeaders, 200"
        var b64String = new Buffer(python).toString('base64');
        obj.stylesheet = b64String;
        obj.name = text
        fs.writeFileSync(filepath + '/data-objects/' + text + '.json', JSON.stringify(obj, null, 4));

        fs.writeFileSync(filepath + '/data-objects/' + text + '.py', python, 'binary', function(err) {});
        dataObjectsHandeler.postFile(path.basename(text)).then(function(){
          atom.notifications.addInfo("Filen: " + path.basename(text) + " finns nu på serven", null)
        })

      }
    });

    dialog.attach()
  },
  newItem(){
    var InputDialog = require('./../Input-dialog.js')

    var dialog = new InputDialog({
      labelText:"Filename",
      callback:function(text){
        filepath = atom.project.getPaths()[0]
        var obj = {}

        fs.writeFile(filepath + '/data-items/' + text, "", 'binary', function(err) {});
        dataitemsHandeler.postFile(path.basename(text)).then(function(){
          atom.notifications.addInfo("Filen: " + path.basename(text) + " finns nu på serven", null)
        })
      }
    });

    dialog.attach()
  },
  start() {
    addListeners()

  },
  uploadItems() {
    atom.notifications.addInfo("Filerna sparas", null)
    filepath = atom.project.getPaths()[0]
    var oldList = JSON.parse(fs.readFileSync(filepath + '/.files.json', 'utf8'));
    var oldSources = oldList.dataSources
    var oldObjects = oldList.dataObjects
    oldList = oldList.fileList
    filelistHandeler.getFileList().then(function(newList) {
      var newSources = newList.dataSources
      var newObjects = newList.dataObjects
      newList = newList.fileList

      let promises = []

      // for data items
      var serverFilesHasBeenEdited = false;
      for (listItem in oldList) {
        if (newList[listItem] == undefined || oldList[listItem]['etag'] !== newList[listItem]['etag']) {
          serverFilesHasBeenEdited = true;
        }
        promises.push(dataitemsHandeler.uploadFile(oldList[listItem], listItem))

      }

      // for data sources
      for (source in oldSources) {
        if (newSources[source] == undefined || oldSources[source]['etag'] !== newSources[source]['etag']) {
          serverFilesHasBeenEdited = true;
          break;
        }
        promises.push(datasourceHandeler.uploadSource(source, oldSources[source]))

      }

      // for data objects
      for (object in oldObjects) {
        if (newObjects[object] == undefined || oldObjects[object]['etag'] !== newObjects[object]['etag']) {
          serverFilesHasBeenEdited = true;
          break;
        }
        promises.push(dataObjectsHandeler.uploadObject(object, oldObjects[object]))

      }

      if(!serverFilesHasBeenEdited){
        Promise.all(promises).then(function(obj){
          filelistHandeler.getFileList().then(function(result) {
            var filepath = atom.project.getPaths()[0]
            fs.writeFile(filepath + '/.files.json', JSON.stringify(result, null, 4));
            atom.notifications.addInfo("Filerna är nu uppladdade", null)
          });
        });
      }

      editedFiles = {}
    });
  },
  createConfig() {
    console.log('Creating config file')
    atom.notifications.addInfo("Config-fil skapas", null)

    var dynappconfig = {
      "username": "<username>/<devgroups>",
      "password": "<password>",
      "group": "<projectGroup>",
      "app": "<appname>",
      "baseUrl":"https://dynappbeta.wip.se/"
    }

    var filepath = atom.project.getPaths()[0]
    if (!fs.existsSync(filepath)) {
      // Do something
      fs.writeFile(filepath + '/dynappconfig.json', JSON.stringify(dynappconfig, null, 4));
    }

    try{
      fs.mkdirSync(filepath + '/data-source-items');

    }catch(ex){
      console.log("data-source-items already exists")
    }
    try{
        fs.mkdirSync(filepath + '/data-objects');

      }catch(ex){
        console.log("data-objects already exists")
      }

      try{
        fs.mkdirSync(filepath + '/data-items');

      }catch(ex){
        console.log("data-items already exists")
      }
  },
  deactivate() {
    this.modalPanel.destroy();
    this.subscriptions.dispose();
    this.wipAtomView.destroy();
  },

  serialize() {
    return {
      wipAtomViewState: this.wipAtomView.serialize()
    };
  },
  // download the project
  download() {
    console.log("Downloading files")
    atom.notifications.addInfo("Downloading project", null)
    filelistHandeler.getFileList().then(function(result) {
      var files = validateFilesToDownload(result)
      var filepath = atom.project.getPaths()[0]
      fs.writeFile(filepath + '/.files.json', JSON.stringify(files, null, 4));
      var promises = []
      for (file in files.fileList) {
        promises.push(dataitemsHandeler.downloadFile(file))
      }
      for(source in files.dataSources){
        promises.push(datasourceHandeler.downloadSource(source))
      }

      for(object in files.dataObjects){
        promises.push(dataObjectsHandeler.downloadObject(object));
      }
      Promise.all(promises).then(function(){
        addListeners()

        atom.notifications.addInfo("Project downloaded", null)
        console.log("adding listeners")
      })

    });
  }
};
<|endoftext|>


<commit_before>'use strict';

var util = require('util');
var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var Promise = require('bluebird');

var debug = require('debug')('loopback:connector:elasticsearch');

var elasticsearch = require('elasticsearch');
var Connector = require('loopback-connector').Connector;

/**
 * Initialize connector with datasource, configure settings and return
 * @param {object} dataSource
 * @param {function} done callback
 */
module.exports.initialize = function (dataSource, done) {
    var settings = dataSource.settings || {};
    var connector = new ESConnector(settings);
    connector.connectToElasticClient(settings, dataSource);
    dataSource.connector = connector;
    if(settings.mappings) {
        connector.setupMappings(settings, done);
    }
    else {
    process.nextTick(done);
    }
};

/**
 * Connector constructor
 * @param {object} datasource settings
 * @param {object} dataSource
 * @constructor
 */
var ESConnector = function (settings) {
    this.name = 'elastic-search';
    this._models = {};
    this.settings = settings;
    this.searchIndex = settings.index || '';
    this.searchType = settings.type || '';
    this.defaultSize = (settings.defaultSize || 10);
    this.idField = '_id';

    this.debug = settings.debug || debug.enabled;
    if (this.debug) {
        debug('Settings: %j', settings);
    }
};

/**
 * Inherit the prototype methods
 */
util.inherits(ESConnector, Connector);

/**
 * Get client URL from settings
 * @param {object} settings of data source
 * @returns {object} host: string, requestTimeout: number, suggestCompression: boolean, log: string
 */
ESConnector.prototype.getESClientURL = function (settings) {
    var defaultHost = {
        host: '127.0.0.1',
        port: 9200
    };
    var options = {
        hosts: settings.hosts || defaultHost,
        requestTimeout: settings.requestTimeout || 1000,
        apiVersion: settings.apiVersion,
        log: settings.log || 'error',
        suggestCompression: true
    };
    if (settings.ssl) {
        options.ssl = {
            ca: fs.readFileSync( path.normalize(settings.ssl.ca) || path.join(__dirname, '..', 'cacert.pem') ),
            rejectUnauthorized: settings.ssl.rejectUnauthorized || true
        };
    }
    return options;
};

/**
 * Connect to elastic search client
 * @param {object} settings of data source
 * @param {object} dataSource
 */
ESConnector.prototype.connectToElasticClient = function (settings, dataSource) {
    this.elasticServer = new elasticsearch.Client(this.getESClientURL(settings));
    this.dataSource = dataSource;
};

ESConnector.prototype.setupMappings = function (settings, done) {
    var elasticServer = this.elasticServer;
    Promise.map(
        settings.mappings,
        function (mapping) {
            return elasticServer.indices.putMapping(
                {
                    index: settings.index,
                    type: mapping.name,
                    body: {properties: mapping.properties}
                }
            ).then(
                function (body) {
                    debug('setupMappings', mapping.name, body);
                    return Promise.resolve();
                }, function (err) {
                    console.trace(err.message);
                    if (err) {
                        return done(err, null);
                    }
                }
            );
        },
        {concurrency: 1}
    )
        .then(function () {
            debug('all setupMappings finished');
            done(); // TODO: what does the connector framework want back as arguments here?
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        });
};

/**
 * Ping to test elastic connection
 * @returns {String} with ping result
 */
ESConnector.prototype.ping = function () {
    this.elasticServer.ping({
        requestTimeout : 1000
    }, function (error) {
        if (error) {
            return 'nok';
        } else {
            return 'ok';
        }
    });
};

/**
 * Return connector type
 * @returns {String} type description
 */
ESConnector.prototype.getTypes = function () {
    return [this.name];
};

/**
 * Get value from property checking type
 * @param {object} property
 * @param {String} value
 * @returns {object}
 */
ESConnector.prototype.getValueFromProperty = function (property, value) {
    if (property.type instanceof Array) {
        if (!value || (value.length === 0)) {
            return new Array();
        } else {
            return new Array(value.toString());
        }
    } else if (property.type === String) {
        return value.toString();
    } else if (property.type === Number) {
        return Number(value);
    } else {
        return value;
    }
};

/**
 * Match and transform data structure to model
 * @param {String} model name
 * @param {Object} data from DB
 * @returns {object} modeled document
 */
ESConnector.prototype.matchDataToModel = function (model, data) {
    var self = this;
    if (!data) {
        return null;
    }
    try {
        var properties = this._models[model].properties;
        var document = {};

        for (var propertyName in properties) {
            var propertyValue = data[propertyName];
            if (propertyValue) {
                document[propertyName] = self.getValueFromProperty(properties[propertyName], propertyValue);
            }
        }
        return document;
    } catch (err) {
        console.trace(err.message);
        return null;
    }
};

/**
 * Convert data source to model
 * @param {String} model name
 * @param {Object} data object
 * @returns {object} modeled document
 */
ESConnector.prototype.dataSourceToModel = function (model, data) {
    if ((!data) || (!data.found) && (data.found === false)) {
        return null;
    }
    return this.matchDataToModel(model, data._source);
};

/**
 * @param {String} model name
 * Make filter with index name and type
 * @returns {object} Filter with index and type
 */
ESConnector.prototype.makeFilterIndexAndType = function (model) {
    var filter = {};
    if (this.searchIndex) {
        filter['index'] = this.searchIndex;
    }
    filter['type'] = model;
    return filter;
};

/**
 * Make filter from criteria, data index and type
 * Ex:
 *   {"body": {"query": {"match": {"title": "Futuro"}}}}
 *   {"q" : "Futuro"}
 * @param {String} model filter
 * @param {String} criteria filter
 * @param {number} size of rows to return, if null then skip
 * @param {number} offset to return, if null then skip
 * @returns {object} filter
 */
ESConnector.prototype.makeFilter = function (model, criteria, size, offset) {
    var self = this;
    if (self.debug) {
        debug('makeFilter', 'criteria', criteria, 'model', model);
    }

    var filter = this.makeFilterIndexAndType(model);
    if (size && (size != null)) {
        if (size < 1) {
            if (this.defaultSize) {
                filter['size'] = this.defaultSize;
            }
        } else {
            filter['size'] = size;
        }
    }
    if (offset && (offset != null)) {
        if (offset > 0) {
            filter['from'] = offset;
        }
    }
    if (criteria) {
        for (var criteriaItem in criteria) {
            filter[criteriaItem] = criteria[criteriaItem];
        }
    }
    return filter;
};

/**
 * Return all data from Elastic search
 * @param {String} model The model name
 * @param {Object} filter The filter
 * @param {Function} done callback function
 */
ESConnector.prototype.all = function all(model, filter, done) {
    var self = this;
    if (self.debug) {
        debug('all', 'model', model, 'filter', filter);
    }

    self.elasticServer.search(
        self.makeFilter(model, filter, 0, 0)
    ).then(
        function (body) {
            var result = [];
            body.hits.hits.forEach(function (item) {
                result.push(self.dataSourceToModel(model, item));
            });
            done(null, result);
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Get document Id validating data
 * @param {String} id
 * @returns {Number} Id
 * @constructor
 */
ESConnector.prototype.getDocumentId = function (id) {
    try {
        if (typeof id !== 'string') {
            return id.toString();
        } else {
            return id;
        }
    } catch (e) {
        return id;
    }
};

/**
 * Check for data existence
 * @param {String} model name
 * @param {String} id row identifier
 * @param {function} done callback
 */
ESConnector.prototype.exists = function (model, id, done) {
    var self = this;
    if (self.debug) {
        debug('exists', 'model', model, 'id', id);
    }

    var filter = self.makeFilterIndexAndType(model);
    filter[self.idField] = this.getDocumentId(id);
    if (!filter[self.idField]) {
        throw new Error('Document id not setted!');
    }
    self.elasticServer.exists(
        filter
    ).then(
        function (exists) {
            done(null, exists);
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Find a model instance by id
 * @param {String} model name
 * @param {String} id row identifier
 * @param {Function} done callback
 */
ESConnector.prototype.find = function find(model, id, done) {
    var self = this;
    if (self.debug) {
        debug('find', 'model', model, 'id', id);
    }

    var filter = self.makeFilterIndexAndType(model);
    filter[self.idField] = this.getDocumentId(id);
    if (!filter[self.idField]) {
        throw new Error('Document id not setted!');
    }
    self.elasticServer.get(
        filter
    ).then(
        function (response) {
            done(null, self.dataSourceToModel(model, response));
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Delete a document by Id
 * @param {String} model name
 * @param {String} id row identifier
 * @param {Function} done callback
 */
ESConnector.prototype.destroy = function destroy(model, id, done) {
    var self = this;
    if (self.debug) {
        debug('destroy', 'model', model, 'id', id);
    }

    var filter = self.makeFilterIndexAndType(model);
    filter[self.idField] = self.getDocumentId(id);
    if (!filter[self.idField]) {
        throw new Error('Document id not setted!');
    }
    self.elasticServer.delete(
        filter
    ).then(
        function (response) {
            done(null, response);
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Delete all documents with param criteria
 * @param {String} model name
 * @param {String} filter criteria
 * @param {Function} done callback
 */
ESConnector.prototype.destroyAll = function destroyAll(model, filter, done) {
    var self = this;
    if (self.debug) {
        debug('destroyAll', 'model', model, 'filter', filter);
    }

    var filter = self.makeFilter(model, filter, 0, 0);
    self.elasticServer.deleteByQuery(
        filter
    ).then(
        function (response) {
            done(null, response);
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Return number of rows by the where criteria
 * @param {String} model name
 * @param {String} filter criteria
 * @param {Function} done callback
 */
ESConnector.prototype.count = function count(model, done, filter) {
    var self = this;
    if (self.debug) {
        debug('count', 'model', model, 'filter', filter);
    }

    self.elasticServer.count(
        self.makeFilter(model, filter, null, null)
    ).then(
        function (response) {
            done(null, response.count);
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Create a new model instance
 * @param {String} model name
 * @param {object} data info
 * @param {Function} done callback
 */
ESConnector.prototype.create = function (model, data, done) {
    var self = this;
    if (self.debug) {
        debug('create', model, data);
    }

    var idValue = self.getIdValue(model, data);
    var idName = self.idName(model);
    debug('create', 'idName', idName, 'idValue', idValue);

    var document = self.makeFilterIndexAndType(model);
    document[self.idField] = self.getDocumentId(idValue);
    document.body = {};
    _.assign(document.body, data);
    debug('create', 'document', document);

    self.elasticServer.create(
        document
    ).then(
        function (response) {
            debug('response', response);
            done(null, response._id); // the connector framework expects the id as a return value
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Update document data
 * @param {String} model name
 * @param {Object} data document
 * @param {Function} done callback
 */
ESConnector.prototype.save = function (model, data, done) {
    var self = this;
    if (self.debug) {
        debug('save', 'model', model, 'data', data);
    }

    var document = self.makeFilterIndexAndType(model);
    document[self.idField] = self.makeId(data.id);
    if (!document[self.idField]) {
        throw new Error('Document id not setted!');
    }
    document.body = self.matchDataToModel(model, data);
    self.elasticServer.update(
        document
    ).then(
        function (response) {
            done(null, response);
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Update a model instance or create a new model instance if it doesn't exist
 */
ESConnector.prototype.updateOrCreate = function updateOrCreate(model, data, done) {
    // TODO: fail, test and re test
    var self = this;
    if (self.debug) {
        debug('updateOrCreate', 'model', model, 'data', data);
    }

    var document = self.makeFilterIndexAndType(model);
    document[self.idField] = self.makeId(data.id);
    if (!document[self.idField]) {
        throw new Error('Document id not setted!');
    }
    document.body = self.matchDataToModel(model, data);
    self.elasticServer.update(
        document
    ).then(
        function (response) {
            done(null, response);
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Update the attributes for a model instance by id
 */
ESConnector.prototype.updateAttributes = function updateAttrs(model, id, data, done) {
// TODO: make code
};

module.exports.name = ESConnector.name;
module.exports.ESConnector = ESConnector;
<commit_msg>the idField wasn't tracking the actual elasticsearch `_id` ... rather its just used by the ES client<commit_after>'use strict';

var util = require('util');
var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var Promise = require('bluebird');

var debug = require('debug')('loopback:connector:elasticsearch');

var elasticsearch = require('elasticsearch');
var Connector = require('loopback-connector').Connector;

/**
 * Initialize connector with datasource, configure settings and return
 * @param {object} dataSource
 * @param {function} done callback
 */
module.exports.initialize = function (dataSource, done) {
    var settings = dataSource.settings || {};
    var connector = new ESConnector(settings);
    connector.connectToElasticClient(settings, dataSource);
    dataSource.connector = connector;
    if(settings.mappings) {
        connector.setupMappings(settings, done);
    }
    else {
    process.nextTick(done);
    }
};

/**
 * Connector constructor
 * @param {object} datasource settings
 * @param {object} dataSource
 * @constructor
 */
var ESConnector = function (settings) {
    this.name = 'elastic-search';
    this._models = {};
    this.settings = settings;
    this.searchIndex = settings.index || '';
    this.searchType = settings.type || '';
    this.defaultSize = (settings.defaultSize || 10);
    this.idField = 'id';

    this.debug = settings.debug || debug.enabled;
    if (this.debug) {
        debug('Settings: %j', settings);
    }
};

/**
 * Inherit the prototype methods
 */
util.inherits(ESConnector, Connector);

/**
 * Get client URL from settings
 * @param {object} settings of data source
 * @returns {object} host: string, requestTimeout: number, suggestCompression: boolean, log: string
 */
ESConnector.prototype.getESClientURL = function (settings) {
    var defaultHost = {
        host: '127.0.0.1',
        port: 9200
    };
    var options = {
        hosts: settings.hosts || defaultHost,
        requestTimeout: settings.requestTimeout || 1000,
        apiVersion: settings.apiVersion,
        log: settings.log || 'error',
        suggestCompression: true
    };
    if (settings.ssl) {
        options.ssl = {
            ca: fs.readFileSync( path.normalize(settings.ssl.ca) || path.join(__dirname, '..', 'cacert.pem') ),
            rejectUnauthorized: settings.ssl.rejectUnauthorized || true
        };
    }
    return options;
};

/**
 * Connect to elastic search client
 * @param {object} settings of data source
 * @param {object} dataSource
 */
ESConnector.prototype.connectToElasticClient = function (settings, dataSource) {
    this.elasticServer = new elasticsearch.Client(this.getESClientURL(settings));
    this.dataSource = dataSource;
};

ESConnector.prototype.setupMappings = function (settings, done) {
    var elasticServer = this.elasticServer;
    Promise.map(
        settings.mappings,
        function (mapping) {
            return elasticServer.indices.putMapping(
                {
                    index: settings.index,
                    type: mapping.name,
                    body: {properties: mapping.properties}
                }
            ).then(
                function (body) {
                    debug('setupMappings', mapping.name, body);
                    return Promise.resolve();
                }, function (err) {
                    console.trace(err.message);
                    if (err) {
                        return done(err, null);
                    }
                }
            );
        },
        {concurrency: 1}
    )
        .then(function () {
            debug('all setupMappings finished');
            done(); // TODO: what does the connector framework want back as arguments here?
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        });
};

/**
 * Ping to test elastic connection
 * @returns {String} with ping result
 */
ESConnector.prototype.ping = function () {
    this.elasticServer.ping({
        requestTimeout : 1000
    }, function (error) {
        if (error) {
            return 'nok';
        } else {
            return 'ok';
        }
    });
};

/**
 * Return connector type
 * @returns {String} type description
 */
ESConnector.prototype.getTypes = function () {
    return [this.name];
};

/**
 * Get value from property checking type
 * @param {object} property
 * @param {String} value
 * @returns {object}
 */
ESConnector.prototype.getValueFromProperty = function (property, value) {
    if (property.type instanceof Array) {
        if (!value || (value.length === 0)) {
            return new Array();
        } else {
            return new Array(value.toString());
        }
    } else if (property.type === String) {
        return value.toString();
    } else if (property.type === Number) {
        return Number(value);
    } else {
        return value;
    }
};

/**
 * Match and transform data structure to model
 * @param {String} model name
 * @param {Object} data from DB
 * @returns {object} modeled document
 */
ESConnector.prototype.matchDataToModel = function (model, data) {
    var self = this;
    if (!data) {
        return null;
    }
    try {
        var properties = this._models[model].properties;
        var document = {};

        for (var propertyName in properties) {
            var propertyValue = data[propertyName];
            if (propertyValue) {
                document[propertyName] = self.getValueFromProperty(properties[propertyName], propertyValue);
            }
        }
        return document;
    } catch (err) {
        console.trace(err.message);
        return null;
    }
};

/**
 * Convert data source to model
 * @param {String} model name
 * @param {Object} data object
 * @returns {object} modeled document
 */
ESConnector.prototype.dataSourceToModel = function (model, data) {
    if ((!data) || (!data.found) && (data.found === false)) {
        return null;
    }
    return this.matchDataToModel(model, data._source);
};

/**
 * @param {String} model name
 * Make filter with index name and type
 * @returns {object} Filter with index and type
 */
ESConnector.prototype.makeFilterIndexAndType = function (model) {
    var filter = {};
    if (this.searchIndex) {
        filter['index'] = this.searchIndex;
    }
    filter['type'] = model;
    return filter;
};

/**
 * Make filter from criteria, data index and type
 * Ex:
 *   {"body": {"query": {"match": {"title": "Futuro"}}}}
 *   {"q" : "Futuro"}
 * @param {String} model filter
 * @param {String} criteria filter
 * @param {number} size of rows to return, if null then skip
 * @param {number} offset to return, if null then skip
 * @returns {object} filter
 */
ESConnector.prototype.makeFilter = function (model, criteria, size, offset) {
    var self = this;
    if (self.debug) {
        debug('makeFilter', 'criteria', criteria, 'model', model);
    }

    var filter = this.makeFilterIndexAndType(model);
    if (size && (size != null)) {
        if (size < 1) {
            if (this.defaultSize) {
                filter['size'] = this.defaultSize;
            }
        } else {
            filter['size'] = size;
        }
    }
    if (offset && (offset != null)) {
        if (offset > 0) {
            filter['from'] = offset;
        }
    }
    if (criteria) {
        for (var criteriaItem in criteria) {
            filter[criteriaItem] = criteria[criteriaItem];
        }
    }
    return filter;
};

/**
 * Return all data from Elastic search
 * @param {String} model The model name
 * @param {Object} filter The filter
 * @param {Function} done callback function
 */
ESConnector.prototype.all = function all(model, filter, done) {
    var self = this;
    if (self.debug) {
        debug('all', 'model', model, 'filter', filter);
    }

    self.elasticServer.search(
        self.makeFilter(model, filter, 0, 0)
    ).then(
        function (body) {
            var result = [];
            body.hits.hits.forEach(function (item) {
                result.push(self.dataSourceToModel(model, item));
            });
            done(null, result);
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Get document Id validating data
 * @param {String} id
 * @returns {Number} Id
 * @constructor
 */
ESConnector.prototype.getDocumentId = function (id) {
    try {
        if (typeof id !== 'string') {
            return id.toString();
        } else {
            return id;
        }
    } catch (e) {
        return id;
    }
};

/**
 * Check for data existence
 * @param {String} model name
 * @param {String} id row identifier
 * @param {function} done callback
 */
ESConnector.prototype.exists = function (model, id, done) {
    var self = this;
    if (self.debug) {
        debug('exists', 'model', model, 'id', id);
    }

    var filter = self.makeFilterIndexAndType(model);
    filter[self.idField] = this.getDocumentId(id);
    if (!filter[self.idField]) {
        throw new Error('Document id not setted!');
    }
    self.elasticServer.exists(
        filter
    ).then(
        function (exists) {
            done(null, exists);
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Find a model instance by id
 * @param {String} model name
 * @param {String} id row identifier
 * @param {Function} done callback
 */
ESConnector.prototype.find = function find(model, id, done) {
    var self = this;
    if (self.debug) {
        debug('find', 'model', model, 'id', id);
    }

    var filter = self.makeFilterIndexAndType(model);
    filter[self.idField] = this.getDocumentId(id);
    if (!filter[self.idField]) {
        throw new Error('Document id not setted!');
    }
    self.elasticServer.get(
        filter
    ).then(
        function (response) {
            done(null, self.dataSourceToModel(model, response));
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Delete a document by Id
 * @param {String} model name
 * @param {String} id row identifier
 * @param {Function} done callback
 */
ESConnector.prototype.destroy = function destroy(model, id, done) {
    var self = this;
    if (self.debug) {
        debug('destroy', 'model', model, 'id', id);
    }

    var filter = self.makeFilterIndexAndType(model);
    filter[self.idField] = self.getDocumentId(id);
    if (!filter[self.idField]) {
        throw new Error('Document id not setted!');
    }
    self.elasticServer.delete(
        filter
    ).then(
        function (response) {
            done(null, response);
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Delete all documents with param criteria
 * @param {String} model name
 * @param {String} filter criteria
 * @param {Function} done callback
 */
ESConnector.prototype.destroyAll = function destroyAll(model, filter, done) {
    var self = this;
    if (self.debug) {
        debug('destroyAll', 'model', model, 'filter', filter);
    }

    var filter = self.makeFilter(model, filter, 0, 0);
    self.elasticServer.deleteByQuery(
        filter
    ).then(
        function (response) {
            done(null, response);
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Return number of rows by the where criteria
 * @param {String} model name
 * @param {String} filter criteria
 * @param {Function} done callback
 */
ESConnector.prototype.count = function count(model, done, filter) {
    var self = this;
    if (self.debug) {
        debug('count', 'model', model, 'filter', filter);
    }

    self.elasticServer.count(
        self.makeFilter(model, filter, null, null)
    ).then(
        function (response) {
            done(null, response.count);
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Create a new model instance
 * @param {String} model name
 * @param {object} data info
 * @param {Function} done callback
 */
ESConnector.prototype.create = function (model, data, done) {
    var self = this;
    if (self.debug) {
        debug('create', model, data);
    }

    var idValue = self.getIdValue(model, data);
    var idName = self.idName(model);
    debug('create', 'idName', idName, 'idValue', idValue);

    var document = self.makeFilterIndexAndType(model);
    document[self.idField] = self.getDocumentId(idValue);
    document.body = {};
    _.assign(document.body, data);
    debug('create', 'document', document);

    self.elasticServer.create(
        document
    ).then(
        function (response) {
            debug('response', response);
            done(null, response._id); // the connector framework expects the id as a return value
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Update document data
 * @param {String} model name
 * @param {Object} data document
 * @param {Function} done callback
 */
ESConnector.prototype.save = function (model, data, done) {
    var self = this;
    if (self.debug) {
        debug('save', 'model', model, 'data', data);
    }

    var document = self.makeFilterIndexAndType(model);
    document[self.idField] = self.makeId(data.id);
    if (!document[self.idField]) {
        throw new Error('Document id not setted!');
    }
    document.body = self.matchDataToModel(model, data);
    self.elasticServer.update(
        document
    ).then(
        function (response) {
            done(null, response);
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Update a model instance or create a new model instance if it doesn't exist
 */
ESConnector.prototype.updateOrCreate = function updateOrCreate(model, data, done) {
    // TODO: fail, test and re test
    var self = this;
    if (self.debug) {
        debug('updateOrCreate', 'model', model, 'data', data);
    }

    var document = self.makeFilterIndexAndType(model);
    document[self.idField] = self.makeId(data.id);
    if (!document[self.idField]) {
        throw new Error('Document id not setted!');
    }
    document.body = self.matchDataToModel(model, data);
    self.elasticServer.update(
        document
    ).then(
        function (response) {
            done(null, response);
        }, function (err) {
            console.trace(err.message);
            if (err) {
                return done(err, null);
            }
        }
    );
};

/**
 * Update the attributes for a model instance by id
 */
ESConnector.prototype.updateAttributes = function updateAttrs(model, id, data, done) {
// TODO: make code
};

module.exports.name = ESConnector.name;
module.exports.ESConnector = ESConnector;
<|endoftext|>


<commit_before>var phantom = require('phantom'),
    config = require('_/config'),
    log = require('_/log'),
    _ = require('lodash'),
    phantomOptions = config.phantomJS || {},
    _phantomDestroyed = false,
    phantomExitHandler,
    workerExitHandler,
    _ph;

/* Phantom Process Creation
 *
 * spins up a child phantom process and stores a reference
 */
phantomExitHandler = function (err) {
    // log.info('Phantom process died. Killing worker.');
    _phantomDestroyed = true;
    process.exit();
};

phantom.create(function (ph) {
    _ph = ph;
}, _.defaultsDeep(phantomOptions, {
    onExit: phantomExitHandler
}));

/* Worker Process Exit Handlers
 *
 * cleanup the associated phantom process if the worker dies
 */
workerExitHandler = function (err) {
    if (_phantomDestroyed) return;
    // log.info('Worker process died. Killing phantomJS.');

    try {
        process.kill(_ph.process.pid, 'SIGHUP');
    } catch (e) {} finally {
        _phantomDestroyed = true;
    }
};

process.on('exit', workerExitHandler);
process.on('SIGINT', workerExitHandler);
process.on('uncaughtException', workerExitHandler);

module.exports = function (inp, callback) {
    callback(null, inp + ' (' + process.pid + ')');
};
<commit_msg>Force worker to wait for ready status before processing message.<commit_after>var phantom = require('phantom'),
    config = require('_/config'),
    log = require('_/log'),
    _ = require('lodash'),
    phantomOptions = config.phantomJS || {},
    phantomExitHandler,
    workerExitHandler,
    _ready = false,
    _ph;

/* Phantom Process Creation
 *
 * spins up a child phantom process and stores a reference
 */
phantomExitHandler = function (err) {
    log.debug('Phantom process exit.');
    process.exit(1);
};

phantom.create(function (ph) {
    _ph = ph;
    _ready = true;
}, _.defaultsDeep(phantomOptions, {
    onExit: phantomExitHandler
}));

/* Worker Process Exit Handlers
 *
 * cleanup the associated phantom process if the worker dies
 */
workerExitHandler = function (err) {
    log.debug('Worker process exit.');

    try {
        process.kill(_ph.process.pid, 'SIGKILL');
    } catch (e) {}
};

process.on('exit', workerExitHandler);
process.on('SIGINT', workerExitHandler);
process.on('uncaughtException', workerExitHandler);

module.exports = function (inp, callback) {
    var doCallback = function () {
        if (_ready) {
            callback(null, inp + ' (' + process.pid + ')' + '(' + _ph.process.pid + ')');
        } else {
            setTimeout(doCallback, 10);
        }
    };
    doCallback();
};
<|endoftext|>


<commit_before>// TODO: Update description to 'Create/copy folder to temporary working directory'

function FixtureDir(dir) {
  this.dir = dir;
}
FixtureDir.prototype = {
  enter: function (folderName, options) {
    options = options || {};
    var dir = path.join(this.dir, folderName);
    // TODO: rm folder if it exists
    // If there is a copyFrom, use `wrench.copy`
    // Otherwise, wrench.mkdirp
  },
  exit: function (folderName) {
    // TODO: rm folder
  }
};

// TODO: Make complementary mocha wrapper which receives `fixture-dir` and does enter/exit automagically

module.exports = FixtureDir;
<commit_msg>Sorted out how to deal with graceful previous directory exits<commit_after>// TODO: Update description to 'Create/copy folder to temporary working directory'

function FixtureDir(dir) {
  this.dir = dir;
}
FixtureDir.prototype = {
  enter: function (folderName, options) {
    // If we are already in a directory, complain
    if (this.previousDirectory) {
      throw new Error('`FixtureDir#enter` cannot enter multiple directories at the same time. Please run `FixtureDir#exit` first');
    }

    // Fallback options
    options = options || {};
    var dir = path.join(this.dir, folderName);

    // TODO: Save `previousDirectory`

    // TODO: rm folder if it exists
    // If there is a copyFrom, use `wrench.copy`
    // Otherwise, wrench.mkdirp

    // Move to the new directory
  },
  exit: function () {
    // TODO: rm folder
    // TODO: Reset previous directory
  }
};

// TODO: Make complementary mocha wrapper which receives `fixture-dir` and does enter/exit automagically

module.exports = FixtureDir;
<|endoftext|>


<commit_before>// flex-buffer.js

exports.FlexDecoder = FlexDecoder;
exports.FlexEncoder = FlexEncoder;

var MIN_BUFFER_SIZE = 2048;
var MAX_BUFFER_SIZE = 65536;
var BUFFER_SHORTAGE = new Error("BUFFER_SHORTAGE");

function FlexDecoder() {
  if (!(this instanceof FlexDecoder)) return new FlexDecoder();
}

function FlexEncoder() {
  if (!(this instanceof FlexEncoder)) return new FlexEncoder();
}

FlexDecoder.mixin = mixinFactory(getDecoderMethods());
FlexDecoder.mixin(FlexDecoder.prototype);

FlexEncoder.mixin = mixinFactory(getEncoderMethods());
FlexEncoder.mixin(FlexEncoder.prototype);

function getDecoderMethods() {
  return {
    write: write,
    fetch: fetch,
    flush: flush,
    push: push,
    pull: pull,
    read: read,
    reserve: reserve,
    offset: 0
  };

  function write(chunk) {
    var prev = this.offset ? this.buffer.slice(this.offset) : this.buffer;
    this.buffer = prev ? (chunk ? Buffer.concat([prev, chunk]) : prev) : chunk;
    this.offset = 0;
  }

  function flush() {
    while (this.offset < this.buffer.length) {
      var start = this.offset;
      var value;
      try {
        value = this.fetch();
      } catch (e) {
        if (e !== BUFFER_SHORTAGE) throw e;
        // rollback
        this.offset = start;
        break;
      }
      this.push(value);
    }
  }

  function reserve(length) {
    var start = this.offset;
    var end = start + length;
    if (end > this.buffer.length) throw BUFFER_SHORTAGE;
    this.offset = end;
    return start;
  }
}

function getEncoderMethods() {
  return {
    write: write,
    fetch: fetch,
    flush: flush,
    push: push,
    pull: pull,
    read: read,
    reserve: reserve,
    send: send,
    offset: 0,
    start: 0
  };

  function fetch() {
    var start = this.start;
    if (start < this.offset) {
      var end = this.start = this.offset;
      return this.buffer.slice(start, end);
    }
  }

  function flush() {
    while (this.start < this.offset) {
      var value = this.fetch();
      if (value) this.push(value);
    }
  }

  function pull() {
    var buffers = this.buffers || (this.buffers = []);
    var chunk = buffers.length > 1 ? Buffer.concat(buffers) : buffers[0];
    buffers.length = 0; // buffer exhausted
    return chunk;
  }

  function reserve(length) {
    var req = length | 0;

    if (this.buffer) {
      var size = this.buffer.length;
      var start = this.offset | 0;
      var end = start + req;

      // is it long enough?
      if (end < size) {
        this.offset = end;
        return start;
      }

      // flush current buffer
      this.flush();

      // resize it to 2x current length
      length = Math.max(length, Math.min(size * 2, MAX_BUFFER_SIZE));
    }

    // minimum buffer size
    length = length > MIN_BUFFER_SIZE ? length : MIN_BUFFER_SIZE;

    // allocate new buffer
    this.buffer = new Buffer(length);
    this.start = 0;
    this.offset = req;
    return 0;
  }

  function send(buffer) {
    var end = this.offset + buffer.length;
    if (this.buffer && end < this.buffer.length) {
      buffer.copy(this.buffer, this.offset);
      this.offset = end;
    } else {
      this.flush();
      this.push(buffer);
    }
  }
}

// common methods

function write() {
  throw new Error("method not implemented: write()");
}

function fetch() {
  throw new Error("method not implemented: fetch()");
}

function read() {
  var length = this.buffers && this.buffers.length;

  // fetch the first result
  if (!length) return this.fetch();

  // flush current buffer
  this.flush();

  // read from the results
  return this.pull();
}

function push(chunk) {
  var buffers = this.buffers || (this.buffers = []);
  buffers.push(chunk);
}

function pull() {
  var buffers = this.buffers || (this.buffers = []);
  return buffers.shift();
}

function mixinFactory(source) {
  return mixin;

  function mixin(target) {
    for (var key in source) {
      target[key] = source[key];
    }
    return target;
  }
}
<commit_msg>re #8: maxBufferSize, minBufferSize<commit_after>// flex-buffer.js

exports.FlexDecoder = FlexDecoder;
exports.FlexEncoder = FlexEncoder;

var MIN_BUFFER_SIZE = 2048;
var MAX_BUFFER_SIZE = 65536;
var BUFFER_SHORTAGE = new Error("BUFFER_SHORTAGE");

function FlexDecoder() {
  if (!(this instanceof FlexDecoder)) return new FlexDecoder();
}

function FlexEncoder() {
  if (!(this instanceof FlexEncoder)) return new FlexEncoder();
}

FlexDecoder.mixin = mixinFactory(getDecoderMethods());
FlexDecoder.mixin(FlexDecoder.prototype);

FlexEncoder.mixin = mixinFactory(getEncoderMethods());
FlexEncoder.mixin(FlexEncoder.prototype);

function getDecoderMethods() {
  return {
    write: write,
    fetch: fetch,
    flush: flush,
    push: push,
    pull: pull,
    read: read,
    reserve: reserve,
    offset: 0
  };

  function write(chunk) {
    var prev = this.offset ? this.buffer.slice(this.offset) : this.buffer;
    this.buffer = prev ? (chunk ? Buffer.concat([prev, chunk]) : prev) : chunk;
    this.offset = 0;
  }

  function flush() {
    while (this.offset < this.buffer.length) {
      var start = this.offset;
      var value;
      try {
        value = this.fetch();
      } catch (e) {
        if (e !== BUFFER_SHORTAGE) throw e;
        // rollback
        this.offset = start;
        break;
      }
      this.push(value);
    }
  }

  function reserve(length) {
    var start = this.offset;
    var end = start + length;
    if (end > this.buffer.length) throw BUFFER_SHORTAGE;
    this.offset = end;
    return start;
  }
}

function getEncoderMethods() {
  return {
    write: write,
    fetch: fetch,
    flush: flush,
    push: push,
    pull: pull,
    read: read,
    reserve: reserve,
    send: send,
    maxBufferSize: MAX_BUFFER_SIZE,
    minBufferSize: MIN_BUFFER_SIZE,
    offset: 0,
    start: 0
  };

  function fetch() {
    var start = this.start;
    if (start < this.offset) {
      var end = this.start = this.offset;
      return this.buffer.slice(start, end);
    }
  }

  function flush() {
    while (this.start < this.offset) {
      var value = this.fetch();
      if (value) this.push(value);
    }
  }

  function pull() {
    var buffers = this.buffers || (this.buffers = []);
    var chunk = buffers.length > 1 ? Buffer.concat(buffers) : buffers[0];
    buffers.length = 0; // buffer exhausted
    return chunk;
  }

  function reserve(length) {
    var req = length | 0;

    if (this.buffer) {
      var size = this.buffer.length;
      var start = this.offset | 0;
      var end = start + req;

      // is it long enough?
      if (end < size) {
        this.offset = end;
        return start;
      }

      // flush current buffer
      this.flush();

      // resize it to 2x current length
      length = Math.max(length, Math.min(size * 2, this.maxBufferSize));
    }

    // minimum buffer size
    length = Math.max(length, this.minBufferSize);

    // allocate new buffer
    this.buffer = new Buffer(length);
    this.start = 0;
    this.offset = req;
    return 0;
  }

  function send(buffer) {
    var end = this.offset + buffer.length;
    if (this.buffer && end < this.buffer.length) {
      buffer.copy(this.buffer, this.offset);
      this.offset = end;
    } else {
      this.flush();
      this.push(buffer);
    }
  }
}

// common methods

function write() {
  throw new Error("method not implemented: write()");
}

function fetch() {
  throw new Error("method not implemented: fetch()");
}

function read() {
  var length = this.buffers && this.buffers.length;

  // fetch the first result
  if (!length) return this.fetch();

  // flush current buffer
  this.flush();

  // read from the results
  return this.pull();
}

function push(chunk) {
  var buffers = this.buffers || (this.buffers = []);
  buffers.push(chunk);
}

function pull() {
  var buffers = this.buffers || (this.buffers = []);
  return buffers.shift();
}

function mixinFactory(source) {
  return mixin;

  function mixin(target) {
    for (var key in source) {
      target[key] = source[key];
    }
    return target;
  }
}
<|endoftext|>


<commit_before>
module.exports = {
    flow_default_target:{
        title: 'Default build target',
        description: 'Configure the default build target. Blank means the current user platform.',
        type: 'string',
        default: ''
    },

    debug_logging: {
        title:'Debug Logging',
        description: 'Enable to get more in depth logging for debugging problems with the package',
        type: 'boolean',
        default:'false'
    }

}
<commit_msg>config; add build selectors<commit_after>
module.exports = {
    flow_default_target:{
        title: 'Default build target',
        description: 'Configure the default build target. Blank means the current user platform.',
        type: 'string',
        default: ''
    },

    debug_logging: {
        title:'Debug Logging',
        description: 'Enable to get more in depth logging for debugging problems with the package',
        type: 'boolean',
        default:'false'
    },

    build_selectors: {
        title:'Haxe Build: additional allowed file scopes',
        description: 'When running the build command, these file scopes will also be allowed to trigger a build.',
        type: 'string',
        default:'source.flow, source.json'
    },

}
<|endoftext|>