<commit_before>'use strict';

// MODULES //

var debug = require( 'debug' )( 'flow-map:main' ),
	Transform = require( 'readable-stream' ).Transform,
	copy = require( 'utils-copy' ),
	isFunction = require( 'validate.io-function' ),
	validate = require( './validate.js' );

// VARIABLES //

var DEFAULTS = require( './defaults.json' );

// STREAM //

/**
* FUNCTION: Stream( [options,] fcn )
*	Transform stream constructor.
*
* @constructor
* @param {Object} [options] - stream options
* @param {Number} [options.highWaterMark=16] - specifies the Buffer level for when `write()` starts returning `false`
* @param {Boolean} [options.allowHalfOpen=false] - specifies whether a stream should remain open even if one side ends
* @param {Function} fcn - map function
* @returns {Stream} Transform stream
*/
function Stream( options, fcn ) {
	var opts,
		err,
		map;

	if ( !( this instanceof Stream ) ) {
		if ( arguments.length > 1 ) {
			return new Stream( options, fcn );
		}
		return new Stream( options );
	}
	opts = copy( DEFAULTS );
	if ( arguments.length === 1 ) {
		map = options;
	} else {
		map = fcn;
		err = validate( opts, options );
		if ( err ) {
			throw err;
		}
	}
	if ( !isFunction( map ) ) {
		throw new TypeError( 'invalid input argument. Must provide a map function. Value: `' + map + '`.' );
	}
	// The stream always operates in objectMode:
	opts.objectMode = true;

	// Make the stream a Transform stream:
	debug( 'Creating a transform stream configured with the following options: %s.', JSON.stringify( opts ) );
	Transform.call( this, opts );

	// Flag indicating if a stream has been destroyed:
	this._destroyed = false;

	// Cache the transform function:
	this._map = map;

	// Initialize a counter (index) to track the number of streamed datum (zero-based):
	this._idx = -1;

	return this;
} // end FUNCTION Stream()

/**
* Create a prototype which inherits from the parent prototype.
*/
Stream.prototype = Object.create( Transform.prototype );

/**
* Set the constructor.
*/
Stream.prototype.constructor = Stream;

/**
* METHOD: _transform( chunk, encoding, clbk )
*	Implements the `_transform` method.
*
* @private
* @param {Buffer|String} chunk - streamed chunk
* @param {String} encoding - Buffer encoding
* @param {Function} clbk - callback to invoke after transforming the streamed chunk
* @returns {Void}
*/
Stream.prototype._transform = function _transform( chunk, encoding, clbk ) {
	this._idx += 1;
	debug( 'Received a new chunk to transform. Chunk: %s. Count: %d.', chunk.toString(), this._idx );
	clbk( null,  this._map( chunk, this._idx ) );
}; // end METHOD _transform()

/**
* METHOD: destroy( [error] )
*	Gracefully destroys a stream, providing backwards compatibility.
*
* @param {Object} [error] - optional error message
* @returns {Stream} Stream instance
*/
Stream.prototype.destroy = function destroy( error ) {
	var self = this;
	if ( this._destroyed ) {
		debug( 'Attempted to destroy an already destroyed stream.' );
		return;
	}
	this._destroyed = true;
	process.nextTick( close );

	return this;

	/**
	* FUNCTION: close()
	*	Emits a `close` event.
	*
	* @private
	* @returns {Void}
	*/
	function close() {
		if ( error ) {
			debug( 'Stream was destroyed due to an error. Error: %s.', JSON.stringify( error ) );
			self.emit( 'error', error );
		}
		debug( 'Closing the stream...' );
		self.emit( 'close' );
	}
}; // end METHOD destroy()

// EXPORTS //

module.exports = Stream;
<commit_msg>s/Count/Index/<commit_after>'use strict';

// MODULES //

var debug = require( 'debug' )( 'flow-map:main' ),
	Transform = require( 'readable-stream' ).Transform,
	copy = require( 'utils-copy' ),
	isFunction = require( 'validate.io-function' ),
	validate = require( './validate.js' );

// VARIABLES //

var DEFAULTS = require( './defaults.json' );

// STREAM //

/**
* FUNCTION: Stream( [options,] fcn )
*	Transform stream constructor.
*
* @constructor
* @param {Object} [options] - stream options
* @param {Number} [options.highWaterMark=16] - specifies the Buffer level for when `write()` starts returning `false`
* @param {Boolean} [options.allowHalfOpen=false] - specifies whether a stream should remain open even if one side ends
* @param {Function} fcn - map function
* @returns {Stream} Transform stream
*/
function Stream( options, fcn ) {
	var opts,
		err,
		map;

	if ( !( this instanceof Stream ) ) {
		if ( arguments.length > 1 ) {
			return new Stream( options, fcn );
		}
		return new Stream( options );
	}
	opts = copy( DEFAULTS );
	if ( arguments.length === 1 ) {
		map = options;
	} else {
		map = fcn;
		err = validate( opts, options );
		if ( err ) {
			throw err;
		}
	}
	if ( !isFunction( map ) ) {
		throw new TypeError( 'invalid input argument. Must provide a map function. Value: `' + map + '`.' );
	}
	// The stream always operates in objectMode:
	opts.objectMode = true;

	// Make the stream a Transform stream:
	debug( 'Creating a transform stream configured with the following options: %s.', JSON.stringify( opts ) );
	Transform.call( this, opts );

	// Flag indicating if a stream has been destroyed:
	this._destroyed = false;

	// Cache the transform function:
	this._map = map;

	// Initialize a counter (index) to track the number of streamed datum (zero-based):
	this._idx = -1;

	return this;
} // end FUNCTION Stream()

/**
* Create a prototype which inherits from the parent prototype.
*/
Stream.prototype = Object.create( Transform.prototype );

/**
* Set the constructor.
*/
Stream.prototype.constructor = Stream;

/**
* METHOD: _transform( chunk, encoding, clbk )
*	Implements the `_transform` method.
*
* @private
* @param {Buffer|String} chunk - streamed chunk
* @param {String} encoding - Buffer encoding
* @param {Function} clbk - callback to invoke after transforming the streamed chunk
* @returns {Void}
*/
Stream.prototype._transform = function _transform( chunk, encoding, clbk ) {
	this._idx += 1;
	debug( 'Received a new chunk to transform. Chunk: %s. Index: %d.', chunk.toString(), this._idx );
	clbk( null,  this._map( chunk, this._idx ) );
}; // end METHOD _transform()

/**
* METHOD: destroy( [error] )
*	Gracefully destroys a stream, providing backwards compatibility.
*
* @param {Object} [error] - optional error message
* @returns {Stream} Stream instance
*/
Stream.prototype.destroy = function destroy( error ) {
	var self = this;
	if ( this._destroyed ) {
		debug( 'Attempted to destroy an already destroyed stream.' );
		return;
	}
	this._destroyed = true;
	process.nextTick( close );

	return this;

	/**
	* FUNCTION: close()
	*	Emits a `close` event.
	*
	* @private
	* @returns {Void}
	*/
	function close() {
		if ( error ) {
			debug( 'Stream was destroyed due to an error. Error: %s.', JSON.stringify( error ) );
			self.emit( 'error', error );
		}
		debug( 'Closing the stream...' );
		self.emit( 'close' );
	}
}; // end METHOD destroy()

// EXPORTS //

module.exports = Stream;
<|endoftext|>


<commit_before><commit_msg>explicitly flag use_bitfield_dv<commit_after><|endoftext|>


<commit_before>var utils = require('./utils');

