<commit_before>
import { NativeModules, Image } from 'react-native';
import uuid from 'uuid/v1';

const { RNImageRecognition, RNTensorFlowInference, RNTensorFlowGraph, RNTensorFlowGraphOperations } = NativeModules;

class TensorFlowOperation {
  constructor(id, opName) {
    this.id = id
    this.opName = opName
  }

  inputListLength(name) {
    return RNTensorFlowGraphOperations.inputListLength(this.id, this.opName, name);
  }

  name() {
    return RNTensorFlowGraphOperations.name(this.id, this.opName)
  }

  numOutputs() {
    return RNTensorFlowGraphOperations.numOutputs(this.id, this.opName)
  }

  output(index) {
    return RNTensorFlowGraphOperations.output(this.id, this.opName, index)
  }

  outputList(index, length) {
    return RNTensorFlowGraphOperations.outputList(this.id, this.opName, index, length)
  }

  outputListLength(name) {
    return RNTensorFlowGraphOperations.outputListLength(this.id, this.opName, name)
  }

  type() {
    return RNTensorFlowGraphOperations.type(this.id, this.opName)
  }
}

class TensorFlowGraph {
  constructor(id) {
    this.id = id
  }

  importGraphDef(graphDef) {
    return RNTensorFlowGraph.importGraphDef(this.id, graphDef)
  }

  importGraphDefWithPrefix(graphDef, prefix) {
    return RNTensorFlowGraph.importGraphDefWithPrefix(this.id, graphDef, prefix)
  }

  toGraphDef() {
    return RNTensorFlowGraph.toGraphDef(this.id)
  }

  operation(name) {
    return new TensorFlowOperation(this.id, name)
  }

  close() {
    return RNTensorFlowGraph.close(this.id)
  }
}

class TensorFlowInference {

  constructor(modelLocation) {
    this.id = uuid()
    const resolvedModelLocation = Image.resolveAssetSource(modelLocation) != null
      ? Image.resolveAssetSource(modelLocation).uri
      : modelLocation
    this.init = RNTensorFlowInference.initTensorFlowInference(this.id, resolvedModelLocation)
    this.tfGraph = new TensorFlowGraph(this.id)
  }

  async feed(data) {
    await this.init
    return RNTensorFlowInference.feed(this.id, data)
  }

  async run(outputNames, withStats) {
    await this.init
    return RNTensorFlowInference.run(this.id, outputNames, withStats !== undefined ? withStats : false)
  }

  async fetch(outputName) {
    await this.init
    return RNTensorFlowInference.fetch(this.id, outputName)
  }

  async graph() {
    await this.init
    return this.tfGraph
  }

  async close() {
    await this.init
    return RNTensorFlowInference.close(this.id)
  }
}

class ImageRecognition {
  constructor(data) {
    this.id = uuid()
    data['model'] = Image.resolveAssetSource(data['model']) != null
      ? Image.resolveAssetSource(data['model']).uri
      : data['model']

    data['label'] = Image.resolveAssetSource(data['label']) != null
      ? Image.resolveAssetSource(data['label']).uri
      : data['label']

    this.init = RNImageRecognition.initImageRecognizer(this.id, data)
  }

  async recognize(data) {
    await this.init

    data['image'] = Image.resolveAssetSource(data['image']) != null
      ? Image.resolveAssetSource(data['image']).uri
      : data['image']

    return RNTensorFlowInference.feed(this.id, data)
  }
}

export TensorFlowInference;
export ImageRecognition;
<commit_msg>Rename label to labels<commit_after>
import { NativeModules, Image } from 'react-native';
import uuid from 'uuid/v1';

const { RNImageRecognition, RNTensorFlowInference, RNTensorFlowGraph, RNTensorFlowGraphOperations } = NativeModules;

class TensorFlowOperation {
  constructor(id, opName) {
    this.id = id
    this.opName = opName
  }

  inputListLength(name) {
    return RNTensorFlowGraphOperations.inputListLength(this.id, this.opName, name);
  }

  name() {
    return RNTensorFlowGraphOperations.name(this.id, this.opName)
  }

  numOutputs() {
    return RNTensorFlowGraphOperations.numOutputs(this.id, this.opName)
  }

  output(index) {
    return RNTensorFlowGraphOperations.output(this.id, this.opName, index)
  }

  outputList(index, length) {
    return RNTensorFlowGraphOperations.outputList(this.id, this.opName, index, length)
  }

  outputListLength(name) {
    return RNTensorFlowGraphOperations.outputListLength(this.id, this.opName, name)
  }

  type() {
    return RNTensorFlowGraphOperations.type(this.id, this.opName)
  }
}

class TensorFlowGraph {
  constructor(id) {
    this.id = id
  }

  importGraphDef(graphDef) {
    return RNTensorFlowGraph.importGraphDef(this.id, graphDef)
  }

  importGraphDefWithPrefix(graphDef, prefix) {
    return RNTensorFlowGraph.importGraphDefWithPrefix(this.id, graphDef, prefix)
  }

  toGraphDef() {
    return RNTensorFlowGraph.toGraphDef(this.id)
  }

  operation(name) {
    return new TensorFlowOperation(this.id, name)
  }

  close() {
    return RNTensorFlowGraph.close(this.id)
  }
}

class TensorFlowInference {

  constructor(modelLocation) {
    this.id = uuid()
    const resolvedModelLocation = Image.resolveAssetSource(modelLocation) != null
      ? Image.resolveAssetSource(modelLocation).uri
      : modelLocation
    this.init = RNTensorFlowInference.initTensorFlowInference(this.id, resolvedModelLocation)
    this.tfGraph = new TensorFlowGraph(this.id)
  }

  async feed(data) {
    await this.init
    return RNTensorFlowInference.feed(this.id, data)
  }

  async run(outputNames, withStats) {
    await this.init
    return RNTensorFlowInference.run(this.id, outputNames, withStats !== undefined ? withStats : false)
  }

  async fetch(outputName) {
    await this.init
    return RNTensorFlowInference.fetch(this.id, outputName)
  }

  async graph() {
    await this.init
    return this.tfGraph
  }

  async close() {
    await this.init
    return RNTensorFlowInference.close(this.id)
  }
}

class ImageRecognition {
  constructor(data) {
    this.id = uuid()
    data['model'] = Image.resolveAssetSource(data['model']) != null
      ? Image.resolveAssetSource(data['model']).uri
      : data['model']

    data['labels'] = Image.resolveAssetSource(data['labels']) != null
      ? Image.resolveAssetSource(data['labels']).uri
      : data['labels']

    this.init = RNImageRecognition.initImageRecognizer(this.id, data)
  }

  async recognize(data) {
    await this.init

    data['image'] = Image.resolveAssetSource(data['image']) != null
      ? Image.resolveAssetSource(data['image']).uri
      : data['image']

    return RNTensorFlowInference.feed(this.id, data)
  }
}

export TensorFlowInference;
export ImageRecognition;
<|endoftext|>


<commit_before>/*!
 * Jade - Compiler
 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var oldCompiler = require('jade').Compiler;
var transformers = require('transformers');

/**
 * Initialize `Compiler` with the given `node`.
 *
 * @param {Node} node
 * @param {Object} options
 * @api public
 */

var Compiler = function Compiler(node, options) {
  oldCompiler.apply(this, arguments);
};

/**
 * Compiler prototype.
 */

Compiler.prototype = Object.create(oldCompiler.prototype);
Compiler.prototype.constructor = Compiler;

  /**
   * Compile parse tree to JavaScript.
   *
   * @api public
   */

Compiler.prototype.compile = function(){
  this.buf = ['var interp;'];
  if (this.pp) this.buf.push("var __indent = [];");
  this.lastBufferedIdx = -1;
  this.buf.push('var filter_mixin = (' + filter.toString() + '())');
  this.visit(this.node);
  return this.buf.join('\n');
};

function filter() {
  var nested = 0;
  return function (type, options) {
    if (0 === nested++) {
      if (helpers.transformers[type].outputFormat === 'css') {
        buf.push('<style type="text/css">')
      } else if (helpers.transformers[type].outputFormat === 'js') {
        buf.push('<script>')
      }
    }
    var oldBuf = buf, oldIndent = __indent; buf = [];__indent = [];
    this.block()
    oldBuf.push(helpers.transformers[type].renderSync(buf.join(''), options || this.attributes));
    buf = oldBuf; __indent = oldIndent;
    if (0 === --nested) {
      if (helpers.transformers[type].outputFormat === 'css') {
        buf.push('</style>')
      } else if (helpers.transformers[type].outputFormat === 'js') {
        buf.push('</script>')
      }
    }
  }
}

module.exports = function (obj) {
  obj = obj || {};
  obj.compiler = Compiler;
  obj.transformers = transformers;
  return obj;
};

module.exports.include = ('-var filter_mixin = (' + filter.toString() + '())').replace(/\n/g,'');
module.exports.helpers = { transformers: transformers; };<commit_msg>SyntaxError: Unexpected token ; <commit_after>/*!
 * Jade - Compiler
 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var oldCompiler = require('jade').Compiler;
var transformers = require('transformers');

/**
 * Initialize `Compiler` with the given `node`.
 *
 * @param {Node} node
 * @param {Object} options
 * @api public
 */

var Compiler = function Compiler(node, options) {
  oldCompiler.apply(this, arguments);
};

/**
 * Compiler prototype.
 */

Compiler.prototype = Object.create(oldCompiler.prototype);
Compiler.prototype.constructor = Compiler;

  /**
   * Compile parse tree to JavaScript.
   *
   * @api public
   */

Compiler.prototype.compile = function(){
  this.buf = ['var interp;'];
  if (this.pp) this.buf.push("var __indent = [];");
  this.lastBufferedIdx = -1;
  this.buf.push('var filter_mixin = (' + filter.toString() + '())');
  this.visit(this.node);
  return this.buf.join('\n');
};

function filter() {
  var nested = 0;
  return function (type, options) {
    if (0 === nested++) {
      if (helpers.transformers[type].outputFormat === 'css') {
        buf.push('<style type="text/css">')
      } else if (helpers.transformers[type].outputFormat === 'js') {
        buf.push('<script>')
      }
    }
    var oldBuf = buf, oldIndent = __indent; buf = [];__indent = [];
    this.block()
    oldBuf.push(helpers.transformers[type].renderSync(buf.join(''), options || this.attributes));
    buf = oldBuf; __indent = oldIndent;
    if (0 === --nested) {
      if (helpers.transformers[type].outputFormat === 'css') {
        buf.push('</style>')
      } else if (helpers.transformers[type].outputFormat === 'js') {
        buf.push('</script>')
      }
    }
  }
}

