<commit_before>
// deps

	const path = require("path");
	const fs = require("fs");

	const sqlite3 = require("sqlite3").verbose();

// consts

	const EXPORT_DIR = path.join(__dirname, "..", "fr");

// module

module.exports = class WarcraftSoundsAPIV1Model {

	constructor() {
		this.db = new sqlite3.Database(':memory:');
	}

	init() {

		// open db
		return new Promise((resolve) => {
			this.db.serialize(resolve);

		// read file
		}).then(() => {

			return new Promise((resolve, reject) => {

				fs.readFile(path.join(__dirname, "data", "create.sql"), "utf8", (err, content) =>  {

					if (err) {
						reject(err);
					}
					else {

						let result = [];

							content.split(";").forEach((request) => {

								request = request
											.trim()
											.replace(/(?:\\[rn]|[\r\n]+)+/g, "\n")
											.replace(/\t/g, "")
											.split("\n").filter((line) => {
												return "" !== line.trim() && "--" !== line.substring(0, 2);
											}).join(" ").trim();

								if ("" !== request) {
									result.push(request + ";");
								}

							});

						resolve(result);

					}

				});

			});

		// execute requests
		}).then((queries) => {

			function execQuery(db,i) {

				if (i >= queries.length) {
					return Promise.resolve();
				}
				else {

					return new Promise((resolve, reject) => {

						db.run(queries[i], (err) => {

							if (err) {
								reject(err);
							}
							else {
								resolve();
							}

						});

					}).then(() => {
						return execQuery(db, i+1);
					});

				}

			}

			return execQuery(this.db, 0);

		});

	}

	getRaces() {

		return new Promise((resolve, reject) => {

			this.db.all("SELECT code, name FROM races;", (err, data) => {

				if (err) {
					reject(err);
				}
				else {
					resolve(data);
				}

			});

		});

	}

	getRace(code) {

		return new Promise((resolve, reject) => {

			this.db.get(
				"SELECT id, code, name FROM races WHERE code = ?;"
			, [ code ], (err, data) => {

				if (err) {
					reject(err);
				}
				else {
					resolve(data);
				}

			});

		}).then((race) => {

			if (!race) {
				return Promise.resolve(null);
			}
			else {

				let result = {
					code: race.code,
					name: race.name,
					characters: [],
					musics: [],
					warnings: []
				};

				return new Promise((resolve, reject) => {

					this.db.all("SELECT code, name FROM characters WHERE k_race = ?;"
					, [ race.id ], (err, data) => {

						if (err) {
							reject(err);
						}
						else {
							result.characters = data; resolve();
						}

					});

				}).then(() => {

					return new Promise((resolve, reject) => {

						this.db.all("SELECT code, name, file FROM musics WHERE k_race = ?;"
						, [ race.id ], (err, data) => {

							if (err) {
								reject(err);
							}
							else {
								result.musics = data; resolve();
							}

						});

					});

				}).then(() => {

					return new Promise((resolve, reject) => {

						this.db.all("SELECT code, name, file FROM warnings WHERE k_race = ?;"
						, [ race.id ], (err, data) => {

							if (err) {
								reject(err);
							}
							else {
								result.warnings = data; resolve();
							}

						});

					});

				}).then(() => {
					return Promise.resolve(result);
				});

			}

		});

	}

	getCharacter(codeRace, code) {

		return new Promise((resolve, reject) => {

			this.db.get(
				" SELECT characters.id, characters.code, characters.name" +
				" FROM characters INNER JOIN races ON races.id = characters.k_race" +
				" WHERE races.code = ? AND characters.code = ?;"
			, [ codeRace, code ], (err, data) => {

				if (err) {
					reject(err);
				}
				else {
					resolve(data);
				}

			});

		}).then((character) => {

			if (!character) {
				return Promise.resolve(null);
			}
			else {

				let result = {
					code: character.code,
					name: character.name,
					actions: []
				};

				return new Promise((resolve, reject) => {

					this.db.all(
						" SELECT actions.code, actions.name, actions.file, actions.file, actions_types.code AS type_code, actions_types.name AS type_name" +
						" FROM actions INNER JOIN actions_types ON actions_types.id = actions.k_action_type" +
						" WHERE actions.k_character = ?;"
					, [ character.id ], (err, data) => {

						if (err) {
							reject(err);
						}
						else {

							data.forEach((action) => {

								result.actions.push({
									code: action.code,
									name: action.name,
									type: {
										code: action.type_code,
										name: action.type_name
									},
									file: action.file
								});

							});

							resolve();

						}

					});

				}).then(() => {
					return Promise.resolve(result);
				});

			}

		});

	}

	release() {

		return new Promise((resolve, reject) => {

			this.db.close((err) => {

				if (err) {
					reject(err);
				}
				else {
					resolve();
				}

			});

		});

	}

};
<commit_msg>correction eslint<commit_after>
// deps

	const path = require("path");
	const fs = require("fs");

	const sqlite3 = require("sqlite3").verbose();

// consts

	const EXPORT_DIR = path.join(__dirname, "..", "fr");

// module

module.exports = class WarcraftSoundsAPIV1Model {

	constructor() {
		this.db = new sqlite3.Database(":memory:");
	}

	init() {

		// open db
		return new Promise((resolve) => {
			this.db.serialize(resolve);

		// read file
		}).then(() => {

			return new Promise((resolve, reject) => {

				fs.readFile(path.join(__dirname, "data", "create.sql"), "utf8", (err, content) =>  {

					if (err) {
						reject(err);
					}
					else {

						let result = [];

							content.split(";").forEach((request) => {

								request = request
											.trim()
											.replace(/(?:\\[rn]|[\r\n]+)+/g, "\n")
											.replace(/\t/g, "")
											.split("\n").filter((line) => {
												return "" !== line.trim() && "--" !== line.substring(0, 2);
											}).join(" ").trim();

								if ("" !== request) {
									result.push(request + ";");
								}

							});

						resolve(result);

					}

				});

			});

		// execute requests
		}).then((queries) => {

			function execQuery(db,i) {

				if (i >= queries.length) {
					return Promise.resolve();
				}
				else {

					return new Promise((resolve, reject) => {

						db.run(queries[i], (err) => {

							if (err) {
								reject(err);
							}
							else {
								resolve();
							}

						});

					}).then(() => {
						return execQuery(db, i+1);
					});

				}

			}

			return execQuery(this.db, 0);

		});

	}

	getRaces() {

		return new Promise((resolve, reject) => {

			this.db.all("SELECT code, name FROM races;", (err, data) => {

				if (err) {
					reject(err);
				}
				else {
					resolve(data);
				}

			});

		});

	}

	getRace(code) {

		return new Promise((resolve, reject) => {

			this.db.get(
				"SELECT id, code, name FROM races WHERE code = ?;"
			, [ code ], (err, data) => {

				if (err) {
					reject(err);
				}
				else {
					resolve(data);
				}

			});

		}).then((race) => {

			if (!race) {
				return Promise.resolve(null);
			}
			else {

				let result = {
					code: race.code,
					name: race.name,
					characters: [],
					musics: [],
					warnings: []
				};

				return new Promise((resolve, reject) => {

					this.db.all("SELECT code, name FROM characters WHERE k_race = ?;"
					, [ race.id ], (err, data) => {

						if (err) {
							reject(err);
						}
						else {
							result.characters = data; resolve();
						}

					});

				}).then(() => {

					return new Promise((resolve, reject) => {

						this.db.all("SELECT code, name, file FROM musics WHERE k_race = ?;"
						, [ race.id ], (err, data) => {

							if (err) {
								reject(err);
							}
							else {
								result.musics = data; resolve();
							}

						});

					});

				}).then(() => {

					return new Promise((resolve, reject) => {

						this.db.all("SELECT code, name, file FROM warnings WHERE k_race = ?;"
						, [ race.id ], (err, data) => {

							if (err) {
								reject(err);
							}
							else {
								result.warnings = data; resolve();
							}

						});

					});

				}).then(() => {
					return Promise.resolve(result);
				});

			}

		});

	}

	getCharacter(codeRace, code) {

		return new Promise((resolve, reject) => {

			this.db.get(
				" SELECT characters.id, characters.code, characters.name" +
				" FROM characters INNER JOIN races ON races.id = characters.k_race" +
				" WHERE races.code = ? AND characters.code = ?;"
			, [ codeRace, code ], (err, data) => {

				if (err) {
					reject(err);
				}
				else {
					resolve(data);
				}

			});

		}).then((character) => {

			if (!character) {
				return Promise.resolve(null);
			}
			else {

				let result = {
					code: character.code,
					name: character.name,
					actions: []
				};

				return new Promise((resolve, reject) => {

					this.db.all(
						" SELECT actions.code, actions.name, actions.file, actions.file, actions_types.code AS type_code, actions_types.name AS type_name" +
						" FROM actions INNER JOIN actions_types ON actions_types.id = actions.k_action_type" +
						" WHERE actions.k_character = ?;"
					, [ character.id ], (err, data) => {

						if (err) {
							reject(err);
						}
						else {

							data.forEach((action) => {

								result.actions.push({
									code: action.code,
									name: action.name,
									type: {
										code: action.type_code,
										name: action.type_name
									},
									file: action.file
								});

							});

							resolve();

						}

					});

				}).then(() => {
					return Promise.resolve(result);
				});

			}

		});

	}

	release() {

		return new Promise((resolve, reject) => {

			this.db.close((err) => {

				if (err) {
					reject(err);
				}
				else {
					resolve();
				}

			});

		});

	}

};
<|endoftext|>


<commit_before>/*global exports, require*/
var child_process = require('child_process'),
    constants = process.ENOENT ? process : require('constants'),
    Path = require('path'),
    _ = require('underscore'),
    assets = {};

assets.typeByExtension = {};

assets.typeByContentType = {};

assets.register = function (type, Constructor) {
    var prototype = Constructor.prototype;
    prototype.type = type;
    assets[type] = Constructor;
    if (prototype.contentType && !(prototype.contentType in assets.typeByContentType)) {
        assets.typeByContentType[prototype.contentType] = type;
    }
    if (prototype.defaultExtension) {
        assets.typeByExtension[prototype.defaultExtension] = type;
    }
    if (prototype.alternativeExtensions) {
        prototype.alternativeExtensions.forEach(function (alternativeExtension) {
            assets.typeByExtension[alternativeExtension] = type;
        });
    }
};

assets.lookupContentType = function (contentType) {
    if (contentType) {
        // Trim whitespace and semicolon suffixes such as ;charset=...
        contentType = contentType.match(/^\s*([^;\s]*)(?:;|\s|$)/)[1].toLowerCase(); // Will always match
        if (contentType in assets.typeByContentType) {
            return assets.typeByContentType[contentType];
        } else if (/\+xml$/i.test(contentType)) {
            return 'Xml';
        } else if (/^text\//i.test(contentType)) {
            return 'Text';
        } else {
            return 'Base';
        }
    }
};