module.exports = function (expect) {
    expect.installTheme({ styles: {
        jsBoolean: 'jsPrimitive',
        jsNumber: 'jsPrimitive',
        error: ['red', 'bold'],
        success: ['green', 'bold'],
        diffAddedLine: 'green',
        diffAddedHighlight: ['bgGreen', 'white'],
        diffAddedSpecialChar: ['bgGreen', 'cyan', 'bold'],
        diffRemovedLine: 'red',
        diffRemovedHighlight: ['bgRed', 'white'],
        diffRemovedSpecialChar: ['bgRed', 'cyan', 'bold'],
        partialMatchHighlight: ['bgYellow']
    }});

    expect.installTheme('html', {
        palette: [
            '#993333', '#993366', '#D17575', '#669933', '#339999', '#339966',
            '#75D1D1', '#C24747', '#999933', '#993399', '#996633', '#47C2C2',
            '#333399', '#339933', '#336699', '#663399'
        ],
        styles: {
            jsComment: '#969896',
            jsFunctionName: '#795da3',
            jsKeyword: '#a71d5d',
            jsPrimitive: '#0086b3',
            jsRegexp: '#183691',
            jsString: '#df5000',
            jsKey: '#555'
        }
    });

    expect.installTheme('ansi', {
        palette: [
            '#FF1A53', '#E494FF', '#1A53FF', '#FF1AC6', '#1AFF53', '#81FF57',
            '#C6FF1A', '#531AFF', '#AFFF94', '#C61AFF', '#53FF1A', '#FF531A',
            '#D557FF', '#1AFFC6', '#FFC61A', '#1AC6FF'
        ],
        styles: {
            jsComment: 'gray',
            jsFunctionName: 'jsKeyword',
            jsKeyword: 'magenta',
            jsNumber: [],
            jsPrimitive: 'cyan',
            jsRegexp: 'green',
            jsString: 'cyan',
            jsKey: '#666',
            diffAddedHighlight: ['bgGreen', 'black'],
            diffRemovedHighlight: ['bgRed', 'black'],
            partialMatchHighlight: ['bgYellow', 'black']
        }
    });

    expect.addStyle('colorByIndex', function (content, index) {
        var palette = this.theme().palette;
        if (palette) {
            var color = palette[index % palette.length];
            this.text(content, color);
        } else {
            this.text(content);
        }
    });

    expect.addStyle('singleQuotedString', function (content) {
        content = String(content);
        this.jsString("'")
            .jsString(content.replace(/[\\\x00-\x1f']/g, function ($0) {
                if ($0 === '\n') {
                    return '\\n';
                } else if ($0 === '\r') {
                    return '\\r';
                } else if ($0 === "'") {
                    return "\\'";
                } else if ($0 === '\\') {
                    return '\\\\';
                } else if ($0 === '\t') {
                    return '\\t';
                } else if ($0 === '\b') {
                    return '\\b';
                } else if ($0 === '\f') {
                    return '\\f';
                } else {
                    var charCode = $0.charCodeAt(0);
                    return '\\x' + (charCode < 16 ? '0' : '') + charCode.toString(16);
                }
            }))
            .jsString("'");
    });

    expect.addStyle('key', function (content) {
        content = String(content);
        if (/^[a-z\$\_][a-z0-9\$\_]*$/i.test(content)) {
            this.text(content, 'jsKey');
        } else if (/^(?:0|[1-9][0-9]*)$/.test(content)) {
            this.jsNumber(content);
        } else {
            this.singleQuotedString(content);
        }
    });

    // Intended to be redefined by a plugin that offers syntax highlighting:
    expect.addStyle('code', function (content, language) {
        this.text(content);
    });

    expect.addStyle('annotationBlock', function () {
        var pen = this.getContentFromArguments(arguments);
        var height = pen.size().height;

        if (height > 0) {
            this.block(function () {
                for (var i = 0; i < height; i += 1) {
                    if (0 < i) {
                        this.nl();
                    }
                    this.error('//');
                }
            });
            this.sp().block(pen);
        }
    });

    expect.addStyle('commentBlock', function () {
        var pen = this.getContentFromArguments(arguments);
        var height = pen.size().height;

        if (height > 0) {
            this.block(function () {
                for (var i = 0; i < height; i += 1) {
                    if (0 < i) {
                        this.nl();
                    }
                    this.jsComment('//');
                }
            });
            this.sp().block(pen);
        }
    });

    expect.addStyle('removedHighlight', function (content) {
        this.alt({
            text: function () {
                content.split(/(\n)/).forEach(function (fragment) {
                    if (fragment === '\n') {
                        this.nl();
                    } else {
                        this.block(function () {
                            this.text(fragment).nl().text(fragment.replace(/[\s\S]/g, '^'));
                        });
                    }
                }, this);
            },
            fallback: function () {
                this.diffRemovedHighlight(content);
            }
        });
    });

    expect.addStyle('match', function (content) {
        this.alt({
            text: function () {
                content.split(/(\n)/).forEach(function (fragment) {
                    if (fragment === '\n') {
                        this.nl();
                    } else {
                        this.block(function () {
                            this.text(fragment).nl().text(fragment.replace(/[\s\S]/g, '^'));
                        });
                    }
                }, this);
            },
            fallback: function () {
                this.diffAddedHighlight(content);
            }
        });
    });

    expect.addStyle('partialMatch', function (content) {
        this.alt({
            text: function () {
                // We haven't yet come up with a good styling for partial matches in text mode
                this.match(content);
            },
            fallback: function () {
                this.partialMatchHighlight(content);
            }
        });
    });

    expect.addStyle('shouldEqualError', function (expected) {
        this.error(typeof expected === 'undefined' ? 'should be' : 'should equal').sp().block(function () {
            this.appendInspected(expected);
        });
    });

    expect.addStyle('errorName', function (error) {
        if (typeof error.name === 'string' && error.name !== 'Error') {
            this.text(error.name);
        } else if (error.constructor && typeof error.constructor.name === 'string') {
            this.text(error.constructor.name);
        } else {
            this.text('Error');
        }
    });

    expect.addStyle('appendErrorMessage', function (error, options) {
        if (error && error.isUnexpected) {
            this.append(error.getErrorMessage(utils.extend({ output: this }, options)));
        } else {
            this.appendInspected(error);
        }
    });

    expect.addStyle('appendItems', function (items, separator) {
        var that = this;
        separator = separator || '';
        items.forEach(function (item, index) {
            if (0 < index) {
                that.append(separator);
            }
            that.appendInspected(item);
        });
    });

    expect.addStyle('magicPenLine', function (line, pen) {
        line.forEach(function (lineEntry, j) {
            if (j > 0) {
                this.nl();
            }
            if (lineEntry.style === 'text') {
                var styles = lineEntry.args.styles;
                if (pen && styles.length === 1 && typeof pen[styles[0]] === 'function') {
                    // Text with a single style also available as a method on the pen being inspected:
                    this
                        .text('.')
                        .jsFunctionName(styles[0])
                        .text('(')
                        .singleQuotedString(lineEntry.args.content)
                        .text(')');
                } else {
                    this
                        .text('.')
                        .jsFunctionName('text')
                        .text('(')
                        .singleQuotedString(lineEntry.args.content);
                    if (styles.length > 0) {
                        this
                            .text(', ')
                            .appendInspected(styles.length === 1 && Array.isArray(styles[0]) ? styles[0] : styles);
                    }
                    this.text(')');
                }
            } else {
                // lineEntry.style === 'block'
                this
                    .text('.')
                    .jsFunctionName('block').text('(').jsKeyword('function').text(' () {');
                if (lineEntry.args) {
                    this
                        .nl()
                        .indentLines()
                        .i()
                        .magicPen(pen, lineEntry.args)
                        .outdentLines()
                        .nl();
                }
                this.text('})');
            }
        }, this);
    });

    expect.addStyle('magicPen', function (pen, lines) {
        var isTopLevel = !lines;
        lines = lines || pen.output;
        this.block(function () {
            if (isTopLevel) {
                this.jsFunctionName('magicpen').text('(');
                if (pen.format) {
                    this.singleQuotedString(pen.format);
                }
                this.text(')');
            } else {
                this.jsKeyword('this');
            }
            if (!pen.isEmpty()) {
                var inspectOnMultipleLines = lines.length > 1 || lines[0].length > 1;
                if (inspectOnMultipleLines) {
                    this
                        .nl()
                        .indentLines()
                        .i();
                }
                this.block(function () {
                    lines.forEach(function (line, i) {
                        if (i > 0) {
                            this.text('.').jsFunctionName('nl').text('()').nl();
                        }
                        this.magicPenLine(line, pen);
                    }, this);
                    if (!isTopLevel) {
                        this.text(';');
                    }
                });
                if (inspectOnMultipleLines) {
                    this.outdentLines();
                }
            }
        });

        // If we're at the top level of a non-empty pen compatible with the current output,
        // render the output of the pen in a comment:
        if (isTopLevel && !pen.isEmpty() && (pen.format === this.format || !pen.format)) {
            this.sp().commentBlock(pen);
        }
    });
};
<commit_msg>Tweaking the color palettes<commit_after>var utils = require('./utils');

module.exports = function (expect) {
    expect.installTheme({ styles: {
        jsBoolean: 'jsPrimitive',
        jsNumber: 'jsPrimitive',
        error: ['red', 'bold'],
        success: ['green', 'bold'],
        diffAddedLine: 'green',
        diffAddedHighlight: ['bgGreen', 'white'],
        diffAddedSpecialChar: ['bgGreen', 'cyan', 'bold'],
        diffRemovedLine: 'red',
        diffRemovedHighlight: ['bgRed', 'white'],
        diffRemovedSpecialChar: ['bgRed', 'cyan', 'bold'],
        partialMatchHighlight: ['bgYellow']
    }});

    expect.installTheme('html', {
        palette: [
            '#993333', '#669933', '#314575', '#337777', '#710071', '#319916',
            '#BB1A53', '#999933', '#4311C2', '#996633', '#993399', '#333399',
            '#228842', '#C24747', '#336699', '#663399'
        ],
        styles: {
            jsComment: '#969896',
            jsFunctionName: '#795da3',
            jsKeyword: '#a71d5d',
            jsPrimitive: '#0086b3',
            jsRegexp: '#183691',
            jsString: '#df5000',
            jsKey: '#555'
        }
    });

    expect.installTheme('ansi', {
        palette: [
            '#FF1A53', '#E494FF', '#1A53FF', '#FF1AC6', '#1AFF53', '#D557FF',
            '#81FF57', '#C6FF1A', '#531AFF', '#AFFF94', '#C61AFF', '#53FF1A',
            '#FF531A', '#1AFFC6', '#FFC61A', '#1AC6FF'
        ],
        styles: {
            jsComment: 'gray',
            jsFunctionName: 'jsKeyword',
            jsKeyword: 'magenta',
            jsNumber: [],
            jsPrimitive: 'cyan',
            jsRegexp: 'green',
            jsString: 'cyan',
            jsKey: '#666',
            diffAddedHighlight: ['bgGreen', 'black'],
            diffRemovedHighlight: ['bgRed', 'black'],
            partialMatchHighlight: ['bgYellow', 'black']
        }
    });

    expect.addStyle('colorByIndex', function (content, index) {
        var palette = this.theme().palette;
        if (palette) {
            var color = palette[index % palette.length];
            this.text(content, color);
        } else {
            this.text(content);
        }
    });

    expect.addStyle('singleQuotedString', function (content) {
        content = String(content);
        this.jsString("'")
            .jsString(content.replace(/[\\\x00-\x1f']/g, function ($0) {
                if ($0 === '\n') {
                    return '\\n';
                } else if ($0 === '\r') {
                    return '\\r';
                } else if ($0 === "'") {
                    return "\\'";
                } else if ($0 === '\\') {
                    return '\\\\';
                } else if ($0 === '\t') {
                    return '\\t';
                } else if ($0 === '\b') {
                    return '\\b';
                } else if ($0 === '\f') {
                    return '\\f';
                } else {
                    var charCode = $0.charCodeAt(0);
                    return '\\x' + (charCode < 16 ? '0' : '') + charCode.toString(16);
                }
            }))
            .jsString("'");
    });

    expect.addStyle('key', function (content) {
        content = String(content);
        if (/^[a-z\$\_][a-z0-9\$\_]*$/i.test(content)) {
            this.text(content, 'jsKey');
        } else if (/^(?:0|[1-9][0-9]*)$/.test(content)) {
            this.jsNumber(content);
        } else {
            this.singleQuotedString(content);
        }
    });

    // Intended to be redefined by a plugin that offers syntax highlighting:
    expect.addStyle('code', function (content, language) {
        this.text(content);
    });

    expect.addStyle('annotationBlock', function () {
        var pen = this.getContentFromArguments(arguments);
        var height = pen.size().height;

        if (height > 0) {
            this.block(function () {
                for (var i = 0; i < height; i += 1) {
                    if (0 < i) {
                        this.nl();
                    }
                    this.error('//');
                }
            });
            this.sp().block(pen);
        }
    });

    expect.addStyle('commentBlock', function () {
        var pen = this.getContentFromArguments(arguments);
        var height = pen.size().height;

        if (height > 0) {
            this.block(function () {
                for (var i = 0; i < height; i += 1) {
                    if (0 < i) {
                        this.nl();
                    }
                    this.jsComment('//');
                }
            });
            this.sp().block(pen);
        }
    });

    expect.addStyle('removedHighlight', function (content) {
        this.alt({
            text: function () {
                content.split(/(\n)/).forEach(function (fragment) {
                    if (fragment === '\n') {
                        this.nl();
                    } else {
                        this.block(function () {
                            this.text(fragment).nl().text(fragment.replace(/[\s\S]/g, '^'));
                        });
                    }
                }, this);
            },
            fallback: function () {
                this.diffRemovedHighlight(content);
            }
        });
    });

    expect.addStyle('match', function (content) {
        this.alt({
            text: function () {
                content.split(/(\n)/).forEach(function (fragment) {
                    if (fragment === '\n') {
                        this.nl();
                    } else {
                        this.block(function () {
                            this.text(fragment).nl().text(fragment.replace(/[\s\S]/g, '^'));
                        });
                    }
                }, this);
            },
            fallback: function () {
                this.diffAddedHighlight(content);
            }
        });
    });

    expect.addStyle('partialMatch', function (content) {
        this.alt({
            text: function () {
                // We haven't yet come up with a good styling for partial matches in text mode
                this.match(content);
            },
            fallback: function () {
                this.partialMatchHighlight(content);
            }
        });
    });

    expect.addStyle('shouldEqualError', function (expected) {
        this.error(typeof expected === 'undefined' ? 'should be' : 'should equal').sp().block(function () {
            this.appendInspected(expected);
        });
    });

    expect.addStyle('errorName', function (error) {
        if (typeof error.name === 'string' && error.name !== 'Error') {
            this.text(error.name);
        } else if (error.constructor && typeof error.constructor.name === 'string') {
            this.text(error.constructor.name);
        } else {
            this.text('Error');
        }
    });

    expect.addStyle('appendErrorMessage', function (error, options) {
        if (error && error.isUnexpected) {
            this.append(error.getErrorMessage(utils.extend({ output: this }, options)));
        } else {
            this.appendInspected(error);
        }
    });

    expect.addStyle('appendItems', function (items, separator) {
        var that = this;
        separator = separator || '';
        items.forEach(function (item, index) {
            if (0 < index) {
                that.append(separator);
            }
            that.appendInspected(item);
        });
    });

    expect.addStyle('magicPenLine', function (line, pen) {
        line.forEach(function (lineEntry, j) {
            if (j > 0) {
                this.nl();
            }
            if (lineEntry.style === 'text') {
                var styles = lineEntry.args.styles;
                if (pen && styles.length === 1 && typeof pen[styles[0]] === 'function') {
                    // Text with a single style also available as a method on the pen being inspected:
                    this
                        .text('.')
                        .jsFunctionName(styles[0])
                        .text('(')
                        .singleQuotedString(lineEntry.args.content)
                        .text(')');
                } else {
                    this
                        .text('.')
                        .jsFunctionName('text')
                        .text('(')
                        .singleQuotedString(lineEntry.args.content);
                    if (styles.length > 0) {
                        this
                            .text(', ')
                            .appendInspected(styles.length === 1 && Array.isArray(styles[0]) ? styles[0] : styles);
                    }
                    this.text(')');
                }
            } else {
                // lineEntry.style === 'block'
                this
                    .text('.')
                    .jsFunctionName('block').text('(').jsKeyword('function').text(' () {');
                if (lineEntry.args) {
                    this
                        .nl()
                        .indentLines()
                        .i()
                        .magicPen(pen, lineEntry.args)
                        .outdentLines()
                        .nl();
                }
                this.text('})');
            }
        }, this);
    });

    expect.addStyle('magicPen', function (pen, lines) {
        var isTopLevel = !lines;
        lines = lines || pen.output;
        this.block(function () {
            if (isTopLevel) {
                this.jsFunctionName('magicpen').text('(');
                if (pen.format) {
                    this.singleQuotedString(pen.format);
                }
                this.text(')');
            } else {
                this.jsKeyword('this');
            }
            if (!pen.isEmpty()) {
                var inspectOnMultipleLines = lines.length > 1 || lines[0].length > 1;
                if (inspectOnMultipleLines) {
                    this
                        .nl()
                        .indentLines()
                        .i();
                }
                this.block(function () {
                    lines.forEach(function (line, i) {
                        if (i > 0) {
                            this.text('.').jsFunctionName('nl').text('()').nl();
                        }
                        this.magicPenLine(line, pen);
                    }, this);
                    if (!isTopLevel) {
                        this.text(';');
                    }
                });
                if (inspectOnMultipleLines) {
                    this.outdentLines();
                }
            }
        });

        // If we're at the top level of a non-empty pen compatible with the current output,
        // render the output of the pen in a comment:
        if (isTopLevel && !pen.isEmpty() && (pen.format === this.format || !pen.format)) {
            this.sp().commentBlock(pen);
        }
    });
};
<|endoftext|>