module.exports = function (obj) {
  obj = obj || {};
  obj.compiler = Compiler;
  obj.transformers = transformers;
  return obj;
};

module.exports.include = ('-var filter_mixin = (' + filter.toString() + '())').replace(/\n/g,'');
module.exports.helpers = { transformers: transformers };
<|endoftext|>


<commit_before>var configLocation = './notes/example-patterns-config';

var fs = require( 'fs' )
    , util = require( 'util' )
    , configFile = require( configLocation )
    , css = require( 'css' )
    , example = require( './notes/example-config')
    , async = require( 'async' )
    , commentParser = require( 'comment-parser' )
    ;
// run in the terminal using `node index.js`
module.exports = {

    configObj: {},

    config: require( './notes/parseFiles/input' ).patterns.sections,

    init: function( options ) {

        // var configData = this.configObj;

        this.readFile();

        this.getFiles(this.configObj);
        //this.writeFile();
    },
    getFiles: function( data ) {

        var configData = data
            , files;

        var glob = require("glob");

        // console.log(configData.config);
        // var key = Object.keys( configData );
        // // console.log(configFile[key].sections.length);

        // for ( var i = 0, l = data[key].sections.length; i < l; i++ ) {
        //     var sectObjs = data[key].sections[i];
        //     var ObjFiles = sectObjs.files;
        //     console.log('file name ', ObjFiles);

        //     if ( ObjFiles.indexOf( '*' ) > -1 ) {

        //         files = glob.sync( ObjFiles, { nodir: true, matchBase:true } );
        //         console.log(util.inspect(files, { depth:5, colors: true }));
        //     }
        //     else {
        //         var filesStat = fs.statSync( ObjFiles );
        //         var filesTest = filesStat.isFile();
        //         // console.log(filesTest);
        //         if ( filesTest === false ) {
        //             files = glob.sync( ObjFiles+'*', { nodir: true, matchBase:true } );
        //             console.log(util.inspect(files, { depth:5, colors: true }));
        //         }
        //     }
        // }
    },
    readFile: function() {
        //get the data and throw it into a variable that we can use to edit
        this.configObj = configFile;

        console.log( this.configObj );
        // console.log(this.configObj);

        // this.parseFiles();
    },
    parseFiles: function() {

        var sections = this.config;

        async.each( sections, this.parseFile, function() {

            console.log( 'DONE!', util.inspect( sections, { depth: 5, colors:true } ));

        });
    },
    parseFile: function( section, callback) {

        //internal function that parses using comment-parse on currentFile
        function parseComment( currentFile, data ) {

            // grab each comment block
            var comments = data.split( '/**' );

            // the first array item is always an empty string, so we shift
            comments.shift();

            for ( var i = 0; i < comments.length; i++ ) {

                // split blocks into comment and code content
                var block = comments[ i ].split(/^\s*\*\//m)
                    , toParse = '/**' + block[ 0 ] + ' */'
                    ;

                // add comment section to array
                comments[ i ] = commentParser( toParse )[ 0 ];

                // add code to data obj
                comments[ i ].code = block[ 1 ];
            }

            // now include path
            var push = {
                path: currentFile,
                data: comments
            };

            return push;
        }

        // only one file declared
        if ( typeof section.files === 'string' ) {

            var currentFile = section.files;

            fs.readFile( currentFile, { encoding: 'UTF8' }, function( err, data ) {

                section.files = [];
                section.files.push( parseComment( currentFile, data ));

                return callback( null );
            });
        }
        else {

            // array of files declared
            var files = section.files;
            section.files = [];

            async.each( files,
                function( item, callback ) {

                    var currentFile = item;

                    // read all files
                    fs.readFile( currentFile, { encoding: 'UTF8'}, function( err, data ) {

                        section.files.push( parseComment( currentFile, data ));

                        return callback( null );
                    });
                },
                function( err ) {

                    return callback( null );
                }
            );
        }
    }
};

module.exports.init();<commit_msg>finished get files module<commit_after>var configLocation = './notes/example-patterns-config';

var fs = require( 'fs' )
    , util = require( 'util' )
    , configFile = require( configLocation )
    , css = require( 'css' )
    , example = require( './notes/example-config')
    , async = require( 'async' )
    , commentParser = require( 'comment-parser' )
    ;
// run in the terminal using `node index.js`
module.exports = {

    configObj: {},

    config: require( './notes/parseFiles/input' ).patterns.sections,

    init: function( options ) {

        this.readFile();

        this.getFiles(this.configObj);

    },
    getFiles: function( data ) {

        var configData = data
            , files;

        var glob = require("glob");

        var key = Object.keys( configData );

        for ( var i = 0, l = configData[key].sections.length; i < l; i++ ) {
            var sectObjs = configData[key].sections[i];
            var ObjFiles = sectObjs.files;

            if ( ObjFiles.indexOf( '*' ) > -1 ) {

                files = glob.sync( ObjFiles, { nodir: true, matchBase:true } );
                configData[key].sections[i].files = files;

            }
            else {
                var filesStat = fs.statSync( ObjFiles );
                var filesTest = filesStat.isFile();
                if ( filesTest === false ) {
                    files = glob.sync( ObjFiles+'*', { nodir: true, matchBase:true } );
                    configData[key].sections[i].files = files;
                }
            }
        }

        console.log(configData.patterns.sections);
    },
    readFile: function() {
        //get the data and throw it into a variable that we can use to edit
        this.configObj = configFile;

        // console.log(this.configObj);

        this.parseFiles();
    },
    parseFiles: function() {

        var sections = this.config;

        async.each( sections, this.parseFile, function() {

            // console.log( 'DONE!', util.inspect( sections, { depth: 5, colors:true } ));

        });
    },
    parseFile: function( section, callback) {

        //internal function that parses using comment-parse on currentFile
        function parseComment( currentFile, data ) {

            // grab each comment block
            var comments = data.split( '/**' );

            // the first array item is always an empty string, so we shift
            comments.shift();

            for ( var i = 0; i < comments.length; i++ ) {

                // split blocks into comment and code content
                var block = comments[ i ].split(/^\s*\*\//m)
                    , toParse = '/**' + block[ 0 ] + ' */'
                    ;

                // add comment section to array
                comments[ i ] = commentParser( toParse )[ 0 ];

                // add code to data obj
                comments[ i ].code = block[ 1 ];
            }

            // now include path
            var push = {
                path: currentFile,
                data: comments
            };

            return push;
        }

        // only one file declared
        if ( typeof section.files === 'string' ) {

            var currentFile = section.files;

            fs.readFile( currentFile, { encoding: 'UTF8' }, function( err, data ) {

                section.files = [];
                section.files.push( parseComment( currentFile, data ));

                return callback( null );
            });
        }
        else {

            // array of files declared
            var files = section.files;
            section.files = [];

            async.each( files,
                function( item, callback ) {

                    var currentFile = item;

                    // read all files
                    fs.readFile( currentFile, { encoding: 'UTF8'}, function( err, data ) {

                        section.files.push( parseComment( currentFile, data ));

                        return callback( null );
                    });
                },
                function( err ) {

                    return callback( null );
                }
            );
        }
    }
};

module.exports.init();<|endoftext|>


<commit_before>function isOnCallback (str) {
  return typeof str === 'string' && /^on(.+)/.test(str)
}

/**
 * Function called recursively on all the object properties
 * If a property is a function we make it promisable
 * @param   { Object } parent - context where the apply method will be triggered
 * @param   { String } prop - property we are trying to get from the parent object
 * @returns { Proxy }
 */
function makePromisable (parent, prop) {
  return new Proxy(prop ? parent[prop] : parent, {
    get: (target, property) => {
      // no function no need for promises in return
      if (isOnCallback(property)) {
        // detect properties like
        // window.onload.then(() => console.log('loaded'))
        return new Promise((resolve) => {
          target[property] = resolve
        })
      } else if (typeof target[property] !== 'function') {
        return target[property]
      } else {
        // make proxy also the nested object properties
        return makePromisable(target, property)
      }
    },
    // this is cool to make promiseable event emitters
    //  and many other native node methods
    apply: (target, thisArg, argumentsList) => {
      return new Promise((resolve, reject) => {
        // guessing the timer functions from the type of arguments passed to the method
        const isTimer = !argumentsList.length || typeof argumentsList[0] === 'number'
        // assuming the callback will be always the second argument
        argumentsList.splice(isTimer ? 0 : 1, 0, resolve)
        Reflect.apply(target, parent, argumentsList)
      })
    }
  })
}

module.exports = exports.default = (object) => makePromisable(object)
<commit_msg>Return the value of the function call via `valueOf`<commit_after>function isOnCallback (str) {
  return typeof str === 'string' && /^on(.+)/.test(str)
}

/**
 * Function called recursively on all the object properties
 * If a property is a function we make it promisable
 * @param   { Object } parent - context where the apply method will be triggered
 * @param   { String } prop - property we are trying to get from the parent object
 * @returns { Proxy }
 */
function makePromisable (parent, prop) {
  return new Proxy(prop ? parent[prop] : parent, {
    get: (target, property) => {
      // no function no need for promises in return
      if (isOnCallback(property)) {
        // detect properties like
        // window.onload.then(() => console.log('loaded'))
        return new Promise((resolve) => {
          target[property] = resolve
        })
      } else if (typeof target[property] !== 'function') {
        return target[property]
      } else {
        // make proxy also the nested object properties
        return makePromisable(target, property)
      }
    },
    // this is cool to make promiseable event emitters
    //  and many other native node methods
    apply: (target, thisArg, argumentsList) => {
      let returnValue
      const promise = new Promise((resolve, reject) => {
        // guessing the timer functions from the type of arguments passed to the method
        const isTimer = !argumentsList.length || typeof argumentsList[0] === 'number'
        // assuming the callback will be always the second argument
        argumentsList.splice(isTimer ? 0 : 1, 0, resolve)
        returnValue = Reflect.apply(target, parent, argumentsList)
      })
      // Return the returnValue through valueOf
      promise.valueOf = _ => returnValue
      return promise
    }
  })
}

module.exports = exports.default = (object) => makePromisable(object)
<|endoftext|>


<commit_before>var through = require('through2'),
	datauri = require('datauri'),
	gutil = require('gulp-util'),
	path = require('path'),
	PluginError = gutil.PluginError;

// Name
const PLUGIN_NAME = 'gulp-inline-image';

module.exports = function (opts) {
	opts = opts || {};

	var rInlineImage = /inline-image\(['"]?([^'")]+)['"]?,?['"]?([^'")]+)?['"]?\)/mg;

	function inlineImage(file, encoding, callback) {

		if (file.isNull()) {
			return callback(null, file);
		}

		if (file.isStream()) {
			new PluginError(PLUGIN_NAME, 'This plugin does not support streams');
		}

		var baseDir = opts.baseDir || file.base,
			src = file.contents.toString(),
			match,
			dUri;

		while (match = rInlineImage.exec(src)) {
			dUri = datauri(path.resolve(baseDir, match[1].replace('/',path.sep)));
			if (match[2]) {
				// datauri has no option to give a MIME type, so we hack it in
				dUri = dUri.replace(/(data:)[^]+(;base64)/,'$1'+match[2]+'$2');
			}

			src = src.replace(match[0], 'url("'+dUri+'")');
		}

		file.contents = new Buffer(src);
		return callback(null, file);
	}

	return through.obj(inlineImage);
};
<commit_msg>Moved to datauri.sync for now<commit_after>var through = require('through2'),
	datauri = require('datauri').sync,
	gutil = require('gulp-util'),
	path = require('path'),
	PluginError = gutil.PluginError;

// Name
const PLUGIN_NAME = 'gulp-inline-image';

module.exports = function (opts) {
	opts = opts || {};

	var rInlineImage = /inline-image\(['"]?([^'")]+)['"]?,?['"]?([^'")]+)?['"]?\)/mg;

	function inlineImage(file, encoding, callback) {

		if (file.isNull()) {
			return callback(null, file);
		}

		if (file.isStream()) {
			new PluginError(PLUGIN_NAME, 'This plugin does not support streams');
		}

		var baseDir = opts.baseDir || file.base,
			src = file.contents.toString(),
			match,
			dUri;

		while (match = rInlineImage.exec(src)) {
			dUri = datauri(path.resolve(baseDir, match[1].replace('/',path.sep)));
			if (match[2]) {
				// datauri has no option to give a MIME type, so we hack it in
				dUri = dUri.replace(/(data:)[^]+(;base64)/,'$1'+match[2]+'$2');
			}

			src = src.replace(match[0], 'url("'+dUri+'")');
		}

		file.contents = new Buffer(src);
		return callback(null, file);
	}

	return through.obj(inlineImage);
};
<|endoftext|>


<commit_before>/*
 *  Babel plugin to remove unwanted `import` declarations when building
 *  packages with babel transforms.
 *
 *  PLEASE USE WITH COUTION and check your RegExp expressions carefully.
 */

module.exports = function (regex) {
    return function(babel) {
        return new babel.Transformer('babel-plugin-remove-imports', {
            ImportDeclaration: function (node, parent) {

                //node.source.value contains the import declaration
                var text = node.source.value;

                //convert regex to Array of regexp if we have a single item
                if(!(regex instanceof Array)) {
                    regex = [regex];
                }

                //iterate over all regexps to find a truthy one,
                //when found, remove the `import` node from the code
                for(var i = 0, len = regex.length; i < len; i++) {
                    if(isRegexExpressionTruthy(text, regex[i])) {
                        this.dangerouslyRemove();
                        break;
                    }
                }
            }
        });
    }
};

//check whether the text (import declaration) is matches the given regex
function isRegexExpressionTruthy(text, regex) {
    return (regex instanceof RegExp) ? regex.test(text) : false;
}
<commit_msg>Typo fixes<commit_after>/*
 *  Babel plugin to remove unwanted `import` declarations when building
 *  packages with babel transforms.
 *
 *  PLEASE USE WITH CAUTION and check your RegExp expressions carefully.
 */

module.exports = function (regex) {
    return function(babel) {
        return new babel.Transformer('babel-plugin-remove-imports', {
            ImportDeclaration: function (node, parent) {

                //node.source.value contains the import declaration
                var text = node.source.value;

                //convert regex to Array of regexp if we have a single item
                if(!(regex instanceof Array)) {
                    regex = [regex];
                }

                //iterate over all regexps to find a truthy one,
                //when found, remove the `import` node from the code
                for(var i = 0, len = regex.length; i < len; i++) {
                    if(isRegexExpressionTruthy(text, regex[i])) {
                        this.dangerouslyRemove();
                        break;
                    }
                }
            }
        });
    }
};

//check whether the text (import declaration) matches the given regex
function isRegexExpressionTruthy(text, regex) {
    return (regex instanceof RegExp) ? regex.test(text) : false;
}
<|endoftext|>


<commit_before>var stream = require('stream'),
    fs = require('fs'),
    util = require('util'),
    events = require('events');

var Parser = function(fileName, options) {
  var self = this;
  this.fileName   = fileName;
  this.header     = this.getHeader();
  this.fieldsCnt  = this.header.fields.length;
  this.parseTypes = true;

  if (options) {
    if ( options.parseTypes != undefined )
      this.parseTypes = options.parseTypes;
  }

  var hNumRecs  = this.header.numberOfRecords
    , hRecLen   = this.header.recordLength
    , hDataSize = hNumRecs * hRecLen;

  var seqNumber  = 0
    , skipBytes  = this.header.headerLength
    , byteReades = 0
    , buffer     = new Buffer(0);

  this.stream = new stream.Transform({ 'objectMode': true });
  this.stream._transform = function( chunk, encoding, done ) {
    var buffPos = 0
      , buffLen = 0
      , rec;
    buffer  = Buffer.concat([ buffer, chunk ]);
    buffLen = buffer.length;

    if ( skipBytes ) {
      if( skipBytes >= buffLen ) {
        skipBytes = skipBytes - buffLen;
        done();
        return;
      }
      buffPos   = skipBytes;
      skipBytes = 0;
    }

    while ( byteReades<hDataSize && (buffPos+hRecLen)<=buffLen ) {
      rec = self.parseRecord(
              ++seqNumber,
              buffer.slice( buffPos, buffPos+hRecLen )
      );
      buffPos += hRecLen;
      byteReades += hRecLen;
      this.push( rec );
    }

    buffer = buffer.slice( buffPos, buffLen );
    done();
  };

  fs.createReadStream(this.fileName).pipe(this.stream);
};

util.inherits(Parser, events.EventEmitter);

Parser.prototype.parseRecord = function(sequenceNumber, buffer) {
  var self = this;

  var record = {
    '@sequenceNumber': sequenceNumber,
    '@deleted'       : buffer[0] !== 32
  };
  for ( var i=0, pos=1, fld; i < this.fieldsCnt; i++ ) {
    fld = this.header.fields[i];
    record[fld.name] = self.parseField( fld, buffer.slice(pos, pos+fld.length) );
    pos += fld.length;
  }
  return record;
};

Parser.prototype.parseField = function(field, buffer) {
  var st  = 0
    , end = buffer.length;
  while( end>st && buffer[end-1]===32 ) end--;
  while( st<end && buffer[st   ]===32 ) st++;

  if( field.raw ) {
        return buffer.slice( st, end );
  }

  var data = buffer.toString( 'utf-8', st, end );
  if ( this.parseTypes ) {
    if ( field.type==='N' || field.type==='F' ) {
      data = Number( data );
    }
  }

  return data;
};

Parser.prototype.getHeader = function() {
  var fd = fs.openSync( this.fileName, 'r' )
    , buff = new Buffer( 32 )
    , header;
  fs.readSync( fd, buff, 0, 32, 0 );
  header = this.parseBaseHeader( buff );
  buff = new Buffer( header.headerLength );
  fs.readSync( fd, buff, 0, header.headerLength, 0 );
  this.parseFieldsHeader( header, buff );
  fs.closeSync( fd );
  return header;
};

Parser.prototype.parseBaseHeader = function(data) {
  var header = {
    'version'        : data.readUInt8  (  0, true ),
    'dateUpdated'    : this.parseHeaderDate( data.slice(1, 4) ),
    'numberOfRecords': data.readInt32LE(  4, true ),
    'headerLength'   : data.readInt16LE(  8, true ),
    'recordLength'   : data.readInt16LE( 10, true ),
    'fields'         : []
  };
  return header;
};

Parser.prototype.parseFieldsHeader = function(header, data) {
  var fieldData = [];
  for (var i = 32; i <= header.headerLength-32; i += 32) {
    fieldData.push( data.slice(i, i + 32) );
  }

  header.fields = fieldData.map(this.parseFieldSubRecord);
};

Parser.prototype.parseHeaderDate = function(buffer) {
  var day   = buffer.readUInt8( 0, true ) + 1900
    , month = buffer.readUInt8( 1, true ) - 1
    , year  = buffer.readUInt8( 2, true );
  return new Date( year, month, day );
};

Parser.prototype.parseFieldSubRecord = function(buffer) {
  var field = {
    'name'         : buffer.toString( 'utf-8',  0, 11 ).replace( /\x00+$/, '' ),
    'type'         : buffer.toString( 'utf-8', 11, 12 ),
    'displacement' : buffer.readInt32LE( 12, true ),
    'length'       : buffer.readUInt8( 16, true ),
    'decimalPlaces': buffer.readUInt8( 17, true ),
    'indexFlag'    : buffer.readUInt8( 31, true )
  };
  return field;
};

module.exports = Parser;
<commit_msg>option for return value can be array (it's 50% faster than object)<commit_after>var stream = require('stream'),
    fs = require('fs'),
    util = require('util'),
    events = require('events');

var Parser = function(fileName, options) {
  var self = this;
  this.fileName   = fileName;
  this.header     = this.getHeader();
  this.fieldsCnt  = this.header.fields.length;
  this.parseTypes = true;
  this.recAsArray = false;

  if (options) {
    if ( options.parseTypes != undefined )
      this.parseTypes = options.parseTypes;
    if ( options.recAsArray != undefined )
      this.recAsArray = options.recAsArray;
  }

  var hNumRecs  = this.header.numberOfRecords
    , hRecLen   = this.header.recordLength
    , hDataSize = hNumRecs * hRecLen;

  var seqNumber  = 0
    , skipBytes  = this.header.headerLength
    , byteReades = 0
    , buffer     = new Buffer(0);

  this.stream = new stream.Transform({ 'objectMode': true });
  this.stream._transform = function( chunk, encoding, done ) {
    var buffPos = 0
      , buffLen = 0
      , rec;
    buffer  = Buffer.concat([ buffer, chunk ]);
    buffLen = buffer.length;

    if ( skipBytes ) {
      if( skipBytes >= buffLen ) {
        skipBytes = skipBytes - buffLen;
        done();
        return;
      }
      buffPos   = skipBytes;
      skipBytes = 0;
    }

    while ( byteReades<hDataSize && (buffPos+hRecLen)<=buffLen ) {
      if( self.recAsArray ) {
        rec = self.parseRecordToArray(
                ++seqNumber,
                buffer.slice( buffPos, buffPos+hRecLen )
        );
      }
      else {
        rec = self.parseRecordToObject(
                ++seqNumber,
                buffer.slice( buffPos, buffPos+hRecLen )
        );
      }
      buffPos += hRecLen;
      byteReades += hRecLen;
      this.push( rec );
    }

    buffer = buffer.slice( buffPos, buffLen );
    done();
  };

  fs.createReadStream(this.fileName).pipe(this.stream);
};

util.inherits(Parser, events.EventEmitter);

Parser.prototype.parseRecordToObject = function(sequenceNumber, buffer) {
  var record = {
    '@sequenceNumber': sequenceNumber,
    '@deleted'       : buffer[0] !== 32
  };
  for ( var i=0, pos=1, fld; i < this.fieldsCnt; i++ ) {
    fld = this.header.fields[i];
    record[fld.name] = this.parseField( fld, buffer.slice(pos, pos+fld.length) );
    pos += fld.length;
  }
  return record;
};

Parser.prototype.parseRecordToArray = function(sequenceNumber, buffer) {
  var record = new Array( this.fieldsCnt+2 );
  record[0] = sequenceNumber;
  record[1] = buffer[0] !== 32;
  for ( var i=0, pos=1, fld; i < this.fieldsCnt; i++ ) {
    fld = this.header.fields[i];
    record[i+2] = this.parseField( fld, buffer.slice(pos, pos+fld.length) );
    pos += fld.length;
  }
  return record;
};

Parser.prototype.parseField = function(field, buffer) {
  var st  = 0
    , end = buffer.length;
  while( end>st && buffer[end-1]===32 ) end--;
  while( st<end && buffer[st   ]===32 ) st++;

  if( field.raw ) {
        return buffer.slice( st, end );
  }

  var data = buffer.toString( 'utf-8', st, end );
  if ( this.parseTypes ) {
    if ( field.type==='N' || field.type==='F' ) {
      data = Number( data );
    }
  }

  return data;
};

Parser.prototype.getHeader = function() {
  var fd = fs.openSync( this.fileName, 'r' )
    , buff = new Buffer( 32 )
    , header;
  fs.readSync( fd, buff, 0, 32, 0 );
  header = this.parseBaseHeader( buff );
  buff = new Buffer( header.headerLength );
  fs.readSync( fd, buff, 0, header.headerLength, 0 );
  this.parseFieldsHeader( header, buff );
  fs.closeSync( fd );
  return header;
};

Parser.prototype.parseBaseHeader = function(data) {
  var header = {
    'version'        : data.readUInt8  (  0, true ),
    'dateUpdated'    : this.parseHeaderDate( data.slice(1, 4) ),
    'numberOfRecords': data.readInt32LE(  4, true ),
    'headerLength'   : data.readInt16LE(  8, true ),
    'recordLength'   : data.readInt16LE( 10, true ),
    'fields'         : []
  };
  return header;
};

Parser.prototype.parseFieldsHeader = function(header, data) {
  var fieldData = [];
  for (var i = 32; i <= header.headerLength-32; i += 32) {
    fieldData.push( data.slice(i, i + 32) );
  }

  header.fields = fieldData.map(this.parseFieldSubRecord);
};

Parser.prototype.parseHeaderDate = function(buffer) {
  var day   = buffer.readUInt8( 0, true ) + 1900
    , month = buffer.readUInt8( 1, true ) - 1
    , year  = buffer.readUInt8( 2, true );
  return new Date( year, month, day );
};

Parser.prototype.parseFieldSubRecord = function(buffer) {
  var field = {
    'name'         : buffer.toString( 'utf-8',  0, 11 ).replace( /\x00+$/, '' ),
    'type'         : buffer.toString( 'utf-8', 11, 12 ),
    'displacement' : buffer.readInt32LE( 12, true ),
    'length'       : buffer.readUInt8( 16, true ),
    'decimalPlaces': buffer.readUInt8( 17, true ),
    'indexFlag'    : buffer.readUInt8( 31, true )
  };
  return field;
};

module.exports = Parser;
<|endoftext|>


<commit_before>var express = require('express')
var app = express()

app.set('port', (process.env.PORT || 5000))

app.configure(function() {
	app.use(express.bodyParser())
	app.use(app.router)
})

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extendd: false})

 // parse application/json
 app.use(bodyParser.json())

app.get('/', function (req, res) {
	res.send('Hello World! I am new born bot!')
})

// for facebook verification
app.get('/webhook/', function (req, res) {
	if (req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
		res.send(req.query['hub.challenge'])
	}
	res.send('Error, wrong token')
})

// to post data
app.post('/webhook/', function (req, res) {
	console.log(req.body)
	res.sendStatus(200)
})

app.listen(app.get('port'), function() {
	console.log('running on port', app.get('port'))
})
<commit_msg>missing parenthesis<commit_after>var express = require('express')
var app = express()

app.set('port', (process.env.PORT || 5000))

app.configure(function() {
	app.use(express.bodyParser())
	app.use(app.router)
})

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extendd: false}))

 // parse application/json
 app.use(bodyParser.json())