assets.addTypeToAssetConfig = function (assetConfig, cb) {
    var type =
        assetConfig.type ||
        (assetConfig.contentType && assets.lookupContentType(assetConfig.contentType)) ||
        assets.typeByExtension[Path.extname(assetConfig.url.replace(/[\?\#].*$/, ""))];
    if (type) {
        assetConfig.type = type;
        process.nextTick(function () {
            cb(null, assetConfig);
        });
    } else {
        // Looks like there's no way around loading the asset and looking at the src or HTTP headers
        return assetConfig.rawSrcProxy(function (err, src, metadata) {
            if (err) {
                if (err.errno === constants.EISDIR || err.errno === constants.EINVAL) {
                    assetConfig.url += /\/$/.test(assetConfig.url) ? 'index.html' : '/index.html';
                    delete assetConfig.rawSrcProxy;
                    assetConfig.type = 'Html';
                    return cb(null, assetConfig);
                } else {
                    return cb(err);
                }
            }
            function foundType(type) {
                assetConfig.rawSrc = src;
                assetConfig.type = type;
                cb(null, assetConfig);
            }
            if (metadata && metadata.contentType) {
                // If the asset was served using HTTP, we shouldn't try to second guess by sniffing.
                foundType(assets.lookupContentType(metadata.contentType));
            } else if (src.length === 0) {
                foundType(); // Give up
            } else {
                // Work the magic
                var fileProcess = child_process.spawn('file', ['-b', '--mime-type', '-']),
                    fileOutput = '';
                fileProcess.stdout.on('data', function (chunk) {
                    fileOutput += chunk;
                }).on('end', function () {
                    foundType(assets.lookupContentType(fileOutput.match(/^([^\n]*)/)[1]));
                });
                fileProcess.stdin.write(src);
                fileProcess.stdin.end();
            }
        });
    }
};

assets.create = function (assetConfig) {
    if (!assetConfig.type) {
        throw new Error("assets.create: No type provided in assetConfig");
    }
    if (assetConfig.isAsset) {
        return assetConfig;
    } else {
        return new assets[assetConfig.type](assetConfig);
    }
};

require('fs').readdirSync(__dirname).forEach(function (fileName) {
    if (/\.js$/.test(fileName) && fileName !== 'index.js') {
        assets.register(fileName.replace(/\.js$/, ''), require('./' + fileName));
    }
});

_.extend(exports, assets);
<commit_msg>assets.addTypeToAssetConfig: Fixed the code that adds "index.html" to file: urls pointing at directories. Was broken for urls containing GET parameters or a fragment identifier.<commit_after>/*global exports, require*/
var child_process = require('child_process'),
    constants = process.ENOENT ? process : require('constants'),
    Path = require('path'),
    _ = require('underscore'),
    assets = {};

assets.typeByExtension = {};

assets.typeByContentType = {};

assets.register = function (type, Constructor) {
    var prototype = Constructor.prototype;
    prototype.type = type;
    assets[type] = Constructor;
    if (prototype.contentType && !(prototype.contentType in assets.typeByContentType)) {
        assets.typeByContentType[prototype.contentType] = type;
    }
    if (prototype.defaultExtension) {
        assets.typeByExtension[prototype.defaultExtension] = type;
    }
    if (prototype.alternativeExtensions) {
        prototype.alternativeExtensions.forEach(function (alternativeExtension) {
            assets.typeByExtension[alternativeExtension] = type;
        });
    }
};

assets.lookupContentType = function (contentType) {
    if (contentType) {
        // Trim whitespace and semicolon suffixes such as ;charset=...
        contentType = contentType.match(/^\s*([^;\s]*)(?:;|\s|$)/)[1].toLowerCase(); // Will always match
        if (contentType in assets.typeByContentType) {
            return assets.typeByContentType[contentType];
        } else if (/\+xml$/i.test(contentType)) {
            return 'Xml';
        } else if (/^text\//i.test(contentType)) {
            return 'Text';
        } else {
            return 'Base';
        }
    }
};

assets.addTypeToAssetConfig = function (assetConfig, cb) {
    var type =
        assetConfig.type ||
        (assetConfig.contentType && assets.lookupContentType(assetConfig.contentType)) ||
        assets.typeByExtension[Path.extname(assetConfig.url.replace(/[\?\#].*$/, ""))];
    if (type) {
        assetConfig.type = type;
        process.nextTick(function () {
            cb(null, assetConfig);
        });
    } else {
        // Looks like there's no way around loading the asset and looking at the src or HTTP headers
        return assetConfig.rawSrcProxy(function (err, src, metadata) {
            if (err) {
                if (err.errno === constants.EISDIR || err.errno === constants.EINVAL) {
                    assetConfig.url = assetConfig.url.replace(/(\/)?((?:[?#].*$)|$)/, '/index.html$2');
                    delete assetConfig.rawSrcProxy;
                    assetConfig.type = 'Html';
                    return cb(null, assetConfig);
                } else {
                    return cb(err);
                }
            }
            function foundType(type) {
                assetConfig.rawSrc = src;
                assetConfig.type = type;
                cb(null, assetConfig);
            }
            if (metadata && metadata.contentType) {
                // If the asset was served using HTTP, we shouldn't try to second guess by sniffing.
                foundType(assets.lookupContentType(metadata.contentType));
            } else if (src.length === 0) {
                foundType(); // Give up
            } else {
                // Work the magic
                var fileProcess = child_process.spawn('file', ['-b', '--mime-type', '-']),
                    fileOutput = '';
                fileProcess.stdout.on('data', function (chunk) {
                    fileOutput += chunk;
                }).on('end', function () {
                    foundType(assets.lookupContentType(fileOutput.match(/^([^\n]*)/)[1]));
                });
                fileProcess.stdin.write(src);
                fileProcess.stdin.end();
            }
        });
    }
};

assets.create = function (assetConfig) {
    if (!assetConfig.type) {
        throw new Error("assets.create: No type provided in assetConfig");
    }
    if (assetConfig.isAsset) {
        return assetConfig;
    } else {
        return new assets[assetConfig.type](assetConfig);
    }
};

require('fs').readdirSync(__dirname).forEach(function (fileName) {
    if (/\.js$/.test(fileName) && fileName !== 'index.js') {
        assets.register(fileName.replace(/\.js$/, ''), require('./' + fileName));
    }
});

_.extend(exports, assets);
<|endoftext|>


<commit_before>(function(){
    'use strict';

    var assets = {},
        internal = {},
        async = require('async'),
        q = require('q'),
        fs = require('fs'),
        config = require('../config').assets,
        _ = require('lodash');

    internal.config = config;
    internal.engines = [];
    internal.defaultEngine = null;

    _.each(config.engines, function(engine){
        engine.tmpdir = config.tmpdir;
    });

    if(config.engines.amazon) {
        internal.engines.amazon = require('./aws').config(config.engines.amazon);
    }
    if(config.engines.local){
        internal.engines.local = require('./local').config(config.engines.local);
    }

    internal.defaultEngine = internal.engines[config.default];

    assets.list = function(params){
        return internal.defaultEngine.list(params);
    };

    assets.find = function(params){
        return internal.defaultEngine.find(params);
    };

    assets.createDirectory = function(params){
        var deferred = q.defer();

        function createDirectory(engine, next){
            internal.engines[engine].createDirectory(params)
                .then(function(){
                    next(null);
                })
                .fail(function(err){
                    next(err);
                });
        }

        function done(err){
            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), createDirectory, done);

        return deferred.promise;
    };

    assets.removeDirectory = function(params){
        var deferred = q.defer();

        function removeDirectory(engine, next){
            internal.engines[engine].removeDirectory(params)
                .then(function(){
                    next(null);
                })
                .fail(function(err){
                    next(err);
                });
        }

        function done(err){
            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), removeDirectory, done);

        return deferred.promise;
    };

    assets.save = function(params){
        var deferred = q.defer();

        function save(engine, next){
            internal.engines[engine].save(params)
                .then(function(){
                    next(null);
                })
                .fail(function(err){
                    next(err);
                });
        }

        function done(err){
            fs.unlinkSync(params.path);

            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), save, done);

        return deferred.promise;
    };

    assets.rename = function(params){
        var deferred = q.defer();

        function rename(engine, next){
            internal.engines[engine].rename(params)
                .then(function(){
                    next(null);
                })
                .fail(function(err){
                    next(err);
                });
        }

        function done(err){
            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), rename, done);

        return deferred.promise;
    };

    assets.move = function(params){
        var deferred = q.defer();

        function move(engine, next){
            internal.engines[engine].move(params)
                .then(function(){
                    next(null);
                })
                .fail(function(err){
                    next(err);
                });
        }

        function done(err){
            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), move, done);

        return deferred.promise;
    };

    assets.copy = function(params){
        var deferred = q.defer();

        function copy(engine, next){
            internal.engines[engine].copy(params).then(function(){
                next();
            })
                .fail(function(err){
                    next(err);
                });
        }

        function done(err){
            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), copy, done);

        return deferred.promise;
    };

    assets.delete = function(params){
        var deferred = q.defer();

        function del(engine, next){
            internal.engines[engine].delete(params)
                .then(function(){
                    next(null);
                })
                .fail(function(err){
                    next(err);
                });
        }

        function done(err){
            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), del, done);

        return deferred.promise;
    };

    assets.deleteAll = function(params){
        var deferred = q.defer();

        function deleteAll(engine, next){
            internal.engines[engine].deleteAll(params)
                .then(function(){
                    next(null);
                })
                .fail(function(err){
                    next(err);
                });
        }

        function done(err){
            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), deleteAll, done);

        return deferred.promise;
    };

    module.exports = assets;
})();<commit_msg>Added a catch to avoid killing server.<commit_after>(function(){
    'use strict';

    var assets = {},
        internal = {},
        async = require('async'),
        q = require('q'),
        fs = require('fs'),
        config = require('../config').assets,
        _ = require('lodash');

    internal.config = config;
    internal.engines = [];
    internal.defaultEngine = null;

    _.each(config.engines, function(engine){
        engine.tmpdir = config.tmpdir;
    });

    if(config.engines.amazon) {
        internal.engines.amazon = require('./aws').config(config.engines.amazon);
    }
    if(config.engines.local){
        internal.engines.local = require('./local').config(config.engines.local);
    }

    internal.defaultEngine = internal.engines[config.default];

    assets.list = function(params){
        return internal.defaultEngine.list(params);
    };

    assets.find = function(params){
        return internal.defaultEngine.find(params);
    };

    assets.createDirectory = function(params){
        var deferred = q.defer();

        function createDirectory(engine, next){
            internal.engines[engine].createDirectory(params)
                .then(function(){
                    next(null);
                })
                .fail(function(err){
                    next(err);
                });
        }

        function done(err){
            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), createDirectory, done);

        return deferred.promise;
    };

    assets.removeDirectory = function(params){
        var deferred = q.defer();

        function removeDirectory(engine, next){
            internal.engines[engine].removeDirectory(params)
                .then(function(){
                    next(null);
                })
                .fail(function(err){
                    next(err);
                })
                .catch(function(err) {
                    next(err);
                })
                .done();
        }

        function done(err){
            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), removeDirectory, done);

        return deferred.promise;
    };

    assets.save = function(params){
        var deferred = q.defer();

        function save(engine, next){
            internal.engines[engine].save(params)
                .then(function(){
                    next(null);
                })
                .fail(function(err){
                    next(err);
                });
        }

        function done(err){
            fs.unlinkSync(params.path);

            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), save, done);

        return deferred.promise;
    };

    assets.rename = function(params){
        var deferred = q.defer();

        function rename(engine, next){
            internal.engines[engine].rename(params)
                .then(function(){
                    next(null);
                })
                .fail(function(err){
                    next(err);
                });
        }

        function done(err){
            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), rename, done);

        return deferred.promise;
    };

    assets.move = function(params){
        var deferred = q.defer();

        function move(engine, next){
            internal.engines[engine].move(params)
                .then(function(){
                    next(null);
                })
                .fail(function(err){
                    next(err);
                });
        }

        function done(err){
            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), move, done);

        return deferred.promise;
    };

    assets.copy = function(params){
        var deferred = q.defer();

        function copy(engine, next){
            internal.engines[engine].copy(params).then(function(){
                next();
            })
                .fail(function(err){
                    next(err);
                });
        }

        function done(err){
            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), copy, done);

        return deferred.promise;
    };

    assets.delete = function(params){
        var deferred = q.defer();

        function del(engine, next){
            internal.engines[engine].delete(params)
                .then(function(){
                    next(null);
                })
                .fail(function(err){
                    next(err);
                });
        }

        function done(err){
            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), del, done);

        return deferred.promise;
    };

    assets.deleteAll = function(params){
        var deferred = q.defer();

        function deleteAll(engine, next){
            internal.engines[engine].deleteAll(params)
                .then(function(){
                    next(null);
                })
                .fail(function(err){
                    next(err);
                });
        }

        function done(err){
            if(err){
                deferred.reject(err);
            }
            else {
                deferred.resolve({ message: 'Success' });
            }
        }

        async.each(_.keys(internal.engines), deleteAll, done);

        return deferred.promise;
    };

    module.exports = assets;
})();<|endoftext|>