<commit_before><commit_msg>Fix passing the dry property.<commit_after><|endoftext|>


<commit_before><commit_msg>Fixed typo.<commit_after><|endoftext|>


<commit_before>/**
 *  File: L.SimpleGraticule.js
 *  Desc: A graticule for Leaflet maps in the L.CRS.Simple coordinate system.
 *  Auth: Andrew Blakey (ablakey@gmail.com)
 */
L.SimpleGraticule = L.LayerGroup.extend({
    options: {
        interval: 20,
        showOriginLabel: true,
        redraw: 'move',
        hidden: false,
		zoomIntervals : []
    },

    lineStyle: {
        stroke: true,
        color: '#111',
        opacity: 0.6,
        weight: 1,
        clickable: false
    },

    initialize: function(options) {
        L.LayerGroup.prototype.initialize.call(this);
        L.Util.setOptions(this, options);
    },

    onAdd: function(map) {
        this._map = map;

        var graticule = this.redraw();
        this._map.on('viewreset ' + this.options.redraw, graticule.redraw, graticule);

        this.eachLayer(map.addLayer, map);
    },

    onRemove: function(map) {
        map.off('viewreset '+ this.options.redraw, this.map);
        this.eachLayer(this.removeLayer, this);
    },

    hide: function() {
        this.options.hidden = true;
        this.redraw();
    },

    show: function() {
        this.options.hidden = false;
        this.redraw();
    },

    redraw: function() {
        this._bounds = this._map.getBounds().pad(0.5);

        this.clearLayers();

        if (!this.options.hidden) {

			var currentZoom = this._map.getZoom();

            for(var i = 0 ; i < this.options.zoomIntervals.length ; i++) {
                if(currentZoom >= this.options.zoomIntervals[i].start && currentZoom <= this.options.zoomIntervals[i].end){
                    this.options.interval = this.options.zoomIntervals[i].interval;
                    break;
                }
            }

            this.constructLines(this.getMins(), this.getLineCounts());

            if (this.options.showOriginLabel) {
                this.addLayer(this.addOriginLabel());
            }
        }

        return this;
    },

    getLineCounts: function() {
        return {
            x: Math.ceil((this._bounds.getEast() - this._bounds.getWest()) /
                this.options.interval),
            y: Math.ceil((this._bounds.getNorth() - this._bounds.getSouth()) /
                this.options.interval)
        };
    },

    getMins: function() {
        //rounds up to nearest multiple of x
        var s = this.options.interval;
        return {
            x: Math.floor(this._bounds.getWest() / s) * s,
            y: Math.floor(this._bounds.getSouth() / s) * s
        };
    },

    constructLines: function(mins, counts) {
        var lines = new Array(counts.x + counts.y);
        var labels = new Array(counts.x + counts.y);

        //for horizontal lines
        for (var i = 0; i <= counts.x; i++) {
            var x = mins.x + i * this.options.interval;
            lines[i] = this.buildXLine(x);
            labels[i] = this.buildLabel('gridlabel-horiz', x);
        }

        //for vertical lines
        for (var j = 0; j <= counts.y; j++) {
            var y = mins.y + j * this.options.interval;
            lines[j + i] = this.buildYLine(y);
            labels[j + i] = this.buildLabel('gridlabel-vert', y);
        }

        lines.forEach(this.addLayer, this);
        labels.forEach(this.addLayer, this);
    },

    buildXLine: function(x) {
        var bottomLL = new L.LatLng(this._bounds.getSouth(), x);
        var topLL = new L.LatLng(this._bounds.getNorth(), x);

        return new L.Polyline([bottomLL, topLL], this.lineStyle);
    },

    buildYLine: function(y) {
        var leftLL = new L.LatLng(y, this._bounds.getWest());
        var rightLL = new L.LatLng(y, this._bounds.getEast());

        return new L.Polyline([leftLL, rightLL], this.lineStyle);
    },

    buildLabel: function(axis, val) {
        var bounds = this._map.getBounds().pad(-0.003);
        var latLng;
        if (axis == 'gridlabel-horiz') {
            latLng = new L.LatLng(bounds.getNorth(), val);
        } else {
            latLng = new L.LatLng(val, bounds.getWest());
        }

        return L.marker(latLng, {
            clickable: false,
            icon: L.divIcon({
                iconSize: [0, 0],
                className: 'leaflet-grid-label',
                html: '
' + val + '
'
            })
        });
    },

    addOriginLabel: function() {
        return L.marker([0, 0], {
            clickable: false,
            icon: L.divIcon({
                iconSize: [0, 0],
                className: 'leaflet-grid-label',
                html: '
(0,0)
'
            })
        });
    }
});

L.simpleGraticule = function(options) {
    return new L.SimpleGraticule(options);
};
<commit_msg>Fix syntax errors<commit_after>/**
 *  File: L.SimpleGraticule.js
 *  Desc: A graticule for Leaflet maps in the L.CRS.Simple coordinate system.
 *  Auth: Andrew Blakey (ablakey@gmail.com)
 */