app.get('/', function (req, res) {
	res.send('Hello World! I am new born bot!')
})

// for facebook verification
app.get('/webhook/', function (req, res) {
	if (req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
		res.send(req.query['hub.challenge'])
	}
	res.send('Error, wrong token')
})

// to post data
app.post('/webhook/', function (req, res) {
	console.log(req.body)
	res.sendStatus(200)
})

app.listen(app.get('port'), function() {
	console.log('running on port', app.get('port'))
})
<|endoftext|>


<commit_before>module.exports = {
    "defaultSeverity": "warning",
    "rules": {
        "color-hex-case": "upper",
        "color-hex-length": "short",
        "color-named": "never",
        "color-no-hex": null,

        "font-family-name-quotes": null,
        "font-weight-notation": "named-where-possible",

        "function-comma-newline-after": "never-multi-line",
        "function-comma-newline-before": "never-multi-line",
        "function-comma-space-after": "always",
        "function-comma-space-before": "never",
        "function-max-empty-lines": 0,
        "function-name-case": "lower",
        "function-parentheses-newline-inside": "never-multi-line",
        "function-parentheses-space-inside": null,
        "function-url-quotes": "always",
        "function-whitespace-after": "always",

        "number-leading-zero": "always",
        "number-max-precision": 6,

        "string-quotes": "single",

        "length-zero-no-unit": true,

        "unit-case": "lower",

        "value-keyword-case": null,
        "value-no-vendor-prefix": true,
        "value-list-comma-newline-after": "never-multi-line",
        "value-list-comma-newline-before": "never-multi-line",
        "value-list-comma-space-after": null,
        "value-list-comma-space-before": "never",
        "value-list-max-empty-lines": 0,

        "property-case": "lower",

        "declaration-bang-space-after": "never",
        "declaration-bang-space-before": "always",
        "declaration-colon-space-after": "always",
        "declaration-colon-space-before": "never",
        "declaration-block-properties-order": [
            {
                "order": "strict",
                "properties": [
                    "position",
                    "top",
                    "right",
                    "bottom",
                    "left",
                    "z-index"
                ]
            },
            {
                "order": "strict",
                "properties": [
                    "float",
                    "clear"
                ]
            },
            {
                "order": "strict",
                "properties": [
                    "flex",
                    "flex-basis",
                    "flex-direction",
                    "flex-flow",
                    "flex-grow",
                    "flex-shrink",
                    "flex-wrap",
                    "align-content",
                    "align-items",
                    "align-self",
                    "justify-content",
                    "order"
                ]
            },
            {
                "order": "strict",
                "properties": [
                    "box-sizing",
                    "display",
                    "overflow",
                    "overflow-x",
                    "overflow-y"
                ]
            },
            {
                "order": "strict",
                "properties": [
                    "width",
                    "min-width",
                    "max-width",
                    "height",
                    "min-height",
                    "max-height"
                ]
            },
            {
                "order": "strict",
                "properties": [
                    "margin",
                    "margin-top",
                    "margin-right",
                    "margin-bottom",
                    "margin-left",
                    "padding",
                    "padding-top",
                    "padding-right",
                    "padding-bottom",
                    "padding-left"
                ]
            },
            {
                "order": "flexible",
                "properties": [
                    "columns",
                    "column-gap",
                    "column-fill",
                    "column-rule",
                    "column-span",
                    "column-count",
                    "column-width"
                ]
            },
            {
                "order": "strict",
                "properties": [
                    "color",
                    "font",
                    "font-family",
                    "font-size",
                    "font-smoothing",
                    "font-style",
                    "font-variant",
                    "font-weight",
                    "font-feature-settings",
                    "letter-spacing",
                    "line-height",
                    "list-style",
                    "text-align",
                    "text-decoration",
                    "text-indent",
                    "text-overflow",
                    "text-rendering",
                    "text-shadow",
                    "text-transform",
                    "text-wrap",
                    "white-space",
                    "word-spacing",
                    "word-wrap"
                ]
            },
            {
                "order": "strict",
                "properties": [
                    "background",
                    "background-clip",
                    "background-color",
                    "background-image",
                    "background-position",
                    "background-size",
                    "background-repeat",
                    "border",
                    "border-top",
                    "border-right",
                    "border-bottom",
                    "border-left",
                    "border-width",
                    "border-top-width",
                    "border-right-width",
                    "border-bottom-width",
                    "border-left-width",
                    "border-style",
                    "border-top-style",
                    "border-right-style",
                    "border-bottom-style",
                    "border-left-style",
                    "border-radius",
                    "border-top-left-radius",
                    "border-top-right-radius",
                    "border-bottom-left-radius",
                    "border-bottom-right-radius",
                    "border-color",
                    "border-top-color",
                    "border-right-color",
                    "border-bottom-color",
                    "border-left-color",
                    "outline",
                    "outline-color",
                    "outline-offset",
                    "outline-style",
                    "outline-width",
                    "border-collapse",
                    "border-spacing",
                    "box-shadow"
                ]
            },
            {
                "order": "flexible",
                "properties": [
                    "caption-side",
                    "content",
                    "cursor",
                    "empty-cells",
                    "opacity",
                    "quotes",
                    "speak",
                    "table-layout",
                    "vertical-align",
                    "visibility"
                ]
            },
            {
                "order": "strict",
                "properties": [
                    "transform",
                    "transition"
                ]
            }
        ],
        "declaration-block-semicolon-newline-after": "always-multi-line",
        "declaration-block-semicolon-newline-before": "never-multi-line",
        "declaration-block-semicolon-space-after": "always-single-line",
        "declaration-block-semicolon-space-before": "never",
        "declaration-block-single-line-max-declarations": null,
        "declaration-block-trailing-semicolon": "always",

        "block-closing-brace-empty-line-before": "never",
        "block-closing-brace-newline-after": ["always", { "ignoreAtRules": ["if", "else"] }],
        "block-closing-brace-newline-before": "always-multi-line",
        "block-closing-brace-space-after": null,
        "block-closing-brace-space-before": "always-single-line",
        "block-no-single-line": null,
        "block-opening-brace-newline-after": "always-multi-line",
        "block-opening-brace-newline-before": null,
        "block-opening-brace-space-after": "always-single-line",
        "block-opening-brace-space-before": "always",

        "selector-attribute-brackets-space-inside": "never",
        "selector-attribute-operator-space-after": "never",
        "selector-attribute-operator-space-before": "never",
        "selector-attribute-quotes": "always",
        "selector-combinator-space-after": "always",
        "selector-combinator-space-before": "always",
        "selector-descendant-combinator-no-non-space": true,
        "selector-max-compound-selectors": 3,
        "selector-max-specificity": "0,3,1",
        "selector-no-attribute": null,
        "selector-no-combinator": null,
        "selector-no-id": true,
        "selector-no-qualifying-type": [true, { "ignore": ["attribute", "class"] }],
        "selector-no-type": null,
        "selector-no-universal": null,
        "selector-no-vendor-prefix": true,
        "selector-pseudo-class-case": "lower",
        "selector-pseudo-class-no-unknown": true,
        "selector-pseudo-class-parentheses-space-inside": "never",
        "selector-pseudo-element-case": "lower",
        "selector-pseudo-element-colon-notation": "double",
        "selector-pseudo-element-no-unknown": true,
        "selector-root-no-composition": true,
        "selector-type-case":"lower",
        "selector-type-no-unknown":true,
        "selector-max-empty-lines": 0,

        "selector-list-comma-newline-after": "always-multi-line",
        "selector-list-comma-newline-before": "never-multi-line",
        "selector-list-comma-space-after": "always-single-line",
        "selector-list-comma-space-before": "never",

        "root-no-standard-properties":true,

        "rule-nested-empty-line-before": null,
        "rule-non-nested-empty-line-before": ["always", { "except":["after-single-line-comment"] }],

        "media-feature-colon-space-after": "always",
        "media-feature-colon-space-before": "never",
        "media-feature-name-case": "lower",
        "media-feature-name-no-unknown": true,
        "media-feature-name-no-vendor-prefix": true,
        "media-feature-no-missing-punctuation": true,
        "media-feature-range-operator-space-after": "always",
        "media-feature-range-operator-space-before": "always",

        "media-query-list-comma-newline-after": "never-multi-line",
        "media-query-list-comma-newline-before": "never-multi-line",
        "media-query-list-comma-space-after": "always",
        "media-query-list-comma-space-before": "never",

        "at-rule-empty-line-before": ["always", { "except": ["first-nested"], "ignore": ["blockless-after-same-name-blockless"], "ignoreAtRules": ["else"]}],
        "at-rule-name-case":"lower",
        "at-rule-name-newline-after": null,
        "at-rule-name-space-after": "always",
        "at-rule-no-unknown": null,
        "at-rule-no-vendor-prefix": true,
        "at-rule-semicolon-newline-after": "always",

        "stylelint-disable-reason": null,

        "comment-empty-line-before": null,
        "comment-no-empty": true,
        "comment-whitespace-inside": null,

        "indentation": "tab",
        "max-empty-lines": 2,
		"max-line-length": [80, { "ignore": ["comments"] }],
        "max-nesting-depth": 4,
        "no-browser-hacks": null,
        "no-descending-specificity": null,
        "no-duplicate-selectors": true,
        "no-empty-source": true,
        "no-eol-whitespace": true,
        "no-extra-semicolons": true,
        "no-indistinguishable-colors": null,
        "no-invalid-double-slash-comments": null,
        "no-missing-end-of-source-newline":true,
        "no-unknown-animations": true,
        "no-unsupported-browser-features": null
    }
}
<commit_msg>Minor visual update<commit_after>module.exports = {
	"defaultSeverity": "warning",
	"rules": {
		"color-hex-case": "upper",
		"color-hex-length": "short",
		"color-named": "never",
		"color-no-hex": null,

		"font-family-name-quotes": null,
		"font-weight-notation": "named-where-possible",

		"function-comma-newline-after": "never-multi-line",
		"function-comma-newline-before": "never-multi-line",
		"function-comma-space-after": "always",
		"function-comma-space-before": "never",
		"function-max-empty-lines": 0,
		"function-name-case": "lower",
		"function-parentheses-newline-inside": "never-multi-line",
		"function-parentheses-space-inside": null,
		"function-url-quotes": "always",
		"function-whitespace-after": "always",

		"number-leading-zero": "always",
		"number-max-precision": 6,

		"string-quotes": "single",

		"length-zero-no-unit": true,

		"unit-case": "lower",

		"value-keyword-case": null,
		"value-no-vendor-prefix": true,
		"value-list-comma-newline-after": "never-multi-line",
		"value-list-comma-newline-before": "never-multi-line",
		"value-list-comma-space-after": null,
		"value-list-comma-space-before": "never",
		"value-list-max-empty-lines": 0,

		"property-case": "lower",

		"declaration-bang-space-after": "never",
		"declaration-bang-space-before": "always",
		"declaration-colon-space-after": "always",
		"declaration-colon-space-before": "never",
		"declaration-block-properties-order": [
			"position",
			"top",
			"right",
			"bottom",
			"left",
			"z-index",

			"float",
			"clear",

			"flex",
			{
				"order": "flexible",
				"properties": [
					"flex-basis",
					"flex-direction",
					"flex-flow",
					"flex-grow",
					"flex-shrink",
					"flex-wrap",
					"align-content",
					"align-items",
					"align-self",
					"justify-content",
					"order"
				]
			},

			"box-sizing",
			"display",
			"overflow",
			"overflow-x",
			"overflow-y",

			"width",
			"min-width",
			"max-width",

			"height",
			"min-height",
			"max-height",

			"margin",
			"margin-top",
			"margin-right",
			"margin-bottom",
			"margin-left",
			"padding",
			"padding-top",
			"padding-right",
			"padding-bottom",
			"padding-left",

			"columns",
			"column-gap",
			"column-fill",
			"column-rule",
			"column-span",
			"column-count",
			"column-width",

			"color",
			"font",
			"font-family",
			"font-size",
			"font-smoothing",
			"font-style",
			"font-variant",
			"font-weight",
			"font-feature-settings",

			"letter-spacing",
			"line-height",
			"list-style",

			"text-align",
			"text-decoration",
			"text-indent",
			"text-overflow",
			"text-rendering",
			"text-shadow",
			"text-transform",
			"text-wrap",

			"white-space",
			"word-spacing",
			"word-wrap",

			"background",
			"background-clip",
			"background-color",
			"background-image",
			"background-position",
			"background-size",
			"background-repeat",
			"border",
			"border-top",
			"border-right",
			"border-bottom",
			"border-left",
			"border-width",
			"border-top-width",
			"border-right-width",
			"border-bottom-width",
			"border-left-width",
			"border-style",
			"border-top-style",
			"border-right-style",
			"border-bottom-style",
			"border-left-style",
			"border-radius",
			"border-top-left-radius",
			"border-top-right-radius",
			"border-bottom-left-radius",
			"border-bottom-right-radius",
			"border-color",
			"border-top-color",
			"border-right-color",
			"border-bottom-color",
			"border-left-color",
			"outline",
			"outline-color",
			"outline-offset",
			"outline-style",
			"outline-width",
			"border-collapse",
			"border-spacing",
			"box-shadow",

			{
				"order": "flexible",
				"properties": [
					"caption-side",
					"content",
					"cursor",
					"empty-cells",
					"opacity",
					"quotes",
					"speak",
					"table-layout",
					"vertical-align",
					"visibility"
				]
			},

			"transform",
			"transition"
		],
		"declaration-block-semicolon-newline-after": "always-multi-line",
		"declaration-block-semicolon-newline-before": "never-multi-line",
		"declaration-block-semicolon-space-after": "always-single-line",
		"declaration-block-semicolon-space-before": "never",
		"declaration-block-single-line-max-declarations": null,
		"declaration-block-trailing-semicolon": "always",

		"block-closing-brace-empty-line-before": "never",
		"block-closing-brace-newline-after": ["always", { "ignoreAtRules": ["if", "else"] }],
		"block-closing-brace-newline-before": "always-multi-line",
		"block-closing-brace-space-after": null,
		"block-closing-brace-space-before": "always-single-line",
		"block-no-single-line": null,
		"block-opening-brace-newline-after": "always-multi-line",
		"block-opening-brace-newline-before": null,
		"block-opening-brace-space-after": "always-single-line",
		"block-opening-brace-space-before": "always",

		"selector-attribute-brackets-space-inside": "never",
		"selector-attribute-operator-space-after": "never",
		"selector-attribute-operator-space-before": "never",
		"selector-attribute-quotes": "always",
		"selector-combinator-space-after": "always",
		"selector-combinator-space-before": "always",
		"selector-descendant-combinator-no-non-space": true,
		"selector-max-compound-selectors": 3,
		"selector-max-specificity": null,
		"selector-no-attribute": null,
		"selector-no-combinator": null,
		"selector-no-id": true,
		"selector-no-qualifying-type": [true, { "ignore": ["attribute"] }],
		"selector-no-type": null,
		"selector-no-universal": null,
		"selector-no-vendor-prefix": true,
		"selector-pseudo-class-case": "lower",
		"selector-pseudo-class-no-unknown": true,
		"selector-pseudo-class-parentheses-space-inside": "never",
		"selector-pseudo-element-case": "lower",
		"selector-pseudo-element-colon-notation": "double",
		"selector-pseudo-element-no-unknown": true,
		"selector-root-no-composition": true,
		"selector-type-case": "lower",
		"selector-type-no-unknown": true,
		"selector-max-empty-lines": 0,

		"selector-list-comma-newline-after": "always-multi-line",
		"selector-list-comma-newline-before": "never-multi-line",
		"selector-list-comma-space-after": "always-single-line",
		"selector-list-comma-space-before": "never",

		"root-no-standard-properties": true,

		"rule-nested-empty-line-before": null,
		"rule-non-nested-empty-line-before": ["always", { "except":["after-single-line-comment"] }],

		"media-feature-colon-space-after": "always",
		"media-feature-colon-space-before": "never",
		"media-feature-name-case": "lower",
		"media-feature-name-no-unknown": true,
		"media-feature-name-no-vendor-prefix": true,
		"media-feature-no-missing-punctuation": true,
		"media-feature-range-operator-space-after": "always",
		"media-feature-range-operator-space-before": "always",

		"media-query-list-comma-newline-after": "never-multi-line",
		"media-query-list-comma-newline-before": "never-multi-line",
		"media-query-list-comma-space-after": "always",
		"media-query-list-comma-space-before": "never",

		"at-rule-empty-line-before": ["always", { "except": ["first-nested"], "ignore": ["blockless-after-same-name-blockless"], "ignoreAtRules": ["else"]}],
		"at-rule-name-case": "lower",
		"at-rule-name-newline-after": null,
		"at-rule-name-space-after": "always",
		"at-rule-no-unknown": null,
		"at-rule-no-vendor-prefix": true,
		"at-rule-semicolon-newline-after": "always",

		"stylelint-disable-reason": null,

		"comment-empty-line-before": null,
		"comment-no-empty": true,
		"comment-whitespace-inside": null,

		"indentation": "tab",
		"max-empty-lines": 2,
		"max-line-length": [80, { "ignore": ["comments"] }],
		"max-nesting-depth": 4,
		"no-browser-hacks": null,
		"no-descending-specificity": null,
		"no-duplicate-selectors": true,
		"no-empty-source": true,
		"no-eol-whitespace": true,
		"no-extra-semicolons": true,
		"no-indistinguishable-colors": null,
		"no-invalid-double-slash-comments": null,
		"no-missing-end-of-source-newline": true,
		"no-unknown-animations": true,
		"no-unsupported-browser-features": null
	}
}
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var type = require('utils-type');
var which = require('which');
var findup = require('findup');
var findupSync = require('findup-sync');