<commit_before>var bcoin = require('../bcoin');
var hash = require('hash.js');
var bn = require('bn.js');
var inherits = require('inherits');
var EventEmitter = require('events').EventEmitter;
var utils = bcoin.utils;
var assert = utils.assert;
var constants = bcoin.protocol.constants;

function Wallet(options, passphrase) {
  if (!(this instanceof Wallet))
    return new Wallet(options, passphrase);

  EventEmitter.call(this);

  // bcoin.wallet('scope', 'password')
  if (typeof options === 'string' && typeof passphrase === 'string') {
    options = {
      scope: options,
      passphrase: passphrase
    };
  }
  if (!options)
    options = {};

  this.compressed = typeof options.compressed !== 'undefined' ?
      options.compressed : true;
  this.storage = options.storage;
  this.key = null;
  this.loaded = false;
  this.lastTs = 0;
  this.sharedKeys = options.sharedKeys;

  if (options.priv instanceof bcoin.hd.priv) {
    this.hd = options.priv;
    this.key = this.hd.pair;
  } else if (options.pub instanceof bcoin.hd.pub) {
    this.hd = options.pub;
    this.key = this.hd.pair;
  } else if (options.hd) {
    this.hd = bcoin.hd.priv(options);
    this.key = this.hd.pair;
  } else if (options.passphrase) {
    this.key = bcoin.ecdsa.genKeyPair({
      pers: options.scope,
      entropy: hash.sha256().update(options.passphrase).digest()
    });
  } else if (options.priv || options.pub) {
    this.key = bcoin.ecdsa.keyPair({
      priv: options.priv,
      pub: options.pub
    });
  } else {
    this.key = bcoin.ecdsa.genKeyPair();
  }

  this.addressType = options.addressType || 'normal';

  // Multisig
  this.sharedKeys = (options.sharedKeys || []).map(utils.toKeyArray);
  this.m = options.m || 1;
  this.n = options.n || 1;

  // Use p2sh multisig by default
  if (!options.addressType && this.sharedKeys.length) {
    this.addressType = 'p2sh';
  }

  if (this.m < 1 || this.m > this.n) {
    throw new Error('m ranges between 1 and n');
  }

  if (this.n < 1 || this.n > 7) {
    throw new Error('n ranges between 1 and 7');
  }

  if (this.sharedKeys.length !== this.m - 1) {
    throw new Error(this.m + ' public keys required');
  }

  this.prefix = 'bt/' + this.getAddress() + '/';
  this.tx = new bcoin.txPool(this);

  // Just a constants, actually
  this.fee = 10000;
  this.dust = 5460;

  this._init();
}
inherits(Wallet, EventEmitter);
module.exports = Wallet;

Wallet.prototype._init = function init() {
  if (this.tx._loaded) {
    this.loaded = true;
    return;
  }

  // Notify owners about new accepted transactions
  var self = this;
  var prevBalance = null;
  this.tx.on('update', function(lastTs, tx) {
    var b = this.balance();
    if (prevBalance && prevBalance.cmp(b) !== 0)
      self.emit('balance', b);
    self.emit('update', tx);
    prevBalance = b;
  });

  this.tx.on('tx', function(tx) {
    self.emit('tx', tx);
  });

  this.tx.once('load', function(ts) {
    self.loaded = true;
    self.lastTs = ts;
    self.emit('load', ts);
  });

  this.tx.on('error', function(err) {
    self.emit('error', err);
  });
};

Wallet.prototype.getPrivateKey = function getPrivateKey(enc) {
  var priv = this.key.getPrivate();
  if (priv)
    priv = priv.toArray();
  else
    return;
  if (!enc)
    return priv;

  if (enc === 'base58') {
    // We'll be using ncompressed public key as an address
    var arr = [ 128 ];

    // 0-pad key
    while (arr.length + priv.length < 33)
      arr.push(0);
    arr = arr.concat(priv);
    if (this.compressed)
      arr.push(1);
    var chk = utils.checksum(arr);
    return utils.toBase58(arr.concat(chk));
  } else {
    return priv;
  }
};

Wallet.prototype.getPublicKey = function getPublicKey(enc) {
  var pub;
  if (this.addressType === 'p2sh')
    pub = this.getRedemption();
  else
    pub = this.key.getPublic(this.compressed, 'array');

  if (enc === 'base58')
    return utils.toBase58(pub);
  else if (enc === 'hex')
    return utils.toHex(pub);
  else
    return pub;
};

Wallet.prototype.getHash = function getHash() {
  return utils.ripesha(this.getPublicKey());
};

Wallet.prototype.getAddress = function getAddress() {
  return Wallet.hash2addr(this.getHash(), this.addressType);
};

Wallet.hash2addr = function hash2addr(hash, version) {
  hash = utils.toArray(hash, 'hex');

  version = constants.addr[version || 'normal'];
  hash = [ version ].concat(hash);

  var addr = hash.concat(utils.checksum(hash));
  return utils.toBase58(addr);
};

Wallet.addr2hash = function addr2hash(addr, version) {
  if (!Array.isArray(addr))
    addr = utils.fromBase58(addr);

  version = constants.addr[version || 'normal'];

  if (addr.length !== 25)
    return [];
  if (addr[0] !== version)
    return [];

  var chk = utils.checksum(addr.slice(0, -4));
  if (utils.readU32(chk, 0) !== utils.readU32(addr, 21))
    return [];

  return addr.slice(1, -4);
};

Wallet.prototype.validateAddress = function validateAddress(addr, version) {
  var p = Wallet.addr2hash(addr, version);
  return p.length !== 0;
};
Wallet.validateAddress = Wallet.prototype.validateAddress;

Wallet.prototype.ownOutput = function ownOutput(tx, index) {
  var hash = this.getHash();
  var key = this.getPublicKey();

  var outputs = tx.outputs.filter(function(output, i) {
    if (index !== undefined && index !== i)
      return false;

    var s = output.script;

    if (bcoin.script.isPubkeyhash(s, hash))
      return true;

    if (bcoin.script.isSimplePubkeyhash(s, hash))
      return true;

    if (bcoin.script.isMultisig(s, key))
      return true;

    if (bcoin.script.isScripthash(s, hash))
      return true;

    return false;
  }, this);
  if (outputs.length === 0)
    return false;

  return outputs;
};

Wallet.prototype.ownInput = function ownInput(tx, index) {
  var hash = this.getHash();
  var key = this.getPublicKey();

  var inputs = tx.inputs.filter(function(input, i) {
    if (index !== undefined && index !== i)
      return false;

    if (bcoin.script.isPubkeyhashInput(input.script) &&
        utils.isEqual(input.script[1], key))
      return true;

    if (!input.out.tx)
      return false;

    var s = input.out.tx.outputs[input.out.index].script;
    if (bcoin.script.isPubkeyhash(s, hash))
      return true;

    if (bcoin.script.isMultisig(s, key))
      return true;

    if (bcoin.script.isScripthash(s, hash))
      return true;

    return false;
  }, this);
  if (inputs.length === 0)
    return false;

  return inputs;
};