L.SimpleGraticule = L.LayerGroup.extend({
    options: {
        interval: 20,
        showOriginLabel: true,
        redraw: 'move',
        hidden: false,
	zoomIntervals : []
    },

    lineStyle: {
        stroke: true,
        color: '#111',
        opacity: 0.6,
        weight: 1,
        clickable: false
    },

    initialize: function(options) {
        L.LayerGroup.prototype.initialize.call(this);
        L.Util.setOptions(this, options);
    },

    onAdd: function(map) {
        this._map = map;

        var graticule = this.redraw();
        this._map.on('viewreset ' + this.options.redraw, graticule.redraw, graticule);

        this.eachLayer(map.addLayer, map);
    },

    onRemove: function(map) {
        map.off('viewreset '+ this.options.redraw, this.map);
        this.eachLayer(this.removeLayer, this);
    },

    hide: function() {
        this.options.hidden = true;
        this.redraw();
    },

    show: function() {
        this.options.hidden = false;
        this.redraw();
    },

    redraw: function() {
        this._bounds = this._map.getBounds().pad(0.5);

        this.clearLayers();

        if (!this.options.hidden) {

	    var currentZoom = this._map.getZoom();

            for(var i = 0 ; i < this.options.zoomIntervals.length ; i++) {
                if(currentZoom >= this.options.zoomIntervals[i].start && currentZoom <= this.options.zoomIntervals[i].end){
                    this.options.interval = this.options.zoomIntervals[i].interval;
                    break;
                }
            }

            this.constructLines(this.getMins(), this.getLineCounts());

            if (this.options.showOriginLabel) {
                this.addLayer(this.addOriginLabel());
            }
        }

        return this;
    },

    getLineCounts: function() {
        return {
            x: Math.ceil((this._bounds.getEast() - this._bounds.getWest()) /
                this.options.interval),
            y: Math.ceil((this._bounds.getNorth() - this._bounds.getSouth()) /
                this.options.interval)
        };
    },

    getMins: function() {
        //rounds up to nearest multiple of x
        var s = this.options.interval;
        return {
            x: Math.floor(this._bounds.getWest() / s) * s,
            y: Math.floor(this._bounds.getSouth() / s) * s
        };
    },

    constructLines: function(mins, counts) {
        var lines = new Array(counts.x + counts.y);
        var labels = new Array(counts.x + counts.y);

        //for horizontal lines
        for (var i = 0; i <= counts.x; i++) {
            var x = mins.x + i * this.options.interval;
            lines[i] = this.buildXLine(x);
            labels[i] = this.buildLabel('gridlabel-horiz', x);
        }

        //for vertical lines
        for (var j = 0; j <= counts.y; j++) {
            var y = mins.y + j * this.options.interval;
            lines[j + i] = this.buildYLine(y);
            labels[j + i] = this.buildLabel('gridlabel-vert', y);
        }

        lines.forEach(this.addLayer, this);
        labels.forEach(this.addLayer, this);
    },

    buildXLine: function(x) {
        var bottomLL = new L.LatLng(this._bounds.getSouth(), x);
        var topLL = new L.LatLng(this._bounds.getNorth(), x);

        return new L.Polyline([bottomLL, topLL], this.lineStyle);
    },

    buildYLine: function(y) {
        var leftLL = new L.LatLng(y, this._bounds.getWest());
        var rightLL = new L.LatLng(y, this._bounds.getEast());

        return new L.Polyline([leftLL, rightLL], this.lineStyle);
    },

    buildLabel: function(axis, val) {
        var bounds = this._map.getBounds().pad(-0.003);
        var latLng;
        if (axis == 'gridlabel-horiz') {
            latLng = new L.LatLng(bounds.getNorth(), val);
        } else {
            latLng = new L.LatLng(val, bounds.getWest());
        }

        return L.marker(latLng, {
            clickable: false,
            icon: L.divIcon({
                iconSize: [0, 0],
                className: 'leaflet-grid-label',
                html: '
' + val + '
'
            })
        });
    },

    addOriginLabel: function() {
        return L.marker([0, 0], {
            clickable: false,
            icon: L.divIcon({
                iconSize: [0, 0],
                className: 'leaflet-grid-label',
                html: '
(0,0)
'
            })
        });
    }
});

L.simpleGraticule = function(options) {
    return new L.SimpleGraticule(options);
};
<|endoftext|>


<commit_before><commit_msg>deleted console.logs<commit_after><|endoftext|>


<commit_before><commit_msg>Updated the mixin for non function properties, prevent wrapped to store the returned value<commit_after><|endoftext|>


<commit_before><commit_msg>#292 fix color swap with two link files<commit_after><|endoftext|>


<commit_before><commit_msg>[fix] Specify default sidebar/panel widths in px.<commit_after><|endoftext|>


<commit_before><commit_msg>config for https production<commit_after><|endoftext|>


<commit_before>/* jslint node: true, esnext: true */

'use strict';

const address = require('network-address'),
	url = require('url'),
	route = require('koa-route'),
	endpoint = require('kronos-endpoint'),
	service = require('kronos-service'),
	ServiceConsumerMixin = require('kronos-service').ServiceConsumerMixin;

class ServiceConsul extends service.Service {
	static get name() {
		return 'consul';
	}

	get type() {
		return ServiceConsul.name;
	}

	get autostart() {
		return true;
	}

	constructor(config, owner) {
		super(config, owner);

		const nodesEndpoint = new endpoint.ReceiveEndpoint('nodes', this, {
			createOpposite: true
		});

		nodesEndpoint.receive = request => {
			if (request.update) {
				const watch = this.consul.watch({
					method: this.consul.catalog.service.nodes,
					options: {
						service: this.serviceDefinition.name
					}
				});

				watch.on('change', (data, res) => {
					this.info(data);
					nodesEndpoint.opposite.receive(data);
				});

				watch.on('error', err => this.error(err));
			}

			return this.kronosNodes();
		};

		this.addEndpoint(nodesEndpoint);
	}

	get configurationAttributes() {
		const co = this.consulOptions;

		function consulOptionSetter(value, attribute) {
			if (value !== undefined) {
				co[attribute.name] = value;
			}
		}

		return Object.assign({
			'host': {
				description: 'consul host',
				default: 'localhost',
				type: 'string',
				setter: consulOptionSetter
			},
			'port': {
				description: 'consul port',
				default: 8500,
				type: 'integer',
				setter: consulOptionSetter
			},
			'secure': {
				default: false,
				type: 'boolean',
				setter: consulOptionSetter
			},
			'ca': {
				setter: consulOptionSetter
			},
			'id': {
				description: 'kronos service id',
				type: 'string',
				// id of our node in the consul cluster
				default: address()
			},
			'checkPath': {
				description: 'url path used for the kronos check',
				type: 'string',
				default: '/check'
			},
			'checkInterval': {
				description: 'interval the kronos check is called',
				default: '10',
				type: 'duration'
			},
			'checkTimeout': {
				description: 'timeout for the kronos check interval',
				default: '5',
				type: 'duration'
			}
		}, super.configurationAttributes);
	}

	_configure(config) {
		if (this.consulOptions === undefined) {
			this.consulOptions = {
				promisify(fn) {
					return new Promise((resolve, reject) => {
						try {
							return fn((err, data, res) => {
								if (err) {
									err.res = res;
									return reject(err);
								}
								return resolve([data, res]);
							});
						} catch (err) {
							return reject(err);
						}
					});
				}
			};
		}

		const modified = super._configure(config);

		// TODO where does baseUrl come from ?
		delete this.consulOptions.baseUrl;

		this.consul = require('consul')(this.consulOptions);

		return modified;
	}

	get serviceDefinition() {
		function asSeconds(value) {
			return value instanceof String && value.matches(/s$/) ? value : `${value}s`;
		}

		return {
			name: 'kronos',
			id: this.id,
			port: this.listener.port,
			address: this.listener.hostname,
			tags: this.tags,
			check: {
				id: this.listener.url + this.checkPath,
				http: this.listener.url + this.checkPath,
				interval: asSeconds(this.checkInterval),
				timeout: asSeconds(this.checkTimeout)
			}
		};
	}

	/**
	 * Register the kronos service in consul
	 * @return {Promise} that fullfills on succesfull startup
	 */
	_start() {
		return super._start().then(() => {
			this.tags = Object.keys(this.owner.steps);

			// wait until health-check and koa services are present
			return ServiceConsumerMixin.defineServiceConsumerProperties(this, {
				listener: {
					name: 'koa-admin',
					type: 'koa'
				},
				hcs: {
					name: 'health-check',
					type: 'health-check'
				}
			}, this.owner, true).then(() =>
				this.listener.start().then(() =>
					this.consul.agent.service.register(this.serviceDefinition).then(f => {
						this.consul.status.leader().then(leader => this.info(level =>
							`Consul raft leader is ${Object.keys(leader).join(',')}`));
						this.consul.status.peers().then(peers => this.trace(level =>
							`Consul raft peers are ${peers.map(p => p.body)}`));
						this.kronosNodes().then(nodes => this.info(level =>
							`Kronos nodes are ${nodes.map( n => n.ServiceID)}`));

						this._stepRegisteredListener = step => {
							this.tags = Object.keys(this.owner.steps);
							this.update(5000);
						};

						this.owner.addListener('stepRegistered', this._stepRegisteredListener);

						this.listener.koa.use(route.get(this.checkPath, ctx =>
							this.hcs.endpoints.state.receive({}).then(r => {
								this.info({
									'health': r
								});
								this.status = r ? 200 : 300;
								ctx.body = r ? 'OK' : 'ERROR';
							})
						));

						return Promise.resolve();
					})
				)
			);
		});
	}

	/**
	 * deregister the service from consul
	 * @return {Promise} that fullfills when the deregitering has finished
	 */
	_stop() {
		return this.consul.agent.service.deregister(this.serviceDefinition.id).then(f => {
			if (this._stepRegisteredListener) {
				this.owner.removeListener('stepRegistered', this._stepRegisteredListener);
				this._stepRegisteredListener = undefined;
			}
			return Promise.resolve();
		});
	}

	/**
	 * Update service definition in consul
	 * @param {Number} delay time to wait before doing the unregister/register action
	 */
	update(delay) {
		const reregister = () =>
			this.consul.agent.service.deregister(this.serviceDefinition.id)
			.then(() => this.consul.agent.service.register(this.serviceDefinition));

		if (this._updateTimer) {
			clearTimeout(this._updateTimer);
		}

		if (delay) {
			this._updateTimer = setTimeout(reregister, delay);
		} else {
			return reregister();
		}
	}

	kronosNodes() {
		return this.consul.catalog.service.nodes({
			service: this.serviceDefinition.name
		}).then(response => response[0]);
	}

	registerService(name, options) {
		this.info({
			message: 'registerService',
			name: name,
			options: options
		});

		const u = url.parse(options.url);

		/*
				const watch = this.consul.watch({
					method: this.consul.kv.get,
					options: {
						key: `services/${name}/${this.id}/url`
					}
				});

				watch.on('change', (data, res) => {
					console.log('change data:', data);
				});

				watch.on('error', err => console.log('error:', err));
		*/

		return this.consul.kv.set({
			key: `services/${name}/${this.id}/url`,
			value: options.url
		});

		/*
				const serviceDefinition = {
					name: name,
					id: u.href,
					address: u.hostname,
					port: parseInt(u.port, 10),
					tags: options.tags
				};

				return consul.agent.service.register(serviceDefinition).then(f => {
					//this.info(`registered: ${JSON.stringify(f)}`);
					return Promise.resolve();
				});
				*/
	}

	unregisterService(name) {
		this.info({
			message: 'unregisterService',
			name: name
		});

		return this.consul.kv.del({
			key: `services/${name}/${this.id}`,
			recurse: true
		});

		//return consul.agent.service.deregister(name);
	}

	* serviceURLs(name) {
		let si = [];

		let firstPromise = this.consul.kv.get({
				key: `services/${name}`,
				recurse: true
			})
			.then(data => {
				si = data[0].map(d => d.Value);
				firstPromise = undefined;
				return si.length === 0 ? Promise.reject() : Promise.resolve(si[0]);
			});

		while (firstPromise) {
			yield firstPromise;
			//console.log(`size: ${si.length} ${firstPromise}`);
		}

		if (si.length) {
			for (let i = 1;; i++) {
				if (i >= si.length) {
					i = 0;
				}
				//console.log(`yield: ${i} ${si.length}`);
				yield Promise.resolve(si[i]);
			}
		}
		return undefined;
	}
}

module.exports.registerWithManager = manager =>
	manager.registerServiceFactory(ServiceConsul).then(sf =>
		manager.declareService({
			'type': sf.name,
			'name': 'registry'
		}));
<commit_msg>feat(tags): tags are node in the form type:name<commit_after>/* jslint node: true, esnext: true */