exports = module.exports = whech;

// asynchronous version
//
function whech(name, cb){
  var o = getSpec(name);
  which(o.name, function(err, binPath){
    o.which = err || binPath; whechCommon(o);
    findup(o.cwd, o.configFile, function(err, configDir){
      o.configFile = err || path.join(configDir, o.configFile);
      cb(err, o);
    });
  });
}

// check input and give an object with the spec
//
function getSpec(name){
  var env = type(name).plainObject || {name: name};
  if(typeof env.name !== 'string' || !env.name.trim()){
    throw new TypeError('`o.name` should be  non emtpy string');
  }
  return env;
}

// common ops in sync and async version
//
function whechCommon(o){
  o.cwd = o.cwd || process.cwd();
  o.configFile = o.configFile || o.name + 'file';

  try {
    o.which = o.which || which.sync(o.name);
  } catch(err){ o.which = err; }

  var argv = process.argv;
  if(argv[1] && !(o.runFromBin = argv.indexOf(o.which) > -1)){
    o.configFile = path.basename(argv[1]);
    o.cwd = path.resolve(o.cwd, path.dirname(argv[1]));
  }

  if(!path.extname(o.configFile)){
    o.configFile = path.basename(o.configFile + (whech.ext || '.js'));
  }

  var nameRE = new RegExp(o.name+'.*');
  var packagePath = path.join(o.name, 'package');

  try {
    o.globalDir = require.resolve(o.which).replace(nameRE, '');
    o.globalPackage = require(path.join(o.globalDir, packagePath));
  } catch(err){
    if(o.globalDir){ o.globalPackage = err; }
    else { o.globalPackage = o.globalDir = err; }
  }

  try {
    o.localDir = require.resolve(o.name).replace(nameRE, '');
    o.localPackage = require(packagePath);
  } catch(err){
    if(o.localDir){ o.localPackage = err; }
    else { o.localPackage = o.localDir = err; }
  }

  return o;
}