Wallet.prototype.sign = function sign(tx, type, inputs, off) {
  if (!type)
    type = 'all';

  if (!off)
    off = 0;

  var pub = this.getPublicKey();
  inputs = inputs || tx.inputs;

  // Add signature script to each input
  inputs = inputs.filter(function(input, i) {
    // Filter inputs that this wallet own
    if (!input.out.tx || !this.ownOutput(input.out.tx))
      return false;

    // Get the previous output's subscript
    var s = input.out.tx.getSubscript(input.out.index);

    // Get the hash of the current tx, minus the other inputs, plus the sighash.
    // `off` is used here in a case where we have multiple wallet objects
    // signing the same tx.
    var hash = tx.subscriptHash(off + i, s, type);

    // Sign the transaction with our one input
    var signature = bcoin.ecdsa.sign(hash, this.key).toDER();

    // Add the sighash as a single byte to the signature
    signature = signature.concat(bcoin.protocol.constants.hashType[type]);

    // P2PKH and simple tx
    if (bcoin.script.isPubkeyhash(s) || bcoin.script.isSimplePubkeyhash(s)) {
      input.script = [ signature, pub ];
      return true;
    }

    // Multisig
    // empty array == OP_FALSE == OP_0
    // raw format: OP_FALSE [sig-1] [sig-2] ...
    // p2sh format: OP_FALSE [sig-1] [sig-2] ... [redeem-script]
    if (bcoin.script.isMultisig(s) || bcoin.script.isScripthash(s)) {
      if (!input.script || !input.script.length) {
        input.script = [ [], signature ];
      } else if (!~input.script.indexOf(signature)) {
        input.script.push(signature);
      }
    }

    // P2SH requires a redeem script after signatures
    if (bcoin.script.isScripthash(s)) {
      if (input.script.length - 1 === this.m) {
        input.script.push(this.getRedemption());
      }
    }

    return true;
  }, this);

  return inputs.length;
};

Wallet.prototype.sign = function sign(tx, type, inputs) {
  if (!type)
    type = 'all';

  var pub = this.getPublicKey();
  var key = this.key;
  var nsigs = this.m;

  inputs = inputs || tx.inputs;

  // Add signature script to each input
  inputs = inputs.filter(function(input) {
    // Filter inputs that this wallet own
    if (!input.out.tx || !this.ownOutput(input.out.tx))
      return false;

    tx.scriptSig(input, key, pub, nsigs);

    return true;
  }, this);

  return inputs.length;
};

Wallet.prototype.addTX = function addTX(tx, block) {
  return this.tx.add(tx);
};

Wallet.prototype.all = function all() {
  return this.tx.all();
};

Wallet.prototype.unspent = function unspent() {
  return this.tx.unspent();
};

Wallet.prototype.pending = function pending() {
  return this.tx.pending();
};

Wallet.prototype.balance = function balance() {
  return this.tx.balance();
};

Wallet.prototype.fill = function fill(tx, cb) {
  cb = utils.asyncify(cb);

  // NOTE: tx should be prefilled with all outputs
  var cost = tx.funds('out');

  // Use initial fee for starters
  var fee = 1;

  // total = cost + fee
  var total = cost.add(new bn(this.fee));

  var lastAdded = 0;
  function addInput(unspent, i) {
    // Add new inputs until TX will have enough funds to cover both
    // minimum post cost and fee
    tx.input(unspent);
    lastAdded++;
    return tx.funds('in').cmp(total) < 0;
  }

  // Transfer `total` funds maximum
  var unspent = this.unspent();
  unspent.every(addInput, this);

  // Add dummy output (for `left`) to calculate maximum TX size
  tx.out(options.change || this, new bn(0));

  // Change fee value if it is more than 1024 bytes
  // (10000 satoshi for every 1024 bytes)
  do {
    // Calculate maximum possible size after signing
    var byteSize = tx.maxSize();

    var addFee = Math.ceil(byteSize / 1024) - fee;
    total.iadd(new bn(addFee * this.fee));
    fee += addFee;

    // Failed to get enough funds, add more inputs
    if (tx.funds('in').cmp(total) < 0)
      unspent.slice(lastAdded).every(addInput, this);
  } while (tx.funds('in').cmp(total) < 0 && lastAdded < unspent.length);

  // Still failing to get enough funds, notify caller
  if (tx.funds('in').cmp(total) < 0) {
    var err = new Error('Not enough funds');
    err.minBalance = total;
    return cb(err);
  }

  // How much money is left after sending outputs
  var left = tx.funds('in').sub(total);

  // Not enough money, transfer everything to owner
  if (left.cmpn(this.dust) < 0) {
    // NOTE: that this output is either `postCost` or one of the `dust` values
    tx.outputs[tx.outputs.length - 2].value.iadd(left);
    left = new bn(0);
  }

  // Change or remove last output if there is some money left
  if (left.cmpn(0) === 0)
    tx.outputs.pop();
  else
    tx.outputs[tx.outputs.length - 1].value = left;

  // Sign transaction
  // XXX Do not necessarily call this here
  this.sign(tx);

  cb(null, tx);

  return tx;
};

// P2SH Multisig redeem script
Wallet.prototype.getRedemption = function() {
  var sharedKeys = this.sharedKeys.slice().map(utils.toKeyArray);
  if (sharedKeys.length < this.m) {
    var pub = this.key.getPublic(this.compressed, 'array');
    sharedKeys.push(pub);
  }
  return bcoin.script.redemption(sharedKeys, m, n);
};

Wallet.prototype.toJSON = function toJSON() {
  return {
    v: 1,
    type: 'wallet',
    pub: utils.toBase58(this.key.getPublic(this.compressed, 'array')),
    priv: this.getPrivateKey('base58'),
    tx: this.tx.toJSON(),
    addressType: this.addressType,
    sharedKeys: utils.toBase58(this.sharedKeys),
    m: this.m,
    n: this.n
  };
};

Wallet.fromJSON = function fromJSON(json) {
  assert.equal(json.v, 1);
  assert.equal(json.type, 'wallet');

  var priv;
  var pub;
  var compressed;

  if (json.priv) {
    var key = bcoin.utils.fromBase58(json.priv);
    assert(utils.isEqual(key.slice(-4), utils.checksum(key.slice(0, -4))));
    assert.equal(key[0], 128);

    key = key.slice(0, -4);
    if (key.length === 34) {
      assert.equal(key[33], 1);
      priv = key.slice(1, -1);
      compressed = true;
    } else {
      priv = key.slice(1);
      compressed = false;
    }
  } else {
    pub = bcoin.utils.fromBase58(json.pub);
    compressed = pub[0] !== 0x04;
  }

  var w = new Wallet({
    priv: priv,
    pub: pub,
    compressed: compressed,
    addressType: json.addressType,
    sharedKeys: json.sharedKeys,
    m: json.m,
    n: json.n
  });

  w.tx.fromJSON(json.tx);

  return w;
};
<commit_msg>minor fix for wallet.fill.<commit_after>var bcoin = require('../bcoin');
var hash = require('hash.js');
var bn = require('bn.js');
var inherits = require('inherits');
var EventEmitter = require('events').EventEmitter;
var utils = bcoin.utils;
var assert = utils.assert;
var constants = bcoin.protocol.constants;

function Wallet(options, passphrase) {
  if (!(this instanceof Wallet))
    return new Wallet(options, passphrase);

  EventEmitter.call(this);

  // bcoin.wallet('scope', 'password')
  if (typeof options === 'string' && typeof passphrase === 'string') {
    options = {
      scope: options,
      passphrase: passphrase
    };
  }
  if (!options)
    options = {};

  this.compressed = typeof options.compressed !== 'undefined' ?
      options.compressed : true;
  this.storage = options.storage;
  this.key = null;
  this.loaded = false;
  this.lastTs = 0;
  this.sharedKeys = options.sharedKeys;

  if (options.priv instanceof bcoin.hd.priv) {
    this.hd = options.priv;
    this.key = this.hd.pair;
  } else if (options.pub instanceof bcoin.hd.pub) {
    this.hd = options.pub;
    this.key = this.hd.pair;
  } else if (options.hd) {
    this.hd = bcoin.hd.priv(options);
    this.key = this.hd.pair;
  } else if (options.passphrase) {
    this.key = bcoin.ecdsa.genKeyPair({
      pers: options.scope,
      entropy: hash.sha256().update(options.passphrase).digest()
    });
  } else if (options.priv || options.pub) {
    this.key = bcoin.ecdsa.keyPair({
      priv: options.priv,
      pub: options.pub
    });
  } else {
    this.key = bcoin.ecdsa.genKeyPair();
  }

  this.addressType = options.addressType || 'normal';

  // Multisig
  this.sharedKeys = (options.sharedKeys || []).map(utils.toKeyArray);
  this.m = options.m || 1;
  this.n = options.n || 1;

  // Use p2sh multisig by default
  if (!options.addressType && this.sharedKeys.length) {
    this.addressType = 'p2sh';
  }

  if (this.m < 1 || this.m > this.n) {
    throw new Error('m ranges between 1 and n');
  }

  if (this.n < 1 || this.n > 7) {
    throw new Error('n ranges between 1 and 7');
  }

  if (this.sharedKeys.length !== this.m - 1) {
    throw new Error(this.m + ' public keys required');
  }

  this.prefix = 'bt/' + this.getAddress() + '/';
  this.tx = new bcoin.txPool(this);

  // Just a constants, actually
  this.fee = 10000;
  this.dust = 5460;

  this._init();
}
inherits(Wallet, EventEmitter);
module.exports = Wallet;

Wallet.prototype._init = function init() {
  if (this.tx._loaded) {
    this.loaded = true;
    return;
  }

  // Notify owners about new accepted transactions
  var self = this;
  var prevBalance = null;
  this.tx.on('update', function(lastTs, tx) {
    var b = this.balance();
    if (prevBalance && prevBalance.cmp(b) !== 0)
      self.emit('balance', b);
    self.emit('update', tx);
    prevBalance = b;
  });

  this.tx.on('tx', function(tx) {
    self.emit('tx', tx);
  });

  this.tx.once('load', function(ts) {
    self.loaded = true;
    self.lastTs = ts;
    self.emit('load', ts);
  });

  this.tx.on('error', function(err) {
    self.emit('error', err);
  });
};

Wallet.prototype.getPrivateKey = function getPrivateKey(enc) {
  var priv = this.key.getPrivate();
  if (priv)
    priv = priv.toArray();
  else
    return;
  if (!enc)
    return priv;

  if (enc === 'base58') {
    // We'll be using ncompressed public key as an address
    var arr = [ 128 ];

    // 0-pad key
    while (arr.length + priv.length < 33)
      arr.push(0);
    arr = arr.concat(priv);
    if (this.compressed)
      arr.push(1);
    var chk = utils.checksum(arr);
    return utils.toBase58(arr.concat(chk));
  } else {
    return priv;
  }
};

Wallet.prototype.getPublicKey = function getPublicKey(enc) {
  var pub;
  if (this.addressType === 'p2sh')
    pub = this.getRedemption();
  else
    pub = this.key.getPublic(this.compressed, 'array');

  if (enc === 'base58')
    return utils.toBase58(pub);
  else if (enc === 'hex')
    return utils.toHex(pub);
  else
    return pub;
};

Wallet.prototype.getHash = function getHash() {
  return utils.ripesha(this.getPublicKey());
};

Wallet.prototype.getAddress = function getAddress() {
  return Wallet.hash2addr(this.getHash(), this.addressType);
};