'use strict';

const address = require('network-address'),
	url = require('url'),
	route = require('koa-route'),
	endpoint = require('kronos-endpoint'),
	service = require('kronos-service'),
	ServiceConsumerMixin = require('kronos-service').ServiceConsumerMixin;

class ServiceConsul extends service.Service {
	static get name() {
		return 'consul';
	}

	get type() {
		return ServiceConsul.name;
	}

	get autostart() {
		return true;
	}

	constructor(config, owner) {
		super(config, owner);

		const nodesEndpoint = new endpoint.ReceiveEndpoint('nodes', this, {
			createOpposite: true
		});

		nodesEndpoint.receive = request => {
			if (request.update) {
				const watch = this.consul.watch({
					method: this.consul.catalog.service.nodes,
					options: {
						service: this.serviceDefinition.name
					}
				});

				watch.on('change', (data, res) => {
					this.info(data);
					nodesEndpoint.opposite.receive(data);
				});

				watch.on('error', err => this.error(err));
			}

			return this.kronosNodes();
		};

		this.addEndpoint(nodesEndpoint);
	}

	get configurationAttributes() {
		const co = this.consulOptions;

		function consulOptionSetter(value, attribute) {
			if (value !== undefined) {
				co[attribute.name] = value;
			}
		}

		return Object.assign({
			'host': {
				description: 'consul host',
				default: 'localhost',
				type: 'string',
				setter: consulOptionSetter
			},
			'port': {
				description: 'consul port',
				default: 8500,
				type: 'integer',
				setter: consulOptionSetter
			},
			'secure': {
				default: false,
				type: 'boolean',
				setter: consulOptionSetter
			},
			'ca': {
				setter: consulOptionSetter
			},
			'id': {
				description: 'kronos service id',
				type: 'string',
				// id of our node in the consul cluster
				default: address()
			},
			'checkPath': {
				description: 'url path used for the kronos check',
				type: 'string',
				default: '/check'
			},
			'checkInterval': {
				description: 'interval the kronos check is called',
				default: '10',
				type: 'duration'
			},
			'checkTimeout': {
				description: 'timeout for the kronos check interval',
				default: '5',
				type: 'duration'
			}
		}, super.configurationAttributes);
	}

	_configure(config) {
		if (this.consulOptions === undefined) {
			this.consulOptions = {
				promisify(fn) {
					return new Promise((resolve, reject) => {
						try {
							return fn((err, data, res) => {
								if (err) {
									err.res = res;
									return reject(err);
								}
								return resolve([data, res]);
							});
						} catch (err) {
							return reject(err);
						}
					});
				}
			};
		}

		const modified = super._configure(config);

		// TODO where does baseUrl come from ?
		delete this.consulOptions.baseUrl;

		this.consul = require('consul')(this.consulOptions);

		return modified;
	}

	get serviceDefinition() {
		function asSeconds(value) {
			return value instanceof String && value.matches(/s$/) ? value : `${value}s`;
		}

		return {
			name: 'kronos',
			id: this.id,
			port: this.listener.port,
			address: this.listener.hostname,
			tags: this.tags,
			check: {
				id: this.listener.url + this.checkPath,
				http: this.listener.url + this.checkPath,
				interval: asSeconds(this.checkInterval),
				timeout: asSeconds(this.checkTimeout)
			}
		};
	}

	updateTags() {
			this.tags = Object.keys(this.owner.steps).map(name => `step:${name}`);
		}
		/**
		 * Register the kronos service in consul
		 * @return {Promise} that fullfills on succesfull startup
		 */
	_start() {
		return super._start().then(() => {
			this.updateTags();

			// wait until health-check and koa services are present
			return ServiceConsumerMixin.defineServiceConsumerProperties(this, {
				listener: {
					name: 'koa-admin',
					type: 'koa'
				},
				hcs: {
					name: 'health-check',
					type: 'health-check'
				}
			}, this.owner, true).then(() =>
				this.listener.start().then(() =>
					this.consul.agent.service.register(this.serviceDefinition).then(f => {
						this.consul.status.leader().then(leader => this.info(level =>
							`Consul raft leader is ${Object.keys(leader).join(',')}`));
						this.consul.status.peers().then(peers => this.trace(level =>
							`Consul raft peers are ${peers.map(p => p.body)}`));
						this.kronosNodes().then(nodes => this.info(level =>
							`Kronos nodes are ${nodes.map( n => n.ServiceID)}`));

						this._stepRegisteredListener = step => {
							this.updateTags();
							this.update(5000);
						};

						this.owner.addListener('stepRegistered', this._stepRegisteredListener);

						this.listener.koa.use(route.get(this.checkPath, ctx =>
							this.hcs.endpoints.state.receive({}).then(r => {
								this.info({
									'health': r
								});
								this.status = r ? 200 : 300;
								ctx.body = r ? 'OK' : 'ERROR';
							})
						));

						return Promise.resolve();
					})
				)
			);
		});
	}

	/**
	 * deregister the service from consul
	 * @return {Promise} that fullfills when the deregitering has finished
	 */
	_stop() {
		return this.consul.agent.service.deregister(this.serviceDefinition.id).then(f => {
			if (this._stepRegisteredListener) {
				this.owner.removeListener('stepRegistered', this._stepRegisteredListener);
				this._stepRegisteredListener = undefined;
			}
			return Promise.resolve();
		});
	}

	/**
	 * Update service definition in consul
	 * @param {Number} delay time to wait before doing the unregister/register action
	 */
	update(delay) {
		const reregister = () =>
			this.consul.agent.service.deregister(this.serviceDefinition.id)
			.then(() => this.consul.agent.service.register(this.serviceDefinition));

		if (this._updateTimer) {
			clearTimeout(this._updateTimer);
		}

		if (delay) {
			this._updateTimer = setTimeout(reregister, delay);
		} else {
			return reregister();
		}
	}

	kronosNodes() {
		return this.consul.catalog.service.nodes({
			service: this.serviceDefinition.name
		}).then(response => response[0]);
	}

	registerService(name, options) {
		this.info({
			message: 'registerService',
			name: name,
			options: options
		});

		const u = url.parse(options.url);

		/*
				const watch = this.consul.watch({
					method: this.consul.kv.get,
					options: {
						key: `services/${name}/${this.id}/url`
					}
				});

				watch.on('change', (data, res) => {
					console.log('change data:', data);
				});

				watch.on('error', err => console.log('error:', err));
		*/

		return this.consul.kv.set({
			key: `services/${name}/${this.id}/url`,
			value: options.url
		});

		/*
				const serviceDefinition = {
					name: name,
					id: u.href,
					address: u.hostname,
					port: parseInt(u.port, 10),
					tags: options.tags
				};

				return consul.agent.service.register(serviceDefinition).then(f => {
					//this.info(`registered: ${JSON.stringify(f)}`);
					return Promise.resolve();
				});
				*/
	}

	unregisterService(name) {
		this.info({
			message: 'unregisterService',
			name: name
		});

		return this.consul.kv.del({
			key: `services/${name}/${this.id}`,
			recurse: true
		});

		//return consul.agent.service.deregister(name);
	}

	* serviceURLs(name) {
		let si = [];

		let firstPromise = this.consul.kv.get({
				key: `services/${name}`,
				recurse: true
			})
			.then(data => {
				si = data[0].map(d => d.Value);
				firstPromise = undefined;
				return si.length === 0 ? Promise.reject() : Promise.resolve(si[0]);
			});

		while (firstPromise) {
			yield firstPromise;
			//console.log(`size: ${si.length} ${firstPromise}`);
		}

		if (si.length) {
			for (let i = 1;; i++) {
				if (i >= si.length) {
					i = 0;
				}
				//console.log(`yield: ${i} ${si.length}`);
				yield Promise.resolve(si[i]);
			}
		}
		return undefined;
	}
}

module.exports.registerWithManager = manager =>
	manager.registerServiceFactory(ServiceConsul).then(sf =>
		manager.declareService({
			'type': sf.name,
			'name': 'registry'
		}));
<|endoftext|>


<commit_before>/* jslint node: true, esnext: true */
"use strict";

const http = require('http'),
  https = require('https'),
  address = require('network-address'),
  Koa = require('kronos-koa'),
  IO = require('koa-socket'),
  Service = require('kronos-service').Service,
  ReceiveEndpoint = require('kronos-endpoint').ReceiveEndpoint;

const configAttributes = {
  port: {
    needsRestart: true,
    default: 9898
  },
  hostname: {
    needsRestart: true,
    default: address()
  },
  key: {
    needsRestart: true
  },
  cert: {
    needsRestart: true
  },
  timeout: {
    default: 120000
  },
  io: {
    needsRestart: true
  }
};

/**
 * HTTP server
 */
class ServiceKOA extends Service {

  static get name() {
    return "koa";
  }

  get type() {
    return ServiceKOA.name;
  }

  constructor(config, owner) {
    super(config, owner);

    this.koa = new Koa();

    const props = {};

    Object.keys(configAttributes).forEach(name =>
      props[name] = {
        get() {
          return config[name] || configAttributes[name].default;
        }
      });

    Object.defineProperties(this, props);

    const io = new ReceiveEndpoint('io');
    io.receive = request => {
      if (this.koa.io) {
        this.koa.io.broadcast(request.event, request.data);
      }
      return Promise.resolve();
    };

    this.addEndpoint(io);
  }

  get isSecure() {
    return this.key !== undefined;
  }

  get serverOptions() {
    if (this.isSecure) {
      return {
        key: this.key,
        cert: this.cert
      };
    }

    return undefined;
  }

  get scheme() {
    return this.isSecure ? 'https' : 'http';
  }

  get url() {
    return `${this.scheme}://${this.hostname}:${this.port}`;
  }

  /**
   * apply new configuration.
   * if required restarts the server
   */
  configure(config) {
    let needsRestart = false;

    if (config.timeout) {
      this.server.setTimeout(config.timeout);
    }

    Object.keys(configAttributes).forEach(name => {
      if (config[name] !== undefined && this[name] !== config[name]) {
        needsRestart |= configAttributes[name].needsRestart;
        this.config[name] = config[name];
      }
    });

    if (config.io) {
      const io = new IO();
      io.attach(this.koa);
    }

    return needsRestart ? this.restartIfRunning() : Promise.resolve();
  }

  _start() {
    if (!this.server) {
      if (this.isSecure) {
        this.server = https.createServer(this.serverOptions, this.koa.callback());
      } else {
        this.server = http.createServer(this.koa.callback());
      }

      if (this.timeout) {
        this.server.setTimeout(this.timeout);
      }

      return new Promise((fullfill, reject) => {
        this.trace(level => `starting ${this.url}`);

        try {
          this.server.listen(this.port, this.hostname, err => {
            if (err) {
              this.server = undefined;
              reject(err);
            } else {
              fullfill();
            }
          });
        } catch (e) {
          this.error(e);
          reject(e);
        }
      });
    }

    return Promise.resolve();
  }