// sync counterpart
//
whech.sync = function whechSync(name){
  var env = whechCommon(getSpec(name));
  env.configFile = findupSync(env.configFile, {cwd : env.cwd})
    || new Error('`'+env.configFile+'` wasn\'t found from `'+env.cwd+'`');

  return env;
};
<commit_msg>extension is o.ext<commit_after>'use strict';

var path = require('path');
var type = require('utils-type');
var which = require('which');
var findup = require('findup');
var findupSync = require('findup-sync');

exports = module.exports = whech;

// asynchronous version
//
function whech(name, cb){
  var o = getSpec(name);
  which(o.name, function(err, binPath){
    o.which = err || binPath; whechCommon(o);
    findup(o.cwd, o.configFile, function(err, configDir){
      o.configFile = err || path.join(configDir, o.configFile);
      cb(err, o);
    });
  });
}

// check input and give an object with the spec
//
function getSpec(name){
  var env = type(name).plainObject || {name: name};
  if(typeof env.name !== 'string' || !env.name.trim()){
    throw new TypeError('`o.name` should be  non emtpy string');
  }
  return env;
}

// common ops in sync and async version
//
function whechCommon(o){
  o.cwd = o.cwd || process.cwd();
  o.configFile = o.configFile || o.name + 'file';

  try {
    o.which = o.which || which.sync(o.name);
  } catch(err){ o.which = err; }

  var argv = process.argv;
  if(argv[1] && !(o.runFromBin = argv.indexOf(o.which) > -1)){
    o.configFile = path.basename(argv[1]);
    o.cwd = path.resolve(o.cwd, path.dirname(argv[1]));
  }

  if(!path.extname(o.configFile)){
    o.configFile = path.basename(o.configFile + (o.ext || '.js'));
  }

  var nameRE = new RegExp(o.name+'.*');
  var packagePath = path.join(o.name, 'package');

  try {
    o.globalDir = require.resolve(o.which).replace(nameRE, '');
    o.globalPackage = require(path.join(o.globalDir, packagePath));
  } catch(err){
    if(o.globalDir){ o.globalPackage = err; }
    else { o.globalPackage = o.globalDir = err; }
  }

  try {
    o.localDir = require.resolve(o.name).replace(nameRE, '');
    o.localPackage = require(packagePath);
  } catch(err){
    if(o.localDir){ o.localPackage = err; }
    else { o.localPackage = o.localDir = err; }
  }

  return o;
}