Wallet.hash2addr = function hash2addr(hash, version) {
  hash = utils.toArray(hash, 'hex');

  version = constants.addr[version || 'normal'];
  hash = [ version ].concat(hash);

  var addr = hash.concat(utils.checksum(hash));
  return utils.toBase58(addr);
};

Wallet.addr2hash = function addr2hash(addr, version) {
  if (!Array.isArray(addr))
    addr = utils.fromBase58(addr);

  version = constants.addr[version || 'normal'];

  if (addr.length !== 25)
    return [];
  if (addr[0] !== version)
    return [];

  var chk = utils.checksum(addr.slice(0, -4));
  if (utils.readU32(chk, 0) !== utils.readU32(addr, 21))
    return [];

  return addr.slice(1, -4);
};

Wallet.prototype.validateAddress = function validateAddress(addr, version) {
  var p = Wallet.addr2hash(addr, version);
  return p.length !== 0;
};
Wallet.validateAddress = Wallet.prototype.validateAddress;

Wallet.prototype.ownOutput = function ownOutput(tx, index) {
  var hash = this.getHash();
  var key = this.getPublicKey();

  var outputs = tx.outputs.filter(function(output, i) {
    if (index !== undefined && index !== i)
      return false;

    var s = output.script;

    if (bcoin.script.isPubkeyhash(s, hash))
      return true;

    if (bcoin.script.isSimplePubkeyhash(s, hash))
      return true;

    if (bcoin.script.isMultisig(s, key))
      return true;

    if (bcoin.script.isScripthash(s, hash))
      return true;

    return false;
  }, this);
  if (outputs.length === 0)
    return false;

  return outputs;
};

Wallet.prototype.ownInput = function ownInput(tx, index) {
  var hash = this.getHash();
  var key = this.getPublicKey();

  var inputs = tx.inputs.filter(function(input, i) {
    if (index !== undefined && index !== i)
      return false;

    if (bcoin.script.isPubkeyhashInput(input.script) &&
        utils.isEqual(input.script[1], key))
      return true;

    if (!input.out.tx)
      return false;

    var s = input.out.tx.outputs[input.out.index].script;
    if (bcoin.script.isPubkeyhash(s, hash))
      return true;

    if (bcoin.script.isMultisig(s, key))
      return true;

    if (bcoin.script.isScripthash(s, hash))
      return true;

    return false;
  }, this);
  if (inputs.length === 0)
    return false;

  return inputs;
};

Wallet.prototype.sign = function sign(tx, type, inputs, off) {
  if (!type)
    type = 'all';

  if (!off)
    off = 0;

  var pub = this.getPublicKey();
  inputs = inputs || tx.inputs;

  // Add signature script to each input
  inputs = inputs.filter(function(input, i) {
    // Filter inputs that this wallet own
    if (!input.out.tx || !this.ownOutput(input.out.tx))
      return false;

    // Get the previous output's subscript
    var s = input.out.tx.getSubscript(input.out.index);

    // Get the hash of the current tx, minus the other inputs, plus the sighash.
    // `off` is used here in a case where we have multiple wallet objects
    // signing the same tx.
    var hash = tx.subscriptHash(off + i, s, type);

    // Sign the transaction with our one input
    var signature = bcoin.ecdsa.sign(hash, this.key).toDER();

    // Add the sighash as a single byte to the signature
    signature = signature.concat(bcoin.protocol.constants.hashType[type]);

    // P2PKH and simple tx
    if (bcoin.script.isPubkeyhash(s) || bcoin.script.isSimplePubkeyhash(s)) {
      input.script = [ signature, pub ];
      return true;
    }

    // Multisig
    // empty array == OP_FALSE == OP_0
    // raw format: OP_FALSE [sig-1] [sig-2] ...
    // p2sh format: OP_FALSE [sig-1] [sig-2] ... [redeem-script]
    if (bcoin.script.isMultisig(s) || bcoin.script.isScripthash(s)) {
      if (!input.script || !input.script.length) {
        input.script = [ [], signature ];
      } else if (!~input.script.indexOf(signature)) {
        input.script.push(signature);
      }
    }

    // P2SH requires a redeem script after signatures
    if (bcoin.script.isScripthash(s)) {
      if (input.script.length - 1 === this.m) {
        input.script.push(this.getRedemption());
      }
    }

    return true;
  }, this);

  return inputs.length;
};

Wallet.prototype.sign = function sign(tx, type, inputs) {
  if (!type)
    type = 'all';

  var pub = this.getPublicKey();
  var key = this.key;
  var nsigs = this.m;

  inputs = inputs || tx.inputs;

  // Add signature script to each input
  inputs = inputs.filter(function(input) {
    // Filter inputs that this wallet own
    if (!input.out.tx || !this.ownOutput(input.out.tx))
      return false;

    tx.scriptSig(input, key, pub, nsigs);

    return true;
  }, this);

  return inputs.length;
};

Wallet.prototype.addTX = function addTX(tx, block) {
  return this.tx.add(tx);
};

Wallet.prototype.all = function all() {
  return this.tx.all();
};

Wallet.prototype.unspent = function unspent() {
  return this.tx.unspent();
};

Wallet.prototype.pending = function pending() {
  return this.tx.pending();
};

Wallet.prototype.balance = function balance() {
  return this.tx.balance();
};

Wallet.prototype.fill = function fill(tx, cb) {
  cb = utils.asyncify(cb);

  // NOTE: tx should be prefilled with all outputs
  var cost = tx.funds('out');

  // Use initial fee for starters
  var fee = 1;

  // total = cost + fee
  var total = cost.add(new bn(this.fee));

  var lastAdded = 0;
  function addInput(unspent, i) {
    // Add new inputs until TX will have enough funds to cover both
    // minimum post cost and fee
    tx.input(unspent);
    lastAdded++;
    return tx.funds('in').cmp(total) < 0;
  }

  // Transfer `total` funds maximum
  var unspent = this.unspent();
  unspent.every(addInput, this);

  // Add dummy output (for `left`) to calculate maximum TX size
  tx.out(this, new bn(0));

  // Change fee value if it is more than 1024 bytes
  // (10000 satoshi for every 1024 bytes)
  do {
    // Calculate maximum possible size after signing
    var byteSize = tx.maxSize();

    var addFee = Math.ceil(byteSize / 1024) - fee;
    total.iadd(new bn(addFee * this.fee));
    fee += addFee;

    // Failed to get enough funds, add more inputs
    if (tx.funds('in').cmp(total) < 0)
      unspent.slice(lastAdded).every(addInput, this);
  } while (tx.funds('in').cmp(total) < 0 && lastAdded < unspent.length);

  // Still failing to get enough funds, notify caller
  if (tx.funds('in').cmp(total) < 0) {
    var err = new Error('Not enough funds');
    err.minBalance = total;
    return cb(err);
  }

  // How much money is left after sending outputs
  var left = tx.funds('in').sub(total);

  // Not enough money, transfer everything to owner
  if (left.cmpn(this.dust) < 0) {
    // NOTE: that this output is either `postCost` or one of the `dust` values
    tx.outputs[tx.outputs.length - 2].value.iadd(left);
    left = new bn(0);
  }

  // Change or remove last output if there is some money left
  if (left.cmpn(0) === 0)
    tx.outputs.pop();
  else
    tx.outputs[tx.outputs.length - 1].value = left;

  // Sign transaction
  // XXX Do not necessarily call this here
  this.sign(tx);

  cb(null, tx);

  return tx;
};

// P2SH Multisig redeem script
Wallet.prototype.getRedemption = function() {
  var sharedKeys = this.sharedKeys.slice().map(utils.toKeyArray);
  if (sharedKeys.length < this.m) {
    var pub = this.key.getPublic(this.compressed, 'array');
    sharedKeys.push(pub);
  }
  return bcoin.script.redemption(sharedKeys, m, n);
};

Wallet.prototype.toJSON = function toJSON() {
  return {
    v: 1,
    type: 'wallet',
    pub: utils.toBase58(this.key.getPublic(this.compressed, 'array')),
    priv: this.getPrivateKey('base58'),
    tx: this.tx.toJSON(),
    addressType: this.addressType,
    sharedKeys: utils.toBase58(this.sharedKeys),
    m: this.m,
    n: this.n
  };
};

Wallet.fromJSON = function fromJSON(json) {
  assert.equal(json.v, 1);
  assert.equal(json.type, 'wallet');

  var priv;
  var pub;
  var compressed;

  if (json.priv) {
    var key = bcoin.utils.fromBase58(json.priv);
    assert(utils.isEqual(key.slice(-4), utils.checksum(key.slice(0, -4))));
    assert.equal(key[0], 128);

    key = key.slice(0, -4);
    if (key.length === 34) {
      assert.equal(key[33], 1);
      priv = key.slice(1, -1);
      compressed = true;
    } else {
      priv = key.slice(1);
      compressed = false;
    }
  } else {
    pub = bcoin.utils.fromBase58(json.pub);
    compressed = pub[0] !== 0x04;
  }

  var w = new Wallet({
    priv: priv,
    pub: pub,
    compressed: compressed,
    addressType: json.addressType,
    sharedKeys: json.sharedKeys,
    m: json.m,
    n: json.n
  });

  w.tx.fromJSON(json.tx);

  return w;
};
<|endoftext|>


<commit_before>'use babel';

import { CompositeDisposable } from 'atom';

export default {
  activate(state) {

    this.subscriptions = new CompositeDisposable();

    this.subscriptions.add(atom.workspace.observeTextEditors(editor => {
      this.subscriptions.add(
        editor.onDidInsertText((e) => {
          if (e.text === '{}') {
            let curRange = editor.getCursorBufferPosition();
            let range = [[curRange.row, curRange.column - 3], [curRange.row, curRange.column + 2]]
            if (editor.getTextInBufferRange(range) === '{{}}') {
              editor.setTextInBufferRange(range, '{{  }}');
              editor.getLastCursor().moveLeft(2);
            }
          }
        });
      );
    }));

  },

  deactivate() {
    this.subscriptions.dispose();
  }
};
<commit_msg>semi colon<commit_after>'use babel';

import { CompositeDisposable } from 'atom';

export default {
  activate(state) {

    this.subscriptions = new CompositeDisposable();

    this.subscriptions.add(atom.workspace.observeTextEditors(editor => {
      this.subscriptions.add(
        editor.onDidInsertText((e) => {
          if (e.text === '{}') {
            let curRange = editor.getCursorBufferPosition();
            let range = [[curRange.row, curRange.column - 3], [curRange.row, curRange.column + 2]]
            if (editor.getTextInBufferRange(range) === '{{}}') {
              editor.setTextInBufferRange(range, '{{  }}');
              editor.getLastCursor().moveLeft(2);
            }
          }
        })
      );
    }));

  },

  deactivate() {
    this.subscriptions.dispose();
  }
};
<|endoftext|>