  _stop() {
    return new Promise((fulfill, reject) => {
      this.trace(level => `stopping ${this.url}`);

      this.server.close(err => {
        if (err) {
          reject(err);
        } else {
          this.server = undefined;
          fulfill();
        }
      });
    });
  }
}

module.exports.Service = ServiceKOA;

module.exports.registerWithManager = manager => manager.registerServiceFactory(ServiceKOA);
<commit_msg>fix(config): call super.configure() first<commit_after>/* jslint node: true, esnext: true */
"use strict";

const http = require('http'),
  https = require('https'),
  address = require('network-address'),
  Koa = require('kronos-koa'),
  IO = require('koa-socket'),
  Service = require('kronos-service').Service,
  ReceiveEndpoint = require('kronos-endpoint').ReceiveEndpoint;

const configAttributes = {
  port: {
    needsRestart: true,
    default: 9898
  },
  hostname: {
    needsRestart: true,
    default: address()
  },
  key: {
    needsRestart: true
  },
  cert: {
    needsRestart: true
  },
  timeout: {
    default: 120000
  },
  io: {
    needsRestart: true
  }
};

/**
 * HTTP server
 */
class ServiceKOA extends Service {

  static get name() {
    return "koa";
  }

  get type() {
    return ServiceKOA.name;
  }

  constructor(config, owner) {
    super(config, owner);

    this.koa = new Koa();

    const props = {};

    Object.keys(configAttributes).forEach(name =>
      props[name] = {
        get() {
          return config[name] || configAttributes[name].default;
        }
      });

    Object.defineProperties(this, props);

    const io = new ReceiveEndpoint('io');
    io.receive = request => {
      if (this.koa.io) {
        this.koa.io.broadcast(request.event, request.data);
      }
      return Promise.resolve();
    };

    this.addEndpoint(io);
  }

  get isSecure() {
    return this.key !== undefined;
  }

  get serverOptions() {
    if (this.isSecure) {
      return {
        key: this.key,
        cert: this.cert
      };
    }

    return undefined;
  }

  get scheme() {
    return this.isSecure ? 'https' : 'http';
  }

  get url() {
    return `${this.scheme}://${this.hostname}:${this.port}`;
  }

  /**
   * apply new configuration.
   * if required restarts the server
   */
  configure(config) {
  	const sp = super.configure(config);
    let needsRestart = false;

    if (config.timeout) {
      this.server.setTimeout(config.timeout);
    }

    Object.keys(configAttributes).forEach(name => {
      if (config[name] !== undefined && this[name] !== config[name]) {
        needsRestart |= configAttributes[name].needsRestart;
        this.config[name] = config[name];
      }
    });

    if (config.io) {
      const io = new IO();
      io.attach(this.koa);
    }

    return needsRestart ? sp.then( p => this.restartIfRunning()) : sp;
  }

  _start() {
    if (!this.server) {
      if (this.isSecure) {
        this.server = https.createServer(this.serverOptions, this.koa.callback());
      } else {
        this.server = http.createServer(this.koa.callback());
      }

      if (this.timeout) {
        this.server.setTimeout(this.timeout);
      }

      return new Promise((fullfill, reject) => {
        this.trace(level => `starting ${this.url}`);

        try {
          this.server.listen(this.port, this.hostname, err => {
            if (err) {
              this.server = undefined;
              reject(err);
            } else {
              fullfill();
            }
          });
        } catch (e) {
          this.error(e);
          reject(e);
        }
      });
    }

    return Promise.resolve();
  }

  _stop() {
    return new Promise((fulfill, reject) => {
      this.trace(level => `stopping ${this.url}`);

      this.server.close(err => {
        if (err) {
          reject(err);
        } else {
          this.server = undefined;
          fulfill();
        }
      });
    });
  }
}

module.exports.Service = ServiceKOA;

module.exports.registerWithManager = manager => manager.registerServiceFactory(ServiceKOA);
<|endoftext|>


<commit_before><commit_msg>you can customize icon class now<commit_after><|endoftext|>


<commit_before>/* jslint node: true, esnext: true */

'use strict';

const endpoint = require('kronos-endpoint'),
	service = require('kronos-service'),
	mat = require('model-attributes'),
	Gelf = require('gelf');

/**
 * Log receiving service
 */
class GelfLogger extends service.Logger {

	static get name() {
		return 'gelf-logger';
	}

	static get configurationAttributes() {
		return Object.assign(mat.createAttributes({
			graylogPort: {
				description: 'gelf server port',
				type: 'integer',
				default: 12201,
				needsRestart: true
			},
			graylogHostname: {
				description: 'gelf server name',
				type: 'string',
				default: '127.0.0.1',
				needsRestart: true
			},
			connection: {
				type: 'string',
				default: 'wan',
				needsRestart: true
			},
			maxChunkSizeWan: {
				type: 'integer',
				default: 1420,
				needsRestart: true
			},
			maxChunkSizeLan: {
				type: 'integer',
				default: 8154,
				needsRestart: true
			}
		}), service.Service.configurationAttributes);
	}

	_start() {
		const gelf = new Gelf({
			graylogPort: this.graylogPort,
			graylogHostname: this.graylogHostname,
			connection: this.connection,
			maxChunkSizeWan: this.maxChunkSizeWan,
			maxChunkSizeLan: this.maxChunkSizeLan
		});

		this.endpoints.log.receive = entry => {
			try {
				gelf.emit('gelf.log', entry);
			} catch (e) {
				console.log(`Unable to log entry with the following keys: ${Object.keys(entry)} ${e}`);
				return Promise.reject(e);
			}
			return Promise.resolve();
		};

		return Promise.resolve();
	}
}

module.exports.registerWithManager = manager =>
	manager.registerServiceFactory(GelfLogger).then(sf => {
		return manager.declareService({
			type: GelfLogger.name,
			name: 'logger'
		});
	});
<commit_msg>fix(config): use more precise attribute types<commit_after>/* jslint node: true, esnext: true */

'use strict';

const endpoint = require('kronos-endpoint'),
	service = require('kronos-service'),
	mat = require('model-attributes'),
	Gelf = require('gelf');

/**
 * Log receiving service
 */
class GelfLogger extends service.Logger {

	static get name() {
		return 'gelf-logger';
	}

	static get configurationAttributes() {
		return Object.assign(mat.createAttributes({
			graylogPort: {
				description: 'gelf server port',
				type: 'ip-port',
				default: 12201,
				needsRestart: true
			},
			graylogHostname: {
				description: 'gelf server name',
				type: 'hostname',
				default: '127.0.0.1',
				needsRestart: true
			},
			connection: {
				type: 'string',
				default: 'wan',
				needsRestart: true
			},
			maxChunkSizeWan: {
				type: 'integer',
				default: 1420,
				needsRestart: true
			},
			maxChunkSizeLan: {
				type: 'integer',
				default: 8154,
				needsRestart: true
			}
		}), service.Service.configurationAttributes);
	}

	_start() {
		const gelf = new Gelf({
			graylogPort: this.graylogPort,
			graylogHostname: this.graylogHostname,
			connection: this.connection,
			maxChunkSizeWan: this.maxChunkSizeWan,
			maxChunkSizeLan: this.maxChunkSizeLan
		});

		this.endpoints.log.receive = entry => {
			try {
				gelf.emit('gelf.log', entry);
			} catch (e) {
				console.error(`Unable to log entry with the following keys: ${Object.keys(entry)} ${e}`);
				return Promise.reject(e);
			}
			return Promise.resolve();
		};

		return Promise.resolve();
	}
}

module.exports.registerWithManager = manager =>
	manager.registerServiceFactory(GelfLogger).then(sf => {
		return manager.declareService({
			type: GelfLogger.name,
			name: 'logger'
		});
	});
<|endoftext|>