// sync counterpart
//
whech.sync = function whechSync(name){
  var env = whechCommon(getSpec(name));
  env.configFile = findupSync(env.configFile, {cwd : env.cwd})
    || new Error('`'+env.configFile+'` wasn\'t found from `'+env.cwd+'`');

  return env;
};
<|endoftext|>


<commit_before>'use strict';

const Promise = require('bluebird');
const upyun = require('upyun');
const urlParse = require('url').parse;
const moment = require('moment');
const util = require('util');
const BaseAdapter = require('ghost-storage-base');

class UpyunAdapter extends BaseAdapter {
  constructor(options) {
    super(options);
    this.options = options || {};
    const bucket = new upyun.Bucket(this.options.bucket, this.options.operator, this.options.password);
    this.client = new upyun.Client(bucket);
  }

  /**
   * Saves the image to storage
   * - image is the express image object
   * - returns a promise which ultimately returns the full url to the uploaded image
   *
   * @param file
   * @param targetDir
   * @returns {*}
   */
  save(file, targetDir) {
    const client = this.client;
    const _this = this;

    return new Promise(function(resolve, reject) {
      const remotePath = _this.getRemotePath(file);
      const remoteDomain = _this.options.domain;
      client.putFile(remotePath, file.path).then(function(result) {
        if (_this.options.imageVersion !== undefined) {
          resolve(remoteDomain + remotePath + _this.options.imageVersion);
        } else {
          resolve(remoteDomain + remotePath);
        }
      }).catch(function(error) {
        reject('[' + result.data.code + '] ' + result.data.msg);
      });
    });
  }

  /**
   * don't need it in Upyun
   * @param filename
   * @param targetDir
   * @returns {*|bluebird}
   * TODO: if fileKey option set, should use key to check file whether exists
   */
  exists(filename, targetDir) {
    return new Promise(function(resolve, reject) {
      resolve(false);
    });
  }

  // middleware for serving the files
  serve() {
    // a no-op, these are absolute URLs
    return function(req, res, next) {
      next();
    };
  }

  /**
   * Not implemented.
   * @description not really delete from Upyun, may be implemented later
   * @param fileName
   * @param targetDir
   * @returns {*|bluebird}
   */
  delete(fileName, targetDir) {
    // return Promise.reject('not implemented');
    return new Promise(function(resolve, reject) {
      resolve(true);
    });
  }

  /**
   * Reads bytes from Upyun for a target image
   *
   * @param options
   */
  read(options) {
    options = options || {};

    const client = this.client;
    const key = urlParse(options.path).pathname.slice(1);

    return new Promise(function(resolve, reject) {
      client.getFile(key).then(function(result) {
        resolve(result);
      }).catch(function(error) {
        reject('Could not read image');
      });
    });
  }

  getRemotePath(image) {
    const folder = moment().format(this.options.folder || 'YYYY/MM/').replace(/^\//, '');

    return '/' + this.options.prefix + folder + image.name;
  }
}

module.exports = UpyunAdapter;
<commit_msg>Stream bug fixed<commit_after>'use strict';

const Promise = require('bluebird');
const upyun = require('upyun');
const fs = require('fs');
const urlParse = require('url').parse;
const moment = require('moment');
const BaseAdapter = require('ghost-storage-base');

class UpyunAdapter extends BaseAdapter {
  constructor(options) {
    super(options);
    this.options = options || {};
    const bucket = new upyun.Bucket(this.options.bucket, this.options.operator, this.options.password);
    this.client = new upyun.Client(bucket);
  }

  /**
   * Saves the image to storage
   * - image is the express image object
   * - returns a promise which ultimately returns the full url to the uploaded image
   *
   * @param file
   * @param targetDir
   * @returns {*}
   */
  save(file, targetDir) {
    const client = this.client;
    const _this = this;

    return new Promise(function(resolve, reject) {
      const remotePath = _this.getRemotePath(file);
      const remoteDomain = _this.options.domain;
      client.putFile(remotePath, fs.readFileSync(file.path)).then(function(result) {
        if (_this.options.imageVersion !== undefined) {
          resolve(remoteDomain + remotePath + _this.options.imageVersion);
        } else {
          resolve(remoteDomain + remotePath);
        }
      }).catch(function(error) {
        reject('[' + result.data.code + '] ' + result.data.msg);
      });
    });
  }

  /**
   * don't need it in Upyun
   * @param filename
   * @param targetDir
   * @returns {*|bluebird}
   * TODO: if fileKey option set, should use key to check file whether exists
   */
  exists(filename, targetDir) {
    return new Promise(function(resolve, reject) {
      resolve(false);
    });
  }

  // middleware for serving the files
  serve() {
    // a no-op, these are absolute URLs
    return function(req, res, next) {
      next();
    };
  }