<commit_before>var vm = require('vm'),
    _ = require('underscore'),
    uglifyJs = require('uglify-js-papandreou'),
    uglifyAst = require('uglifyast'),
    i18nTools = require('./i18nTools'),
    bootstrapper = module.exports = {};

// Maintained as a function so syntax highlighting works:
function bootstrapperCode() {
    window.INCLUDE = function () {};

    window.GETSTATICURL = function (url) { // , placeHolderValue1, placeHolderValue2, ...
        var placeHolderValues = Array.prototype.slice.call(arguments, 1);
        return url.replace(/\*\*?/g, function ($0) {
            return placeHolderValues.shift();
        });
    };

    var documentElement = document && document.documentElement,
        documentElementLang = documentElement && i18nTools.normalizeLocaleId(documentElement.getAttribute('lang'));

    function findActiveLocaleId() {
        var isSupportedByLocaleId = {};

        if (window.SUPPORTEDLOCALEIDS) {
            for (var i = 0 ; i < SUPPORTEDLOCALEIDS.length ; i += 1) {
                isSupportedByLocaleId[i18nTools.normalizeLocaleId(SUPPORTEDLOCALEIDS[i])] = true;
            }
        }
        function isSupportedLocaleId(localeId) {
            // Assume that all locales are supported if window.SUPPORTEDLOCALEIDS isn't defined
            return !window.SUPPORTEDLOCALEIDS || isSupportedByLocaleId[i18nTools.normalizeLocaleId(localeId)];
        }
        if (documentElementLang && isSupportedLocaleId(documentElementLang)) {
            return documentElementLang;
        }

        // Check the query string for a locale= parameter.
        if (window.location && location.href) {
            var matchLocationHref = location.href.match(/\?(?:|[^#]*&)locale=([\w\-_]+)(?:[&#]|$)/);
            if (matchLocationHref) {
                var queryStringLocaleId = i18nTools.normalizeLocaleId(matchLocationHref[1]);
                if (isSupportedLocaleId(queryStringLocaleId)) {
                    return queryStringLocaleId;
                }
            }
        }

        if (window.LOCALECOOKIENAME) {
            var matchLocaleCookieValue = document.cookie && document.cookie.match(new RegExp("\\b" + LOCALECOOKIENAME.replace(/[\.\+\*\{\}\[\]\(\)\?\^\$]/g, '\\$&') + "=([\\w\\-]+)"));
            if (matchLocaleCookieValue) {
                var cookieLocaleId = i18nTools.normalizeLocaleId(matchLocaleCookieValue[1]);
                if (isSupportedLocaleId(cookieLocaleId)) {
                    return cookieLocaleId;
                }
            }
        }

        if (window.navigator && navigator.language && isSupportedLocaleId(navigator.language)) {
            return i18nTools.normalizeLocaleId(navigator.language);
        }

        if (window.DEFAULTLOCALEID) {
            return DEFAULTLOCALEID;
        }

        if (window.SUPPORTEDLOCALEID && SUPPORTEDLOCALEID.length > 0) {
            return SUPPORTEDLOCALEID[0];
        }

        return 'en_us';
    }

    window.LOCALEID = findActiveLocaleId();

    // Set <html lang="..."> to the actual value so per-locale CSS can work, eg.: html[lang='en'] .myClass {...}
    if (!window.BUILDDEVELOPMENT && documentElement && documentElementLang !== LOCALEID) {
        documentElement.setAttribute('lang', LOCALEID);
    }

    // Helper for getting a prioritized, normalized list of relevant locale ids from a specific locale id.
    // For instance, "en_US" produces ["en_us", "en"]
    function expandLocaleIdToPrioritizedList(localeId) {
        if (!localeId) {
            return [];
        }
        localeId = i18nTools.normalizeLocaleId(localeId);
        var localeIds = [localeId];
        while (/_[^_]+$/.test(localeId)) {
            localeId = localeId.replace(/_[^_]+$/, '');
            localeIds.push(localeId);
        }
        return localeIds;
    }

    // Returns the canonical id of the best matching supported locale, or
    // false if no suitable supported locale could be found
    function resolveLocaleId(localeId) {
        localeId = i18nTools.normalizeLocaleId(localeId);
        for (var i = 0 ; i < SUPPORTEDLOCALEIDS.length ; i += 1) {
            var supportedLocaleId = SUPPORTEDLOCALEIDS[i];
            if (supportedLocaleId === localeId) {
                // Exact match
                return supportedLocaleId;
            }
        }
        // No exact match found, if the locale id contains variants, try looking for a more general variant:
        var prioritizedLocaleIds = expandLocaleIdToPrioritizedList(localeId);
        if (prioritizedLocaleIds.length > 1) {
            return resolveLocaleId(prioritizedLocaleIds[1]);
        }
        return false;
    }

    // Compute on the first use so the application has a chance to change LOCALEID before TR is used for the first time:
    var allKeysForLocale;
    function getAllKeysForLocale() {
        if (!allKeysForLocale) {
            allKeysForLocale = {};
            var prioritizedLocaleIds = expandLocaleIdToPrioritizedList(LOCALEID);
            for (var key in I18NKEYS) {
                if (I18NKEYS.hasOwnProperty(key)) {
                    for (var i = 0 ; i < prioritizedLocaleIds.length ; i += 1) {
                        if (prioritizedLocaleIds[i] in I18NKEYS[key]) {
                            allKeysForLocale[key] = I18NKEYS[key][prioritizedLocaleIds[i]];
                            break;
                        }
                    }
                }
            }
        }
        return allKeysForLocale;
    }

    window.LOCALIZE = true;

    window.TR = function (key, defaultValue) {
        return getAllKeysForLocale()[key] || defaultValue || '[!' + key + '!]';
    };

    window.TRPAT = function (key, defaultPattern) {
        var pattern = TR(key, defaultPattern),
            tokens = i18nTools.tokenizePattern(pattern);
        return function () { // placeHolderValue, ...
            var placeHolderValues = arguments,
                renderedString = '';
            for (var i = 0 ; i < tokens.length ; i += 1) {
                var token = tokens[i];
                if (token.type === 'placeHolder') {
                    renderedString += placeHolderValues[token.value];
                } else {
                    // token.type === 'text'
                    renderedString += token.value;
                }
            }
            return renderedString;
        };
    };

    window.TRHTML = function (htmlString) {
        var div = document.createElement('div');
        div.innerHTML = htmlString;
        i18nTools.eachI18nTagInHtmlDocument(div, i18nTools.createI18nTagReplacer({
            allKeysForLocale: getAllKeysForLocale(),
            localeId: LOCALEID
        }), function nestedTemplateHandler(node) {
            if (node.firstChild && node.firstChild.nodeType === node.TEXT_NODE) {
                // Use window.TRHTML instead of TRHTML to prevent the recursive call from being recognized as a relation:
                node.firstChild.nodeValue = window.TRHTML(node.firstChild.nodeValue);
            }
        });
        return div.innerHTML;
    };

    window.GETTEXT = function (url) {
        // Do a synchronous XHR in development mode:
        var xhr;
        try {
            xhr = new XMLHttpRequest();
        } catch (e) {
            try {
                xhr = new ActiveXObject('Microsoft.XmlHTTP');
            } catch (e) {}
        }
        if (!xhr) {
            throw new Error("GETTEXT: Couldn't initialize an XMLHttpRequest object.");
        }
        xhr.open('GET', url, false);
        xhr.send();
        if (xhr.status && xhr.status >= 200 && xhr.status < 400) {
            return xhr.responseText;
        } else {
            throw new Error("GETTEXT: Unexpected response from the server: " + (xhr && xhr.status));
        }
    };

    // Taken from jQuery 1.8.3:

    var isReady = false, // Is the DOM ready to be used? Set to true once it occurs.
        readyWait = 1, // A counter to track how many items to wait for before the ready event fires. See #6781
        readyList;

    // The ready event handler and self cleanup method
    function DOMContentLoaded() {
        if (document.addEventListener) {
            document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false);
            ready();
        } else if (document.readyState === "complete") {
            // we're here because readyState === "complete" in oldIE
            // which is good enough for us to call the dom ready!
            document.detachEvent("onreadystatechange", DOMContentLoaded);
            ready();
        }
    }

    // Handle when the DOM is ready
    function ready(wait) {
        // Abort if there are pending holds or we're already ready
        if (wait === true ? --readyWait : isReady) {
            return;
        }

        // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
        if (!document.body) {
            return setTimeout(ready, 1);
        }

        // Remember that the DOM is ready
        isReady = true;

        // If a normal DOM Ready event fired, decrement, and wait if need be
        if (wait !== true && --readyWait > 0) {
            return;
        }

        if (readyList) {
            for (var i = 0 ; i < readyList.length ; i += 1) {
                readyList[i]();
            }
            readyList = [];
        }
    }

    function onReady(fn) {
        if (!readyList) {
            readyList = [];

            // Catch cases where $(document).ready() is called after the browser event has already occurred.
            // we once tried to use readyState "interactive" here, but it caused issues like the one
            // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
            if (document.readyState === "complete") {
                // Handle it asynchronously to allow scripts the opportunity to delay ready
                setTimeout(ready, 1);

            // Standards-based browsers support DOMContentLoaded
            } else if (document.addEventListener) {
                // Use the handy event callback
                document.addEventListener("DOMContentLoaded", DOMContentLoaded, false);

                // A fallback to window.onload, that will always work
                window.addEventListener("load", ready, false);

            // If IE event model is used
            } else {
                // Ensure firing before onload, maybe late but safe also for iframes
                document.attachEvent("onreadystatechange", DOMContentLoaded);

                // A fallback to window.onload, that will always work
                window.attachEvent("onload", ready);

                // If IE and not a frame
                // continually check to see if the document is ready
                var top = false;

                try {
                    top = window.frameElement == null && document.documentElement;
                } catch(e) {}

                if (top && top.doScroll) {
                    (function doScrollCheck() {
                        if (!isReady) {
                            try {
                                // Use the trick by Diego Perini
                                // http://javascript.nwbox.com/IEContentLoaded/
                                top.doScroll("left");
                            } catch(e) {
                                return setTimeout(doScrollCheck, 50);
                            }

                            // and execute any waiting functions
                            ready();
                        }
                    })();
                }
            }
        }
        readyList.push(fn);
    }

    function translateDocument() {
        i18nTools.eachI18nTagInHtmlDocument(document, i18nTools.createI18nTagReplacer({allKeysForLocale: getAllKeysForLocale()}));
    }

    // Give scripts a chance to turn off translation altogether:
    if (document && document.childNodes && window.TRANSLATE !== false && !window.BUILDDEVELOPMENT) {
        if (!window.setTimeout || (!document.addEventListener && !document.attachEvent)) {
            // Assume we're running in an environment where the document is already loaded (jsdom?)
            translateDocument();
        } else {
            onReady(translateDocument);
        }
    }
}

bootstrapper.createAst = function (initialAsset, assetGraph, options) {
    options = options || {};
    if (initialAsset.type !== 'Html' && initialAsset.type !== 'JavaScript') {
        throw new Error('bootstrapper.createAst: initialAsset must be Html or JavaScript, but got ' + initialAsset);
    }
    var statementAsts = [],
        globalValueByName = {
            I18NKEYS: i18nTools.extractAllKeys(assetGraph)
        };

    // Add window.SUPPORTEDLOCALEIDS, window.DEFAULTLOCALEID, and window.LOCALECOOKIENAME if provided in the options object:
    ['supportedLocaleIds', 'defaultLocaleId', 'localeCookieName'].forEach(function (optionName) {
        if (options[optionName]) {
            globalValueByName[optionName.toUpperCase()] = options[optionName];
        }
    });

    Object.keys(globalValueByName).forEach(function (globalName) {
        statementAsts.push(['stat', ['assign', true, ['dot', ['name', 'window'], globalName],
                                     uglifyAst.objToAst(globalValueByName[globalName])]]);
    });

    statementAsts.push(['var', [['i18nTools', ['object', []]]]]);
    ['normalizeLocaleId', 'tokenizePattern', 'eachI18nTagInHtmlDocument', 'createI18nTagReplacer', 'createInfoObjectUpdater'].forEach(function (i18nToolsFunctionName) {
        statementAsts.push(['stat', ['assign', true, ['dot', ['name', 'i18nTools'], i18nToolsFunctionName],
                                     uglifyAst.objToAst(i18nTools[i18nToolsFunctionName])]]);
    });

    Array.prototype.push.apply(statementAsts, uglifyAst.getFunctionBodyAst(bootstrapperCode));

    // Wrap in immediately invoked function:
    return ['toplevel', [['stat', ['call', ['function', null, [], statementAsts]]]]];
};

bootstrapper.createContext = function (initialAsset, assetGraph, contextProperties) {
    var context = vm.createContext();
    context.window = context;
    context.assetGraph = assetGraph;
    context.console = console;
    if (contextProperties) {
        _.extend(context, contextProperties);
    }
    if (initialAsset.type === 'Html') {
        context.initialAsset = initialAsset;
        context.__defineSetter__('document', function () {});
        context.__defineGetter__('document', function () {
            initialAsset.markDirty();
            return initialAsset.parseTree;
        });
    }
    vm.runInContext(uglifyJs.uglify.gen_code(bootstrapper.createAst(initialAsset, assetGraph)),
                    context,
                    'bootstrap code for ' + (initialAsset.url || 'inline'));
    return context;
};
<commit_msg>Bootstrapper, findActiveLocaleId: Fixed fallback to SUPPORTEDLOCALEIDS[0] (was mistyped as SUPPORTEDLOCALEID).<commit_after>var vm = require('vm'),
    _ = require('underscore'),
    uglifyJs = require('uglify-js-papandreou'),
    uglifyAst = require('uglifyast'),
    i18nTools = require('./i18nTools'),
    bootstrapper = module.exports = {};

// Maintained as a function so syntax highlighting works:
function bootstrapperCode() {
    window.INCLUDE = function () {};

    window.GETSTATICURL = function (url) { // , placeHolderValue1, placeHolderValue2, ...
        var placeHolderValues = Array.prototype.slice.call(arguments, 1);
        return url.replace(/\*\*?/g, function ($0) {
            return placeHolderValues.shift();
        });
    };

    var documentElement = document && document.documentElement,
        documentElementLang = documentElement && i18nTools.normalizeLocaleId(documentElement.getAttribute('lang'));

    function findActiveLocaleId() {
        var isSupportedByLocaleId = {};

        if (window.SUPPORTEDLOCALEIDS) {
            for (var i = 0 ; i < SUPPORTEDLOCALEIDS.length ; i += 1) {
                isSupportedByLocaleId[i18nTools.normalizeLocaleId(SUPPORTEDLOCALEIDS[i])] = true;
            }
        }
        function isSupportedLocaleId(localeId) {
            // Assume that all locales are supported if window.SUPPORTEDLOCALEIDS isn't defined
            return !window.SUPPORTEDLOCALEIDS || isSupportedByLocaleId[i18nTools.normalizeLocaleId(localeId)];
        }
        if (documentElementLang && isSupportedLocaleId(documentElementLang)) {
            return documentElementLang;
        }

        // Check the query string for a locale= parameter.
        if (window.location && location.href) {
            var matchLocationHref = location.href.match(/\?(?:|[^#]*&)locale=([\w\-_]+)(?:[&#]|$)/);
            if (matchLocationHref) {
                var queryStringLocaleId = i18nTools.normalizeLocaleId(matchLocationHref[1]);
                if (isSupportedLocaleId(queryStringLocaleId)) {
                    return queryStringLocaleId;
                }
            }
        }

        if (window.LOCALECOOKIENAME) {
            var matchLocaleCookieValue = document.cookie && document.cookie.match(new RegExp("\\b" + LOCALECOOKIENAME.replace(/[\.\+\*\{\}\[\]\(\)\?\^\$]/g, '\\$&') + "=([\\w\\-]+)"));
            if (matchLocaleCookieValue) {
                var cookieLocaleId = i18nTools.normalizeLocaleId(matchLocaleCookieValue[1]);
                if (isSupportedLocaleId(cookieLocaleId)) {
                    return cookieLocaleId;
                }
            }
        }

        if (window.navigator && navigator.language && isSupportedLocaleId(navigator.language)) {
            return i18nTools.normalizeLocaleId(navigator.language);
        }

        if (window.DEFAULTLOCALEID) {
            return DEFAULTLOCALEID;
        }

        if (window.SUPPORTEDLOCALEIDS && SUPPORTEDLOCALEIDS.length > 0) {
            return SUPPORTEDLOCALEIDS[0];
        }

        return 'en_us';
    }

    window.LOCALEID = findActiveLocaleId();

    // Set <html lang="..."> to the actual value so per-locale CSS can work, eg.: html[lang='en'] .myClass {...}
    if (!window.BUILDDEVELOPMENT && documentElement && documentElementLang !== LOCALEID) {
        documentElement.setAttribute('lang', LOCALEID);
    }

    // Helper for getting a prioritized, normalized list of relevant locale ids from a specific locale id.
    // For instance, "en_US" produces ["en_us", "en"]
    function expandLocaleIdToPrioritizedList(localeId) {
        if (!localeId) {
            return [];
        }
        localeId = i18nTools.normalizeLocaleId(localeId);
        var localeIds = [localeId];
        while (/_[^_]+$/.test(localeId)) {
            localeId = localeId.replace(/_[^_]+$/, '');
            localeIds.push(localeId);
        }
        return localeIds;
    }

    // Returns the canonical id of the best matching supported locale, or
    // false if no suitable supported locale could be found
    function resolveLocaleId(localeId) {
        localeId = i18nTools.normalizeLocaleId(localeId);
        for (var i = 0 ; i < SUPPORTEDLOCALEIDS.length ; i += 1) {
            var supportedLocaleId = SUPPORTEDLOCALEIDS[i];
            if (supportedLocaleId === localeId) {
                // Exact match
                return supportedLocaleId;
            }
        }
        // No exact match found, if the locale id contains variants, try looking for a more general variant:
        var prioritizedLocaleIds = expandLocaleIdToPrioritizedList(localeId);
        if (prioritizedLocaleIds.length > 1) {
            return resolveLocaleId(prioritizedLocaleIds[1]);
        }
        return false;
    }

    // Compute on the first use so the application has a chance to change LOCALEID before TR is used for the first time:
    var allKeysForLocale;
    function getAllKeysForLocale() {
        if (!allKeysForLocale) {
            allKeysForLocale = {};
            var prioritizedLocaleIds = expandLocaleIdToPrioritizedList(LOCALEID);
            for (var key in I18NKEYS) {
                if (I18NKEYS.hasOwnProperty(key)) {
                    for (var i = 0 ; i < prioritizedLocaleIds.length ; i += 1) {
                        if (prioritizedLocaleIds[i] in I18NKEYS[key]) {
                            allKeysForLocale[key] = I18NKEYS[key][prioritizedLocaleIds[i]];
                            break;
                        }
                    }
                }
            }
        }
        return allKeysForLocale;
    }

    window.LOCALIZE = true;

    window.TR = function (key, defaultValue) {
        return getAllKeysForLocale()[key] || defaultValue || '[!' + key + '!]';
    };

    window.TRPAT = function (key, defaultPattern) {
        var pattern = TR(key, defaultPattern),
            tokens = i18nTools.tokenizePattern(pattern);
        return function () { // placeHolderValue, ...
            var placeHolderValues = arguments,
                renderedString = '';
            for (var i = 0 ; i < tokens.length ; i += 1) {
                var token = tokens[i];
                if (token.type === 'placeHolder') {
                    renderedString += placeHolderValues[token.value];
                } else {
                    // token.type === 'text'
                    renderedString += token.value;
                }
            }
            return renderedString;
        };
    };

    window.TRHTML = function (htmlString) {
        var div = document.createElement('div');
        div.innerHTML = htmlString;
        i18nTools.eachI18nTagInHtmlDocument(div, i18nTools.createI18nTagReplacer({
            allKeysForLocale: getAllKeysForLocale(),
            localeId: LOCALEID
        }), function nestedTemplateHandler(node) {
            if (node.firstChild && node.firstChild.nodeType === node.TEXT_NODE) {
                // Use window.TRHTML instead of TRHTML to prevent the recursive call from being recognized as a relation:
                node.firstChild.nodeValue = window.TRHTML(node.firstChild.nodeValue);
            }
        });
        return div.innerHTML;
    };

    window.GETTEXT = function (url) {
        // Do a synchronous XHR in development mode:
        var xhr;
        try {
            xhr = new XMLHttpRequest();
        } catch (e) {
            try {
                xhr = new ActiveXObject('Microsoft.XmlHTTP');
            } catch (e) {}
        }
        if (!xhr) {
            throw new Error("GETTEXT: Couldn't initialize an XMLHttpRequest object.");
        }
        xhr.open('GET', url, false);
        xhr.send();
        if (xhr.status && xhr.status >= 200 && xhr.status < 400) {
            return xhr.responseText;
        } else {
            throw new Error("GETTEXT: Unexpected response from the server: " + (xhr && xhr.status));
        }
    };

    // Taken from jQuery 1.8.3:

    var isReady = false, // Is the DOM ready to be used? Set to true once it occurs.
        readyWait = 1, // A counter to track how many items to wait for before the ready event fires. See #6781
        readyList;

    // The ready event handler and self cleanup method
    function DOMContentLoaded() {
        if (document.addEventListener) {
            document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false);
            ready();
        } else if (document.readyState === "complete") {
            // we're here because readyState === "complete" in oldIE
            // which is good enough for us to call the dom ready!
            document.detachEvent("onreadystatechange", DOMContentLoaded);
            ready();
        }
    }

    // Handle when the DOM is ready
    function ready(wait) {
        // Abort if there are pending holds or we're already ready
        if (wait === true ? --readyWait : isReady) {
            return;
        }

        // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
        if (!document.body) {
            return setTimeout(ready, 1);
        }

        // Remember that the DOM is ready
        isReady = true;

        // If a normal DOM Ready event fired, decrement, and wait if need be
        if (wait !== true && --readyWait > 0) {
            return;
        }

        if (readyList) {
            for (var i = 0 ; i < readyList.length ; i += 1) {
                readyList[i]();
            }
            readyList = [];
        }
    }

    function onReady(fn) {
        if (!readyList) {
            readyList = [];

            // Catch cases where $(document).ready() is called after the browser event has already occurred.
            // we once tried to use readyState "interactive" here, but it caused issues like the one
            // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
            if (document.readyState === "complete") {
                // Handle it asynchronously to allow scripts the opportunity to delay ready
                setTimeout(ready, 1);

            // Standards-based browsers support DOMContentLoaded
            } else if (document.addEventListener) {
                // Use the handy event callback
                document.addEventListener("DOMContentLoaded", DOMContentLoaded, false);

                // A fallback to window.onload, that will always work
                window.addEventListener("load", ready, false);

            // If IE event model is used
            } else {
                // Ensure firing before onload, maybe late but safe also for iframes
                document.attachEvent("onreadystatechange", DOMContentLoaded);

                // A fallback to window.onload, that will always work
                window.attachEvent("onload", ready);

                // If IE and not a frame
                // continually check to see if the document is ready
                var top = false;

                try {
                    top = window.frameElement == null && document.documentElement;
                } catch(e) {}

                if (top && top.doScroll) {
                    (function doScrollCheck() {
                        if (!isReady) {
                            try {
                                // Use the trick by Diego Perini
                                // http://javascript.nwbox.com/IEContentLoaded/
                                top.doScroll("left");
                            } catch(e) {
                                return setTimeout(doScrollCheck, 50);
                            }

                            // and execute any waiting functions
                            ready();
                        }
                    })();
                }
            }
        }
        readyList.push(fn);
    }

    function translateDocument() {
        i18nTools.eachI18nTagInHtmlDocument(document, i18nTools.createI18nTagReplacer({allKeysForLocale: getAllKeysForLocale()}));
    }

    // Give scripts a chance to turn off translation altogether:
    if (document && document.childNodes && window.TRANSLATE !== false && !window.BUILDDEVELOPMENT) {
        if (!window.setTimeout || (!document.addEventListener && !document.attachEvent)) {
            // Assume we're running in an environment where the document is already loaded (jsdom?)
            translateDocument();
        } else {
            onReady(translateDocument);
        }
    }
}

bootstrapper.createAst = function (initialAsset, assetGraph, options) {
    options = options || {};
    if (initialAsset.type !== 'Html' && initialAsset.type !== 'JavaScript') {
        throw new Error('bootstrapper.createAst: initialAsset must be Html or JavaScript, but got ' + initialAsset);
    }
    var statementAsts = [],
        globalValueByName = {
            I18NKEYS: i18nTools.extractAllKeys(assetGraph)
        };

    // Add window.SUPPORTEDLOCALEIDS, window.DEFAULTLOCALEID, and window.LOCALECOOKIENAME if provided in the options object:
    ['supportedLocaleIds', 'defaultLocaleId', 'localeCookieName'].forEach(function (optionName) {
        if (options[optionName]) {
            globalValueByName[optionName.toUpperCase()] = options[optionName];
        }
    });

    Object.keys(globalValueByName).forEach(function (globalName) {
        statementAsts.push(['stat', ['assign', true, ['dot', ['name', 'window'], globalName],
                                     uglifyAst.objToAst(globalValueByName[globalName])]]);
    });

    statementAsts.push(['var', [['i18nTools', ['object', []]]]]);
    ['normalizeLocaleId', 'tokenizePattern', 'eachI18nTagInHtmlDocument', 'createI18nTagReplacer', 'createInfoObjectUpdater'].forEach(function (i18nToolsFunctionName) {
        statementAsts.push(['stat', ['assign', true, ['dot', ['name', 'i18nTools'], i18nToolsFunctionName],
                                     uglifyAst.objToAst(i18nTools[i18nToolsFunctionName])]]);
    });

    Array.prototype.push.apply(statementAsts, uglifyAst.getFunctionBodyAst(bootstrapperCode));

    // Wrap in immediately invoked function:
    return ['toplevel', [['stat', ['call', ['function', null, [], statementAsts]]]]];
};

bootstrapper.createContext = function (initialAsset, assetGraph, contextProperties) {
    var context = vm.createContext();
    context.window = context;
    context.assetGraph = assetGraph;
    context.console = console;
    if (contextProperties) {
        _.extend(context, contextProperties);
    }
    if (initialAsset.type === 'Html') {
        context.initialAsset = initialAsset;
        context.__defineSetter__('document', function () {});
        context.__defineGetter__('document', function () {
            initialAsset.markDirty();
            return initialAsset.parseTree;
        });
    }
    vm.runInContext(uglifyJs.uglify.gen_code(bootstrapper.createAst(initialAsset, assetGraph)),
                    context,
                    'bootstrap code for ' + (initialAsset.url || 'inline'));
    return context;
};
<|endoftext|>


<commit_before>import Bluebird from 'bluebird'
import colors from 'colors'
import promptly from 'promptly'

Bluebird.promisifyAll(promptly)

/**
 * List the last executed migration
 * @param  {Object} migrator - migrator instance
 * @return {Promsie} promise
 */
export function current (migrator) {
  return migrator.getLastExecuted()
  .then(last => {
    if (last === undefined) {
      console.log('')
      console.log(colors.grey('It doesn\'t look like any migrations have been executed.'))
      console.log('')
    } else {
      console.log('')
      console.log(colors.grey(`The last executed migration was: ${last}`))
      console.log('')
    }
  })
}

/**
 * Run down migrations
 * @param  {Object} [options={}] - options
 * @return {Function} command
 */
export function down (options = {}) {
  return function _down (migrator) {
    return migrator.getLastExecuted()
    .then(last => {
      console.log('')
      console.log(colors.grey(`The last executed migration was ${last}`))
      const endpoint = options.to ? options.to : 'the beginning'
      const prompt = `Are you sure you want to rollback to ${endpoint}:`
      return promptly.confirm(prompt, { retry: true })
    })
    .then(confirmed => {
      if (confirmed === false) {
        return
      }
      return migrator.down(options)
    })
    .then(executed => {
      console.log('')
      return executed
    })
  }
}

/**
 * List all pending migrations
 * @param  {Object} migrator - migrator instance
 * @return {Promise} promise
 */
export function pending (migrator) {
  return migrator.getPending()
  .then(pending => {
    console.log('')
    if (pending.length === 0) {
      console.log(colors.grey('No pending migrations found, current environment is up to date.'))
    } else {
      console.log(colors.grey(`${pending.length} pending migrations found:`))
    }
    return pending
  })
  .each(version => {
    console.log(colors.grey(`- ${version}`))
  })
  .then(versions => {
    console.log('')
    return versions
  })
}

/**
 * Run pending migrations
 * @param  {Object} options - up options
 * @return {Function} command
 */
export function up (options = {}) {
  return function _up (migrator) {
    return pending(migrator)
    .then(() => {
      const prompt = 'Are you sure you want to migrate?'
      return promptly.confirm(prompt, { retry: true })
    })
    .then(confirmed => {
      if (confirmed === false) {
        return
      }
      return migrator.up(options)
    })
  }
}
<commit_msg>prevents prompting for #up and #down if there are no pending/downward migrations<commit_after>import Bluebird from 'bluebird'
import colors from 'colors'
import promptly from 'promptly'

Bluebird.promisifyAll(promptly)

/**
 * List the last executed migration
 * @param  {Object} migrator - migrator instance
 * @return {Promsie} promise
 */
export function current (migrator) {
  return migrator.getLastExecuted()
  .then(last => {
    if (last === undefined) {
      console.log('')
      console.log(colors.grey('It doesn\'t look like any migrations have been executed.'))
      console.log('')
    } else {
      console.log('')
      console.log(colors.grey(`The last executed migration was: ${last}`))
      console.log('')
    }
  })
}

/**
 * Run down migrations
 * @param  {Object} [options={}] - options
 * @return {Function} command
 */
export function down (options = {}) {
  return function _down (migrator) {
    return migrator.getLastExecuted()
    .then(last => {
      if (last === undefined) {
        return false
      }
      console.log('')
      console.log(colors.grey(`The last executed migration was ${last}`))
      const endpoint = options.to ? options.to : 'the beginning'
      const prompt = `Are you sure you want to rollback to ${endpoint}:`
      return promptly.confirm(prompt, { retry: true })
    })
    .then(confirmed => {
      if (confirmed === false) {
        return
      }
      return migrator.down(options)
    })
    .then(executed => {
      console.log('')
      return executed
    })
  }
}

/**
 * List all pending migrations
 * @param  {Object} migrator - migrator instance
 * @return {Promise} promise
 */
export function pending (migrator) {
  return migrator.getPending()
  .then(pending => {
    console.log('')
    if (pending.length === 0) {
      console.log(colors.grey('No pending migrations found, current environment is up to date.'))
    } else {
      console.log(colors.grey(`${pending.length} pending migrations found:`))
    }
    return pending
  })
  .each(version => {
    console.log(colors.grey(`- ${version}`))
  })
  .then(versions => {
    console.log('')
    return versions
  })
}

/**
 * Run pending migrations
 * @param  {Object} options - up options
 * @return {Function} command
 */
export function up (options = {}) {
  return function _up (migrator) {
    return pending(migrator)
    .then(pending => {
      if (!pending || !pending.length) {
        return false
      }
      const prompt = 'Are you sure you want to migrate?'
      return promptly.confirm(prompt, { retry: true })
    })
    .then(confirmed => {
      if (confirmed === false) {
        return
      }
      return migrator.up(options)
    })
  }
}
<|endoftext|>