<commit_before>angular.module('q.angularS3MultipartUploads', []).
service('S3Upload', function($window, $rootScope) {
    function extend(obj1, obj2, obj3) {
        if (typeof obj1 == 'undefined') {
            obj1 = {};
        }
        if (typeof obj3 == 'object') {
            for (var key in obj3) {
                obj2[key] = obj3[key];
            }
        }
        for (var key2 in obj2) {
            obj1[key2] = obj2[key2];
        }
        return obj1;
    }

    function joinUrlElements() {
        var re1 = new RegExp('^\\/|\\/$', 'g'),
            elts = Array.prototype.slice.call(arguments);
        return elts.map(function(element) {
            return element.replace(re1, "");
        }).join('/');
    }
    var S3Upload = {};
    //implementation
    S3Upload.supported = !((typeof($window.File) == 'undefined') || (typeof($window.Blob) == 'undefined') || !(!!$window.Blob.prototype.webkitSlice || !!$window.Blob.prototype.mozSlice || $window.Blob.prototype.slice));
    if (!S3Upload.supported) {
        throw 'FileS3Upload is unsupported for you browser';
    }
    this.subscribe = function(scope, event, callback) {
            var handler = $rootScope.$on(event, callback);
            scope.$on('$destroy', handler);
        },
        this.c = function(c) {
            var required_keys = ['aws_url', 'file_name', 'file', 'auth_url', 'bucket', 'aws_key_id', 'auth_url_headers'],
                missed_keys = [],
                all_keys = [];
            var key;
            var ind;
            S3Upload.config = extend({
                    partSize: 6 * 1024 * 1024
                }, // 6 Mb
                c || {});
            console.log(S3Upload.config);
            // "Check mandatory keys in config"
            for (key in S3Upload.config) {
                if (S3Upload.config.hasOwnProperty(key)) {
                    all_keys.push(key);
                }
            }
            for (ind in required_keys) {
                if (all_keys.indexOf(required_keys[ind]) == -1) {
                    missed_keys.push(required_keys[ind]);
                }
            }
            if (missed_keys.length > 0) {
                S3Upload.config.not_supported_error && S3Upload.config.not_supported_error();
                S3Upload.config.scope.$emit('not_supported_error', {
                    missed_keys: missed_keys
                });
                throw 'Missed keys in config: ' + missed_keys.join(', ');
            }
            // END "Check mandatory keys in config"
            S3Upload.config.file_name = encodeURIComponent(S3Upload.config.file_name);
            S3Upload.config.file.name = encodeURIComponent(S3Upload.config.file.name);
            S3Upload.count_of_parts = Math.ceil(S3Upload.config.file.size / S3Upload.config.partSize) || 1;
            S3Upload.total = S3Upload.config.file.size;
            S3Upload.loaded = 0;
            S3Upload.current_part = 1;
            S3Upload.parts = [];
            S3Upload.subscribe = this.subscribe;
            console.log('Total count of parts = ' + S3Upload.count_of_parts);
            return S3Upload;
            //return x.toString(16);
        };
    S3Upload.base_onreadystatechange = function(setup, xhr) {
        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                setup.f_200 && setup.f_200()
            } else if (xhr.readyState == 0) {
                S3Upload.config.scope.$emit('on_abort', {
                    xhr: xhr
                });
                S3Upload.config.on_abort && S3Upload.config.on_abort(xhr);
            } else {
                S3Upload.config.scope.$emit('on_non_200_error', {
                    xhr: xhr
                });
                S3Upload.config.on_non_200_error && S3Upload.config.on_non_200_error(xhr) || S3Upload.config[setup.name_non_200_error] && S3Upload.config[setup.name_non_200_error](xhr);
            }
        }
    };
    S3Upload._sign_request = function(method, suffix_to_sign, contentType, success_callback) {
        var xhr = S3Upload.getXmlHttp(),
            to_sign,
            signature,
            date_gmt = new Date().toUTCString();
        to_sign = method + '\n\n' + contentType + '\n\nx-amz-date:' + date_gmt + '\n/' + S3Upload.config.bucket + '/' + S3Upload.config.file_name + suffix_to_sign;
        xhr.open('GET', joinUrlElements(S3Upload.config.auth_url, '?to_sign=' + encodeURIComponent(to_sign)));
        for (var key in S3Upload.config.auth_url_headers) {
            if (S3Upload.config.auth_url_headers.hasOwnProperty(key)) {
                xhr.setRequestHeader(key, S3Upload.config.auth_url_headers[key]);
            }
        }
        xhr.onreadystatechange = function() {
            S3Upload.base_onreadystatechange({
                f_200: function() {
                    //signature will be in a format as
                    //    {
                    //      "signature": "4FxayeX7JhFiTPl022gxEjISILk="
                    //    }
                    //
                    //signature = xhr.response.signature;
                    signature = decodeURIComponent(JSON.parse(xhr.response).signature);
                    S3Upload.config.scope.$emit('success_callback', {
                        signature: signature,
                        date_gmt: date_gmt
                    });
                    success_callback && success_callback(signature, date_gmt);
                },
                name_non_200_error: 'on_auth_error'
            }, xhr);
        };
        xhr.send(null);
    };
    S3Upload.init_multipart_upload = function() {
        S3Upload._sign_request('POST', '?uploads', '', function(signature, date_gmt) {
            console.log(signature);
            S3Upload._get_upload_id(signature, date_gmt); // as result we have S3Upload.UploadId
        });
    };
    S3Upload._send_part = function() {
        var from_byte,
            to_byte,
            suffix_to_sign,
            blob;

        if (S3Upload.parts.length == S3Upload.count_of_parts) {
            suffix_to_sign = '?uploadId=' + S3Upload.UploadId;
            S3Upload._sign_request('POST', suffix_to_sign, 'application/xml; charset=UTF-8', function(signature, date_gmt) {
                S3Upload.complete_multipart_upload(signature, date_gmt, suffix_to_sign);
            });
            console.log('Try to complete');
            return;
        }
        from_byte = (S3Upload.current_part - 1) * S3Upload.config.partSize; // S3Upload.current_part starts from 1
        to_byte = S3Upload.current_part * S3Upload.config.partSize;
        blob = S3Upload.config.file.slice(from_byte, to_byte);
        suffix_to_sign = '?partNumber=' + S3Upload.current_part + '&uploadId=' + S3Upload.UploadId;
        S3Upload._sign_request('PUT', suffix_to_sign, '', function(signature, date_gmt) {
            S3Upload._send_blob(signature, date_gmt, suffix_to_sign, blob);
        });
    };
    S3Upload._send_blob = function(signature, date_gmt, suffix, blob) {
        var xhr = S3Upload.getXmlHttp(),
            ETag;
        xhr.open('PUT', joinUrlElements(S3Upload.config.aws_url, '/' + S3Upload.config.file_name + suffix));
        xhr.setRequestHeader('Authorization', 'AWS ' + S3Upload.config.aws_key_id + ':' + signature);
        xhr.setRequestHeader('x-amz-date', date_gmt);
        if (xhr.upload) {
            xhr.upload.addEventListener("progress", function(prog) {
                //                    value = ~~((prog.loaded / prog.total) * 100);
                S3Upload.config.scope.$emit('on_progress', {
                    total: S3Upload.total,
                    loaded: S3Upload.loaded + prog.loaded
                });
                S3Upload.config.on_progress && S3Upload.config.on_progress(S3Upload.total, S3Upload.loaded + prog.loaded);
            }, false);
        }
        xhr.onreadystatechange = function() {
            S3Upload.base_onreadystatechange({
                f_200: function() {
                    ETag = xhr.getResponseHeader('ETag');
                    console.log('ETag = ' + ETag + ' For part #' + S3Upload.current_part);
                    S3Upload.parts.push(ETag);
                    S3Upload.loaded += blob.size;
                   S3Upload.config.scope.$emit('on_part_upload', {
                        xhr: xhr,
                        ETag: ETag,
                        part_number: S3Upload.current_part
                    });
                    S3Upload.config.scope.$emit('on_progress', {
                        total: S3Upload.total,
                        loaded: S3Upload.loaded
                    });
                    S3Upload.config.on_progress && S3Upload.config.on_progress(S3Upload.total, S3Upload.loaded);
                    // put it here becouse in future we should keep for unuploaded parts

                    S3Upload.config.on_part_upload && S3Upload.config.on_part_upload(xhr, ETag, S3Upload.current_part);
                    S3Upload.current_part += 1;
                    setTimeout(function() { // to avoid recursion
                        S3Upload._send_part();
                    }, 50);
                },
                name_non_200_error: 'on_send_part_error'
            }, xhr);
        };
        xhr.send(blob);
    };
    S3Upload._get_upload_id = function(signature, date_gmt) {
        var xhr = S3Upload.getXmlHttp(),
            uploadId;
        xhr.open('POST', joinUrlElements(S3Upload.config.aws_url, '/' + S3Upload.config.file_name + '?uploads'));
        xhr.setRequestHeader('Authorization', 'AWS ' + S3Upload.config.aws_key_id + ':' + signature);
        //xhr.setRequestHeader('Access-Control-Request-Method', 'OPTIONS');
        xhr.setRequestHeader('x-amz-date', date_gmt);
        xhr.onreadystatechange = function() {
            S3Upload.base_onreadystatechange({
                f_200: function() {
                    uploadId = xhr.response.match(/<UploadId\>(.+)<\/UploadId\>/);
                    if (uploadId && uploadId[1]) {
                        S3Upload.UploadId = uploadId[1];
                        console.log('Got UploadId: ' + S3Upload.UploadId);
                        S3Upload.config.scope.$emit('on_get_upload_id', {
                            xhr: xhr,
                            upload_id: S3Upload.UploadId
                        });
                        S3Upload.config.on_get_upload_id && S3Upload.config.on_get_upload_id(xhr, S3Upload.UploadId);
                        setTimeout(function() {
                            S3Upload._send_part();
                        }, 50);
                    } else {
                        S3Upload.config.scope.$emit('on_non_200_error', {
                            xhr: xhr
                        });
                        S3Upload.config.scope.$emit('on_absence_upload_id_error', {
                            xhr: xhr
                        });
                        S3Upload.config.on_non_200_error && S3Upload.config.on_non_200_error(xhr) || S3Upload.config.on_absence_upload_id_error && S3Upload.config.on_absence_upload_id_error(xhr);
                    }
                },
                name_non_200_error: 'on_getting_upload_id_error'
            }, xhr);
        };
        xhr.send(null);
    };
    S3Upload.complete_multipart_upload = function(signature, date_gmt, suffix) {
        var xhr = S3Upload.getXmlHttp(),
            completeDoc = '<CompleteMultipartUpload>';
        xhr.open('POST', joinUrlElements(S3Upload.config.aws_url, '/' + S3Upload.config.file_name + suffix));
        xhr.setRequestHeader('Authorization', 'AWS ' + S3Upload.config.aws_key_id + ':' + signature);
        xhr.setRequestHeader('Content-Type', 'application/xml; charset=UTF-8');
        xhr.setRequestHeader('x-amz-date', date_gmt);
        xhr.onreadystatechange = function() {
            S3Upload.base_onreadystatechange({
                f_200: function() {
                    console.log('END');
                    S3Upload.config.scope.$emit('on_multipart_upload_complete', {
                        xhr: xhr
                    });
                    S3Upload.config.on_multipart_upload_complete && S3Upload.config.on_multipart_upload_complete(xhr);
                },
                name_non_200_error: 'on_complete_multipart_error'
            }, xhr);
        };
        S3Upload.parts.forEach(function(ETag, partNumber) {
            completeDoc += '<Part><PartNumber>' + (partNumber + 1) + '</PartNumber><ETag>' + ETag + '</ETag></Part>';
        });
        completeDoc += '</CompleteMultipartUpload>';
        xhr.send(completeDoc);
    };
    S3Upload.abort = function() {
        S3Upload.xhr.abort();
    };
    S3Upload.getXmlHttp = function() {
        var xmlhttp;
        try {
            xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (E) {
                xmlhttp = false;
            }
        }
        if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
            xmlhttp = new XMLHttpRequest();
        }
        xmlhttp.onerror = function() {
            S3Upload.config.scope.$emit('on_network_error', {
                xhr: xhr
            });
            S3Upload.config.on_network_error && S3Upload.config.on_network_error(xhr);
        };
        S3Upload.xhr = xmlhttp;
        return xmlhttp;
    };
})<commit_msg>cleanup<commit_after>angular.module('q.angularS3MultipartUploads', []).
service('S3Upload', function($window, $rootScope) {
	    function extend(obj1, obj2, obj3) {
	        if (typeof obj1 == 'undefined') {
	            obj1 = {};
	        }
	        if (typeof obj3 == 'object') {
	            for (var key in obj3) {
	                obj2[key] = obj3[key];
	            }
	        }
	        for (var key2 in obj2) {
	            obj1[key2] = obj2[key2];
	        }
	        return obj1;
	    }

	    function joinUrlElements() {
	        var re1 = new RegExp('^\\/|\\/$', 'g'),
	            elts = Array.prototype.slice.call(arguments);
	        return elts.map(function(element) {
	            return element.replace(re1, "");
	        }).join('/');
	    }

	    var S3Upload = {};
	    //implementation
	    S3Upload.supported = !((typeof($window.File) == 'undefined') || (typeof($window.Blob) == 'undefined') || !(!!$window.Blob.prototype.webkitSlice || !!$window.Blob.prototype.mozSlice || $window.Blob.prototype.slice));
	    if (!S3Upload.supported) {
	        throw 'FileS3Upload is unsupported for you browser';
	    }
        this.c = function(c) {
            var required_keys = ['aws_url', 'file_name', 'file', 'auth_url', 'bucket', 'aws_key_id', 'auth_url_headers'],
                missed_keys = [],
                all_keys = [];
            var key;
            var ind;
            S3Upload.config = extend({
                    partSize: 6 * 1024 * 1024
                }, // 6 Mb
                c || {});
            console.log(S3Upload.config);
            // "Check mandatory keys in config"
            for (key in S3Upload.config) {
                if (S3Upload.config.hasOwnProperty(key)) {
                    all_keys.push(key);
                }
            }
            for (ind in required_keys) {
                if (all_keys.indexOf(required_keys[ind]) == -1) {
                    missed_keys.push(required_keys[ind]);
                }
            }
            if (missed_keys.length > 0) {
                S3Upload.config.not_supported_error && S3Upload.config.not_supported_error();
                S3Upload.config.scope.$emit('not_supported_error', {
                    missed_keys: missed_keys
                });
                throw 'Missed keys in config: ' + missed_keys.join(', ');
            }
            // END "Check mandatory keys in config"
            S3Upload.config.file_name = encodeURIComponent(S3Upload.config.file_name);
            S3Upload.config.file.name = encodeURIComponent(S3Upload.config.file.name);
            S3Upload.count_of_parts = Math.ceil(S3Upload.config.file.size / S3Upload.config.partSize) || 1;
            S3Upload.total = S3Upload.config.file.size;
            S3Upload.loaded = 0;
            S3Upload.current_part = 1;
            S3Upload.parts = [];
            S3Upload.subscribe = this.subscribe;
            console.log('Total count of parts = ' + S3Upload.count_of_parts);
            return S3Upload;

        };
    S3Upload.base_onreadystatechange = function(setup, xhr) {
        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                setup.f_200 && setup.f_200()
            } else if (xhr.readyState == 0) {
                S3Upload.config.scope.$emit('on_abort', {
                    xhr: xhr
                });
                S3Upload.config.on_abort && S3Upload.config.on_abort(xhr);
            } else {
                S3Upload.config.scope.$emit('on_non_200_error', {
                    xhr: xhr
                });
                S3Upload.config.on_non_200_error && S3Upload.config.on_non_200_error(xhr) || S3Upload.config[setup.name_non_200_error] && S3Upload.config[setup.name_non_200_error](xhr);
            }
        }
    };
    S3Upload._sign_request = function(method, suffix_to_sign, contentType, success_callback) {
        var xhr = S3Upload.getXmlHttp(),
            to_sign,
            signature,
            date_gmt = new Date().toUTCString();
        to_sign = method + '\n\n' + contentType + '\n\nx-amz-date:' + date_gmt + '\n/' + S3Upload.config.bucket + '/' + S3Upload.config.file_name + suffix_to_sign;
        xhr.open('GET', joinUrlElements(S3Upload.config.auth_url, '?to_sign=' + encodeURIComponent(to_sign)));
        for (var key in S3Upload.config.auth_url_headers) {
            if (S3Upload.config.auth_url_headers.hasOwnProperty(key)) {
                xhr.setRequestHeader(key, S3Upload.config.auth_url_headers[key]);
            }
        }
        xhr.onreadystatechange = function() {
            S3Upload.base_onreadystatechange({
                f_200: function() {
                    //signature will be in a format as
                    //    {
                    //      "signature": "4FxayeX7JhFiTPl022gxEjISILk="
                    //    }
                    //
                    //signature = xhr.response.signature;
                    signature = decodeURIComponent(JSON.parse(xhr.response).signature);
                    S3Upload.config.scope.$emit('success_callback', {
                        signature: signature,
                        date_gmt: date_gmt
                    });
                    success_callback && success_callback(signature, date_gmt);
                },
                name_non_200_error: 'on_auth_error'
            }, xhr);
        };
        xhr.send(null);
    };
    S3Upload.init_multipart_upload = function() {
        S3Upload._sign_request('POST', '?uploads', '', function(signature, date_gmt) {
            console.log(signature);
            S3Upload._get_upload_id(signature, date_gmt); // as result we have S3Upload.UploadId
        });
    };
    S3Upload._send_part = function() {
        var from_byte,
            to_byte,
            suffix_to_sign,
            blob;

        if (S3Upload.parts.length == S3Upload.count_of_parts) {
            suffix_to_sign = '?uploadId=' + S3Upload.UploadId;
            S3Upload._sign_request('POST', suffix_to_sign, 'application/xml; charset=UTF-8', function(signature, date_gmt) {
                S3Upload.complete_multipart_upload(signature, date_gmt, suffix_to_sign);
            });
            console.log('Try to complete');
            return;
        }
        from_byte = (S3Upload.current_part - 1) * S3Upload.config.partSize; // S3Upload.current_part starts from 1
        to_byte = S3Upload.current_part * S3Upload.config.partSize;
        blob = S3Upload.config.file.slice(from_byte, to_byte);
        suffix_to_sign = '?partNumber=' + S3Upload.current_part + '&uploadId=' + S3Upload.UploadId;
        S3Upload._sign_request('PUT', suffix_to_sign, '', function(signature, date_gmt) {
            S3Upload._send_blob(signature, date_gmt, suffix_to_sign, blob);
        });
    };
    S3Upload._send_blob = function(signature, date_gmt, suffix, blob) {
        var xhr = S3Upload.getXmlHttp(),
            ETag;
        xhr.open('PUT', joinUrlElements(S3Upload.config.aws_url, '/' + S3Upload.config.file_name + suffix));
        xhr.setRequestHeader('Authorization', 'AWS ' + S3Upload.config.aws_key_id + ':' + signature);
        xhr.setRequestHeader('x-amz-date', date_gmt);
        if (xhr.upload) {
            xhr.upload.addEventListener("progress", function(prog) {
                //                    value = ~~((prog.loaded / prog.total) * 100);
                S3Upload.config.scope.$emit('on_progress', {
                    total: S3Upload.total,
                    loaded: S3Upload.loaded + prog.loaded
                });
                S3Upload.config.on_progress && S3Upload.config.on_progress(S3Upload.total, S3Upload.loaded + prog.loaded);
            }, false);
        }
        xhr.onreadystatechange = function() {
            S3Upload.base_onreadystatechange({
                f_200: function() {
                    ETag = xhr.getResponseHeader('ETag');
                    console.log('ETag = ' + ETag + ' For part #' + S3Upload.current_part);
                    S3Upload.parts.push(ETag);
                    S3Upload.loaded += blob.size;
                   S3Upload.config.scope.$emit('on_part_upload', {
                        xhr: xhr,
                        ETag: ETag,
                        part_number: S3Upload.current_part
                    });
                    S3Upload.config.scope.$emit('on_progress', {
                        total: S3Upload.total,
                        loaded: S3Upload.loaded
                    });
                    S3Upload.config.on_progress && S3Upload.config.on_progress(S3Upload.total, S3Upload.loaded);
                    // put it here becouse in future we should keep for unuploaded parts

                    S3Upload.config.on_part_upload && S3Upload.config.on_part_upload(xhr, ETag, S3Upload.current_part);
                    S3Upload.current_part += 1;
                    setTimeout(function() { // to avoid recursion
                        S3Upload._send_part();
                    }, 50);
                },
                name_non_200_error: 'on_send_part_error'
            }, xhr);
        };
        xhr.send(blob);
    };
    S3Upload._get_upload_id = function(signature, date_gmt) {
        var xhr = S3Upload.getXmlHttp(),
            uploadId;
        xhr.open('POST', joinUrlElements(S3Upload.config.aws_url, '/' + S3Upload.config.file_name + '?uploads'));
        xhr.setRequestHeader('Authorization', 'AWS ' + S3Upload.config.aws_key_id + ':' + signature);
        xhr.setRequestHeader('x-amz-date', date_gmt);
        xhr.onreadystatechange = function() {
            S3Upload.base_onreadystatechange({
                f_200: function() {
                    uploadId = xhr.response.match(/<UploadId\>(.+)<\/UploadId\>/);
                    if (uploadId && uploadId[1]) {
                        S3Upload.UploadId = uploadId[1];
                        console.log('Got UploadId: ' + S3Upload.UploadId);
                        S3Upload.config.scope.$emit('on_get_upload_id', {
                            xhr: xhr,
                            upload_id: S3Upload.UploadId
                        });
                        S3Upload.config.on_get_upload_id && S3Upload.config.on_get_upload_id(xhr, S3Upload.UploadId);
                        setTimeout(function() {
                            S3Upload._send_part();
                        }, 50);
                    } else {
                        S3Upload.config.scope.$emit('on_non_200_error', {
                            xhr: xhr
                        });
                        S3Upload.config.scope.$emit('on_absence_upload_id_error', {
                            xhr: xhr
                        });
                        S3Upload.config.on_non_200_error && S3Upload.config.on_non_200_error(xhr) || S3Upload.config.on_absence_upload_id_error && S3Upload.config.on_absence_upload_id_error(xhr);
                    }
                },
                name_non_200_error: 'on_getting_upload_id_error'
            }, xhr);
        };
        xhr.send(null);
    };
    S3Upload.complete_multipart_upload = function(signature, date_gmt, suffix) {
        var xhr = S3Upload.getXmlHttp(),
            completeDoc = '<CompleteMultipartUpload>';
        xhr.open('POST', joinUrlElements(S3Upload.config.aws_url, '/' + S3Upload.config.file_name + suffix));
        xhr.setRequestHeader('Authorization', 'AWS ' + S3Upload.config.aws_key_id + ':' + signature);
        xhr.setRequestHeader('Content-Type', 'application/xml; charset=UTF-8');
        xhr.setRequestHeader('x-amz-date', date_gmt);
        xhr.onreadystatechange = function() {
            S3Upload.base_onreadystatechange({
                f_200: function() {
                    console.log('END');
                    S3Upload.config.scope.$emit('on_multipart_upload_complete', {
                        xhr: xhr
                    });
                    S3Upload.config.on_multipart_upload_complete && S3Upload.config.on_multipart_upload_complete(xhr);
                },
                name_non_200_error: 'on_complete_multipart_error'
            }, xhr);
        };
        S3Upload.parts.forEach(function(ETag, partNumber) {
            completeDoc += '<Part><PartNumber>' + (partNumber + 1) + '</PartNumber><ETag>' + ETag + '</ETag></Part>';
        });
        completeDoc += '</CompleteMultipartUpload>';
        xhr.send(completeDoc);
    };
    S3Upload.abort = function() {
        S3Upload.xhr.abort();
    };
    S3Upload.getXmlHttp = function() {
        var xmlhttp;
        try {
            xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (E) {
                xmlhttp = false;
            }
        }
        if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
            xmlhttp = new XMLHttpRequest();
        }
        xmlhttp.onerror = function() {
            S3Upload.config.scope.$emit('on_network_error', {
                xhr: xhr
            });
            S3Upload.config.on_network_error && S3Upload.config.on_network_error(xhr);
        };
        S3Upload.xhr = xmlhttp;
        return xmlhttp;
    };
})<|endoftext|>