  /**
   * Not implemented.
   * @description not really delete from Upyun, may be implemented later
   * @param fileName
   * @param targetDir
   * @returns {*|bluebird}
   */
  delete(fileName, targetDir) {
    // return Promise.reject('not implemented');
    return new Promise(function(resolve, reject) {
      resolve(true);
    });
  }

  /**
   * Reads bytes from Upyun for a target image
   *
   * @param options
   */
  read(options) {
    options = options || {};

    const client = this.client;
    const key = urlParse(options.path).pathname.slice(1);

    return new Promise(function(resolve, reject) {
      client.getFile(key).then(function(result) {
        resolve(result);
      }).catch(function(error) {
        reject('Could not read image');
      });
    });
  }

  getRemotePath(image) {
    const folder = moment().format(this.options.folder || 'YYYY/MM/').replace(/^\//, '');

    return '/' + this.options.prefix + folder + image.name;
  }
}

module.exports = UpyunAdapter;
<|endoftext|>


<commit_before>const CUSTOM_STR_PREFIX = '|';

function JSToRedis(value) {
	if(value === undefined)
		return 'undefined';

	if(value === null)
		return 'null';

	let type = typeof value;

	if(type === 'string')
		return `${CUSTOM_STR_PREFIX}${value}`;

	if(type === 'boolean')
		return value ? 'true' : 'false';

	if(type === 'object')
		return JSON.stringify(value);

	return value;
}

function JSONTryParse(str) {
	try {
		return JSON.parse(str);
	} catch (e) {
		return str;
	}
}

function RedisToJS(value) {
	if(value[0] === CUSTOM_STR_PREFIX)
		return value.substr(1);

	if(value === 'true' || value === 'false')
		return value === 'true';

	if(value === 'undefined')
		return undefined;

	if(value === 'null')
		return null;

	if(!isNaN(value))
		return Number(value);

	return JSONTryParse(value);
}

function RedisListInsert(redis, keyName, values, func = 'rpush') {
	if(!values || !values.length)
		return;

	let execOn = redis;

	if(values.length > 1)
		execOn = redis.multi();

	for(let i = 0; i < values.length; i++)
		execOn[func](keyName, JSToRedis(values[i]));

	if(values.length > 1)
		execOn.exec();
}

function RedisListDelete(redis, keyName, index, amount) {
	//When _client is set, its an indicator that its a multi obj. Possibly switch out for instanceof.
	let multi = !redis._client ? redis.multi() : redis;
	while(--amount >= 0)
		multi.lset(keyName, index + amount, REDIS_TMP_PIVOT_KEY);

	multi.lrem(keyName, 0, REDIS_TMP_PIVOT_KEY);

	if(!redis._client)
		multi.exec();
}

const REDIS_TMP_PIVOT_KEY = 'DUMMY_PLACEHOLDER#WE+WANT*TO!DELETE:OR;UPDATE&THIS/SO(LETS=DO°IT?';
const OBJECT_PREFIX = 'SAVEDOBJ:';
const ARRAY_PREFIX = 'SAVEDARR:';

function SavedArray(redis, keyName, readyCb) {
	const rawArray = [];

	keyName = ARRAY_PREFIX + keyName;

	const SavedArrayFuncs = {
		push() {
			RedisListInsert(redis, keyName, arguments);
			return rawArray.push(...arguments);
		},
		shift() {
			redis.lpop(keyName);
			return rawArray.shift();
		},
		unshift() {
			RedisListInsert(redis, keyName, arguments, 'lpush');
			return rawArray.unshift(...arguments);
		},
		//"Some" optimization for the Redis side as this often is faster than shifting the values up 1 by 1
		//(like the default implementation would) Removing this custom method would *work*, but it will cause
		//overhead on the Redis side of things. Makes me wonder if this *optimization* ends up causing more overhead, lol.
		splice(index, deleteCount) {
			//No arguments = no action.
			if(arguments.length === 0 || index > rawArray)
				return [];

			let toInsert = Math.max(arguments.length - 2, 0), //First two args arent insert-vals
					toDelete = deleteCount;

			//This exact behaviour is the default per spec
			if(toDelete === undefined)
				toDelete = rawArray.length - index;

			let toOverwrite = Math.min(toInsert, toDelete);

			let multi = redis.multi();

			//Since we don't just insert, but also remove values we might aswell overwrite as much as possible values
			//that would be removed anyways to save some ops
			for(let i = 0; i < toOverwrite; i++) {
				multi.lset(keyName, index + i, JSToRedis(arguments[2 + i]));

				rawArray[index + i] = arguments[2 + i];
			}

			//We try to insert more than we delete, so we need to insert the extra values into Redis
			if(toOverwrite < toInsert) {
				multi.lset(keyName, index + toOverwrite - 1, REDIS_TMP_PIVOT_KEY);

				for(let i = toOverwrite; i < toInsert; i++)
					multi.linsert(keyName, 'AFTER', REDIS_TMP_PIVOT_KEY, JSToRedis(arguments[2 + i]));

				multi.lset(keyName, index + toOverwrite - 1, JSToRedis(rawArray[index + toOverwrite - 1]));
			}

			//If we delete more than we try to insert, we gotta finally remove the more of them from Redis
			if(toDelete > toInsert)
				RedisListDelete(multi, keyName, index, toDelete - toInsert);

			multi.exec();

			//Now after doing all of this stuff for such little gain in the end, we can finally do the native oneliner..
			return rawArray.splice(...arguments);
		},
		overwrite(newValues = []) {
			if(!newValues || newValues.constructor !== Array)
				throw new Error('Replacement must be typeof array!');

			if(!newValues.length)
				redis.del(keyName);
			else {
				let multi = redis.multi();
				multi.del(keyName);
				multi.lpush(keyName, ...newValues.map(JSToRedis));
				multi.exec();
			}

			rawArray.splice(0);
			for(let i = 0; i < newValues.length; i++)
				rawArray.push(newValues[i]);
		}
	};

	function loadFromRedis() {
		redis.lrange(keyName, 0, -1, (err, arrBackup) => {
			if(!err && arrBackup.length > 0) {
				rawArray.splice(0);
				for(let i = 0; i < arrBackup.length; i++)
					rawArray.push(RedisToJS(arrBackup[i]));
			}

			if(readyCb)
				readyCb(err);
		});
	}

	if(redis.connected && !redis.command_queue_length && !redis.offline_queue_length) loadFromRedis();
	//Ready really seems like the best option. When init'ing a new instance of SavedArray it is possible to do some
	//Actions before we were able to restore from Redis. 'ready' is called after any queued operation has been processed.
	//Doing normal Sets, shifts and pushes should work fine before its restored, splice however will cause issues.
	//So when we finally processed anything that possibly happened, we restore from the Redis list, which should be the most accurate
	//representation of the current "real" state
	redis.on('ready', loadFromRedis);

	return new Proxy(rawArray, {
		set (target, index, value) {
			//Operations like 'pop' will just decrease the length of the array, so when this happens we need to remove the values from
			//the redis list as well
			if(index === 'length' && value < target.length) {
				RedisListDelete(redis, keyName, value, target.length - value);

				target[index] = value;
				return true;
			}

			let parsedInt = parseInt(index, 10);

			//While you can set non-integer values of an array, they do not count as "real" values
			if(!isNaN(parsedInt) && Number(index) === parsedInt && parsedInt >= 0) {
				if(parsedInt < target.length) {
					redis.lset(keyName, parsedInt, JSToRedis(value));
				} else {
					//You can e.g. set index 100 of an empty array, the values before that get filled with undefined
					//These fillings however do not cause any (proxy) calls, so we must manually replicate it for the Redis side
					let toPush = Array(parsedInt - target.length);
					toPush.push(value);

					RedisListInsert(redis, keyName, toPush);

					target.push(value);

					return true;
				}
			}

			target[index] = value;
			return true;
		},
		deleteProperty (target, index) {
			let parsedInt = parseInt(index, 10);

			//calling delete on an array will remove the value, but it wont shift down the array, so lets do the same for Redis.
			if(!isNaN(parsedInt) && Number(index) === parsedInt && parsedInt >= 0)
				redis.lset(keyName, parsedInt, 'null');

			delete target[index];
			return true;
		},
		has (target, property) {
			return property in SavedArrayFuncs || property in target;
		},
		get (target, property) {
			if (property in SavedArrayFuncs) {
				return SavedArrayFuncs[property].bind(target);
			} else {
				return target[property];
			}
		}
	});
}

//Why cant the Array be as ez as this. I really didnt want to represent the array as a hash in Redis though.
function SavedObject(redis, keyName, readyCb) {
	const rawObject = {};

	keyName = OBJECT_PREFIX + keyName;

	const SavedObjectFuncs = {
		overwrite(newObject = {}) {
			let multi = redis.multi();
			multi.del(keyName);
			for(let key in newObject)
				multi.hset(keyName, key, JSToRedis(newObject[key]));
			multi.exec();

			for(let k in rawObject)
				delete rawObject[k];

			for(let k in newObject)
				rawObject[k] = newObject[k];
		}
	};

	function loadFromRedis() {
		//Get up to 4294967295 rows from array (Max keys in JS obj). Splitting it into batches *might* be better, but for now I don't care.
		redis.hscan(keyName, 0, 'COUNT', 4294967295, (err, objBackup) => {
			if(!err && objBackup) {
				for(let k in rawObject)
					delete rawObject[k];

				for(let i = 0; i < objBackup[1].length; i += 2)
					rawObject[objBackup[1][i]] = RedisToJS(objBackup[1][i+1]);
			}

			if(readyCb)
				readyCb(err);
		});
	}

	if(redis.connected && !redis.command_queue_length) loadFromRedis();
	redis.on('ready', loadFromRedis);

	return new Proxy(rawObject, {
		set (target, key, value) {
			redis.hset(keyName, key, JSToRedis(value));

			target[key] = value;
			return true;
		},
		deleteProperty (target, key) {
			redis.hdel(keyName, key);

			delete target[key];
			return true;
		},
		has (target, property) {
			return property in SavedObjectFuncs || property in target;
		},
		get (target, property) {
			if (property in SavedObjectFuncs) {
				return SavedObjectFuncs[property].bind(target);
			} else {
				return target[property];
			}
		}
	});
}

module.exports.Array = SavedArray;
module.exports.Object = SavedObject;<commit_msg>Massive performance increase for certain use-cases<commit_after>const CUSTOM_STR_PREFIX = '|';

function JSToRedis(value) {
	if(value === undefined)
		return 'undefined';

	if(value === null)
		return 'null';

	let type = typeof value;

	if(type === 'string')
		return `${CUSTOM_STR_PREFIX}${value}`;

	if(type === 'boolean')
		return value ? 'true' : 'false';

	if(type === 'object')
		return JSON.stringify(value);

	return value;
}

function JSONTryParse(str) {
	try {
		return JSON.parse(str);
	} catch (e) {
		return str;
	}
}

function RedisToJS(value) {
	if(value[0] === CUSTOM_STR_PREFIX)
		return value.substr(1);

	if(value === 'true' || value === 'false')
		return value === 'true';

	if(value === 'undefined')
		return undefined;

	if(value === 'null')
		return null;

	if(!isNaN(value))
		return Number(value);

	return JSONTryParse(value);
}

function RedisListInsert(redis, keyName, values, func = 'rpush') {
	if(!values || !values.length)
		return;

	let execOn = redis;

	if(values.length > 1)
		execOn = redis.multi();

	for(let i = 0; i < values.length; i++)
		execOn[func](keyName, JSToRedis(values[i]));

	if(values.length > 1)
		execOn.exec();
}

function RedisListDelete(redis, keyName, index, amount) {
	//When _client is set, its an indicator that its a multi obj. Possibly switch out for instanceof.
	let multi = !redis._client ? redis.multi() : redis;
	while(--amount >= 0)
		multi.lset(keyName, index + amount, REDIS_TMP_PIVOT_KEY);

	multi.lrem(keyName, 0, REDIS_TMP_PIVOT_KEY);

	if(!redis._client)
		multi.exec();
}

const REDIS_TMP_PIVOT_KEY = 'DUMMY_PLACEHOLDER#WE+WANT*TO!DELETE:OR;UPDATE&THIS/SO(LETS=DO°IT?';
const OBJECT_PREFIX = 'SAVEDOBJ:';
const ARRAY_PREFIX = 'SAVEDARR:';

function SavedArray(redis, keyName, readyCb) {
	const rawArray = [];

	keyName = ARRAY_PREFIX + keyName;

	const SavedArrayFuncs = {
		push() {
			RedisListInsert(redis, keyName, arguments);
			return rawArray.push(...arguments);
		},
		shift() {
			redis.lpop(keyName);
			return rawArray.shift();
		},
		unshift() {
			RedisListInsert(redis, keyName, arguments, 'lpush');
			return rawArray.unshift(...arguments);
		},
		//"Some" optimization for the Redis side as this often is faster than shifting the values up 1 by 1
		//(like the default implementation would) Removing this custom method would *work*, but it will cause
		//overhead on the Redis side of things. Makes me wonder if this *optimization* ends up causing more overhead, lol.
		splice(index, deleteCount) {
			//No arguments = no action.
			if(arguments.length === 0 || index > rawArray)
				return [];

			let toInsert = Math.max(arguments.length - 2, 0), //First two args arent insert-vals
					toDelete = deleteCount;

			//This exact behaviour is the default per spec
			if(toDelete === undefined)
				toDelete = rawArray.length - index;

			let toOverwrite = Math.min(toInsert, toDelete);

			let multi = redis.multi();

			//Since we don't just insert, but also remove values we might aswell overwrite as much as possible values
			//that would be removed anyways to save some ops
			for(let i = 0; i < toOverwrite; i++) {
				multi.lset(keyName, index + i, JSToRedis(arguments[2 + i]));

				rawArray[index + i] = arguments[2 + i];
			}

			//We try to insert more than we delete, so we need to insert the extra values into Redis
			if(toOverwrite < toInsert) {
				multi.lset(keyName, index + toOverwrite - 1, REDIS_TMP_PIVOT_KEY);

				for(let i = toOverwrite; i < toInsert; i++)
					multi.linsert(keyName, 'AFTER', REDIS_TMP_PIVOT_KEY, JSToRedis(arguments[2 + i]));

				multi.lset(keyName, index + toOverwrite - 1, JSToRedis(rawArray[index + toOverwrite - 1]));
			}

			//If we delete more than we try to insert, we gotta finally remove the more of them from Redis
			if(toDelete > toInsert)
				RedisListDelete(multi, keyName, index, toDelete - toInsert);

			multi.exec();

			//Now after doing all of this stuff for such little gain in the end, we can finally do the native oneliner..
			return rawArray.splice(...arguments);
		},
		overwrite(newValues = []) {
			if(!newValues || newValues.constructor !== Array)
				throw new Error('Replacement must be typeof array!');

			if(!newValues.length)
				redis.del(keyName);
			else {
				let multi = redis.multi();
				multi.del(keyName);
				multi.lpush(keyName, ...newValues.map(JSToRedis));
				multi.exec();
			}

			rawArray.splice(0);
			for(let i = 0; i < newValues.length; i++)
				rawArray.push(newValues[i]);
		},
		indexOf(item, start) {
			return rawArray.indexOf(item, start);
		}
	};

	function loadFromRedis() {
		redis.lrange(keyName, 0, -1, (err, arrBackup) => {
			if(!err && arrBackup.length > 0) {
				rawArray.splice(0);
				for(let i = 0; i < arrBackup.length; i++)
					rawArray.push(RedisToJS(arrBackup[i]));
			}

			if(readyCb)
				readyCb(err);
		});
	}

	if(redis.connected && !redis.command_queue_length && !redis.offline_queue_length) loadFromRedis();
	//Ready really seems like the best option. When init'ing a new instance of SavedArray it is possible to do some
	//Actions before we were able to restore from Redis. 'ready' is called after any queued operation has been processed.
	//Doing normal Sets, shifts and pushes should work fine before its restored, splice however will cause issues.
	//So when we finally processed anything that possibly happened, we restore from the Redis list, which should be the most accurate
	//representation of the current "real" state
	redis.on('ready', loadFromRedis);

	return new Proxy(rawArray, {
		set (target, index, value) {
			//Operations like 'pop' will just decrease the length of the array, so when this happens we need to remove the values from
			//the redis list as well
			if(index === 'length' && value < rawArray.length) {
				RedisListDelete(redis, keyName, value, rawArray.length - value);

				rawArray[index] = value;
				return true;
			}

			let parsedInt = parseInt(index, 10);

			//While you can set non-integer values of an array, they do not count as "real" values
			if(!isNaN(parsedInt) && Number(index) === parsedInt && parsedInt >= 0) {
				if(parsedInt < rawArray.length) {
					redis.lset(keyName, parsedInt, JSToRedis(value));
				} else {
					//You can e.g. set index 100 of an empty array, the values before that get filled with undefined
					//These fillings however do not cause any (proxy) calls, so we must manually replicate it for the Redis side
					let toPush = Array(parsedInt - rawArray.length);
					toPush.push(value);

					RedisListInsert(redis, keyName, toPush);

					rawArray.push(value);

					return true;
				}
			}

			rawArray[index] = value;
			return true;
		},
		deleteProperty (target, index) {
			const parsedInt = parseInt(index, 10);

			//calling delete on an array will remove the value, but it wont shift down the array, so lets do the same for Redis.
			if(!isNaN(parsedInt) && Number(index) === parsedInt && parsedInt >= 0)
				redis.lset(keyName, parsedInt, 'null');

			delete rawArray[index];
			return true;
		},
		has (target, property) {
			return SavedArrayFuncs[property] || property in rawArray;
		},
		get (target, property) {
			if(property === "push" || property === "indexOf" || property === "splice" || property === "shift" || property === "unshift" || property === "overwrite")
				return SavedArrayFuncs[property];

			return target[property];
		}
	});
}

//Why cant the Array be as ez as this. I really didnt want to represent the array as a hash in Redis though.
function SavedObject(redis, keyName, readyCb) {
	const rawObject = {};

	keyName = OBJECT_PREFIX + keyName;

	const SavedObjectFuncs = {
		overwrite(newObject = {}) {
			let multi = redis.multi();
			multi.del(keyName);
			for(let key in newObject)
				multi.hset(keyName, key, JSToRedis(newObject[key]));
			multi.exec();

			for(let k in rawObject)
				delete rawObject[k];

			for(let k in newObject)
				rawObject[k] = newObject[k];
		}
	};

	function loadFromRedis() {
		//Get up to 4294967295 rows from array (Max keys in JS obj). Splitting it into batches *might* be better, but for now I don't care.
		redis.hscan(keyName, 0, 'COUNT', 4294967295, (err, objBackup) => {
			if(!err && objBackup) {
				for(let k in rawObject)
					delete rawObject[k];

				for(let i = 0; i < objBackup[1].length; i += 2)
					rawObject[objBackup[1][i]] = RedisToJS(objBackup[1][i+1]);
			}

			if(readyCb)
				readyCb(err);
		});
	}

	if(redis.connected && !redis.command_queue_length) loadFromRedis();
	redis.on('ready', loadFromRedis);

	return new Proxy(rawObject, {
		set (target, key, value) {
			if(key === "overwrite")
				throw "Setting reserved property 'overwrite' is not possible with Saved";

			redis.hset(keyName, key, JSToRedis(value));

			rawObject[key] = value;
			return true;
		},
		deleteProperty (target, key) {
			redis.hdel(keyName, key);

			delete rawObject[key];
			return true;
		},
		has (target, property) {
			return property in rawObject || SavedObjectFuncs[property];
		},
		get (target, property) {
			//Alternative: hasOwnProperty, which is slower than this check
			//and since we only have one custom function anyways...
			if(property === "overwrite")
				return SavedObjectFuncs[property]

			return rawObject[property];
		}
	});
}

module.exports.Array = SavedArray;
module.exports.Object = SavedObject;<|endoftext|>


<commit_before>var url = require('url');

exports.parse = function (request, callback) {
  var method = request.method.toLowerCase();

  if (method == 'get' || method == 'delete') {
    callback && callback(null, url.parse(request.url, true).query);
    return;
  }

  var params = '';

  request.on('data', function (data) {
    params += data;
    if (params.length > 1e6) {
      request.connection.destroy();
      callback && callback(true);
    }
  });

  request.on('end', function () {
    callback && callback(null, JSON.parse(params));
  });
};
<commit_msg>this makes more sense<commit_after>var url = require('url');

exports.parse = function (request, callback) {
  var method = request.method.toLowerCase();

  if (method != 'post' && method != 'put') {
    return callback && callback(null, url.parse(request.url, true).query);
  }

  var params = '';
  request.resume();
  request.on('data', function (data) {
    params += data;
    if (params.length > 1e6) {
      request.connection.destroy();
      callback && callback({ error: 'param size exceeded' });
    }
  });

  request.on('end', function () {
    callback && callback(null, JSON.parse(params));
  });
};

<|endoftext|>