<commit_before>var sys = require('sys');
var logger = require('./logger');
var Binary = require('binary');
var Util = require('./util');
var BlockLocator = require('./blocklocator').BlockLocator;

var genesis_block = {
	'height': 0,
	'nonce': 2083236893,
	'version': 1,
	'hash': new Buffer('6FE28C0AB6F1B372C1A6A246AE63F74F931E8365E15A089C68D6190000000000', 'hex'),
	'prev_hash': new Buffer(32).clear(),
	'timestamp': 1231006505,
	'merkle_root': new Buffer('3BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A', 'hex'),
	'bits': 486604799
};

var genesis_block_tx = {
	'outs': [{
		'value': new Buffer('00F2052A01000000', 'hex'), // 50 BTC
		'script': Binary.put()
			.word8(65) // ???
			.put(new Buffer('04678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5F', 'hex'))
			.word8(0xAC)
			.buffer() // OP_CHECKSIG
	}],
	'lock_time': 0,
	'version': 1,
	'hash': new Buffer('3BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A', 'hex'),
	'ins': [{
		'sequence': 0xFFFFFFFF,
		'outpoint': {
			'index': 0xFFFFFFFF,
			'hash': new Buffer(32).clear()
		},
		'script': Binary.put()
			.put(new Buffer('04FFFF001D010445', 'hex'))
			.put(new Buffer('The Times 03/Jan/2009 Chancellor on brink of second bailout for banks', 'ascii'))
			.buffer()
	}]
};

var BlockChain = exports.BlockChain = function (storage) {
	events.EventEmitter.call(this);

	this.storage = storage;

	var self = this;

	var Block = this.storage.Block;
	var Transaction = this.storage.Transaction;
	var Account = this.storage.Account;

	var genesisBlock = null;
	var currentTopBlock = null;
	var lastRecvBlock = null;
	var orphanBlockFutures = {};
	var queueCount = 0;

	function createGenesisBlock(callback) {
		logger.info("Loading genesis block");

		try {
			genesisBlock = currentTopBlock = new Block(genesis_block);
			genesisBlock.active = true;
			genesisBlock.setChainWork(genesisBlock.getWork());

			// A simple sanity check to make sure our constants are not
			// corrupted and our block hashing algorithm is working.
			if (!genesisBlock.checkHash()) {
				logger.error("Genesis block hash validation failed. There is something wrong with our constants or block hash validation code.");
				return;
			}

			var genesisTransaction = new Transaction(genesis_block_tx);

			self.emit('blockAdd', {block: genesisBlock, txs: [genesisTransaction]});
		} catch (e) {
			logger.error("Error while adding genesis block: "+(e.stack ? e.stack : e));
			return;
		}

		genesisBlock.save(function (err) {
			// It's faster to just ignore the duplicate key error than to
			// check beforehand
			if (err && err.message.indexOf("E11000") == -1) {
				logger.error(err);
				callback(err);
				return;
			}

			if (!genesisTransaction.checkHash()) {
				logger.error("Genesis tx hash validation failed. There is something wrong with our constants or tx hash validation code.");
				return;
			}

			genesisTransaction.block = genesisBlock.getHash();
			genesisTransaction.active = true;

			self.emit('txAdd', {block: genesisBlock, index: 0, tx: genesisTransaction, chain: self});

			genesisTransaction.save(function (err) {
				// It's faster to just ignore the duplicate key error than to
				// check beforehand
				if (err && err.message.indexOf("E11000") == -1) {
					logger.error(err);
					callback(err);
					return;
				}

				self.emit('txAdd', {block: genesisBlock, index: 0, tx: genesisTransaction, chain: self});
			});

			self.emit('blockSave', {block: genesisBlock, txs: [genesisTransaction]});
			callback();
		});
	}

	function loadTopBlock(callback) {
		Block.find().sort('height', -1).limit(1).exec(function (err, block) {
			if (err) {
				logger.error("Error while initializing block chain", err);
				return;
			}
			currentTopBlock = block[0];
			callback();
		});
	}

	this.getBlockByHash = function getBlockByHash(hash, callback) {
		Block.findOne({hash: hash}, function (err, block) {
			if (err) {
				callback(err);
				return;
			}

			callback(err, block);
		});
	};

	this.getBlockByPrev = function getBlockByPrev(block, callback) {
		if ("object" == typeof block && block.hash) {
			block = block.hash;
		}

		Block.findOne({prev_hash: block}, function (err, block) {
			if (err) {
				callback(err);
				return;
			}

			callback(err, block);
		});
	};

	this.getGenesisBlock = function getGenesisBlock() {
		return genesisBlock;
	};

	this.getTopBlock = function getTopBlock() {
		return currentTopBlock;
	};

	this.getBlockLocator = function getBlockLocator(callback) {
		BlockLocator.createFromBlockChain(this, callback);
	};

	/**
	 * Get the last block we received.
	 *
	 * Very untrusted! This is only meant for continuously requesting
	 * blocks during a block chain download. Otherwise always use
	 * getTopBlock().
	 */
	this.getLastRecvBlock = function getLastRecvBlock () {
		return lastRecvBlock;
	};

	this.getQueueCount = function () {
		return queueCount;
	};

	this.add = function add(block, txs, callback) {
		var self = this;

		if (!block instanceof Block) {
			block = this.makeBlockObject(block);
		}

		function connectBlockToParentAndSave(parent) {
			// Our parent block is there, let's attach ourselves
			block.height = parent.height + 1;
			block.setChainWork(parent.getChainWork().add(block.getWork()));

			// Update top block field if this block is a child of it
			if (currentTopBlock.hash.compare(parent.hash) === 0) {
				currentTopBlock = block;
				block.active = true;
			} else {
				// Block belongs to a side chain, switch chains if side
				// chain has more work.
				block.active = false;
				if (block.moreWorkThan(currentTopBlock)) {
					self.reorganize(currentTopBlock, block);
					currentTopBlock = block;
				} else {
					logger.info('Adding block '+Util.formatHash(block.hash)+
								' on side chain');
				}
			}

			self.emit('blockAdd', {block: block, txs: txs, chain: self});

			block.save(function (err) {
				queueCount--;

				if (err) {
					// TODO: Handle if block is a duplicate
					return callback(err);
				}

				// Asynchronously store all of this block's transactions to the database
				self.addTransactions(block, txs);

				// This event will also trigger us saving all child blocks that
				// are currently waiting.
				self.emit('blockSave', {block: block, txs: txs, chain: self});

				callback(err, block);
			});
		}

		// Static checks
		try {
			block.checkBlock();
		} catch (e) {
			callback('Check failed: '+e, null);
		}

		lastRecvBlock = block;

		queueCount++;

		this.getBlockByHash(block.prev_hash, function (err, prevBlock) {
			// Let's see if we are able to connect into the chain
			if (!err && prevBlock && prevBlock.height >= 0) {
				// Our parent is in the chain, connect up and save
				connectBlockToParentAndSave(prevBlock);
			} else {
				// Our parent is not in the chain, create a future to be
				// executed when it is.
				var future = connectBlockToParentAndSave;
				if (!orphanBlockFutures[block.prev_hash]) {
					orphanBlockFutures[block.prev_hash] = {};
				}
				orphanBlockFutures[block.prev_hash][block.hash] = future;
			}
		});
	};

	this.addTransactions = function addTransactions(block, txs) {
		txs.forEach(function (tx, i) {
			tx = new Transaction(tx);

			tx.block = block.getHash();
			tx.active = block.active;

			// Calculate hash
			tx.getHash();

			self.emit('txAdd', {block: block, index: i, tx: tx, chain: self});

			tx.save(function (err) {
				if (err) {
					logger.warn(err);
					return;
				}

				self.emit('txSave', {block: block, index: i, tx: tx, chain: self});
			});
		});
	};

	this.reorganize = function reorganize(oldTopBlock, newTopBlock) {
		logger.info('Reorganize (old head: '+Util.formatHash(oldTopBlock.hash)+
					', new head: '+Util.formatHash(newTopBlock.hash)+')');

		var toDisconnect = [];
		var toConnect = [];

		// Follow the chains down to the fork
		function findFork(bOld, bNew, callback) {
			if (bOld.hash.compare(bNew.hash) === 0) {
				callback(null, bOld);
			}

			if (bOld.height > bNew.height) {
				toDisconnect.push(bOld);
				self.getBlockByPrev(bOld, function (err, bOld) {
					if (err) {
						callback(err);
						return;
					}
					findFork(bOld, bNew, callback);
				});
			} else {
				if (bNew.height <= 0) {
					callback(new Error("No common root found"));
				}
				toConnect.push(bNew);
				self.getBlockByPrev(bNew, function (err, bNew) {
					if (err) {
						callback(err);
						return;
					}
					findFork(bOld, bNew, callback);
				});
			}
		}

		findFork(oldTopBlock, newTopBlock, function (err) {
			if (err) {
				logger.error('Unable to reorganize: '+err);
				return;
			}

			// Disconnect old fork
			toDisconnect.forEach(function (block) {
				block.active = false;

				Transaction.find({block: block.hash}, function (err, txs) {
					if (err) {
						logger.error('Error during reorg (while getting'+
									 'txs to disconnect): '+err);
						return;
					}

					txs.forEach(function (tx, i) {
						self.emit('txRevoke', {
							block: block,
							index: i,
							tx: tx,
							chain: self
						});
						tx.active = false;
						tx.save(function (err) {
							if (err) {
								logger.error('Error during reorg'+
											 '(while disconnecting tx): '+err);
							}
						});
					});
				});

				block.save(function (err) {
					if (err) {
						logger.error('Error during reorg'+
									 '(while disconnecting block): '+err);
					}
				});
			});

			// Connect new fork
			toConnect.forEach(function (block) {
				block.active = true;

				Transaction.find({block: block.hash}, function (err, txs) {
					if (err) {
						logger.error('Error during reorg (while getting'+
									 'txs to connect): '+err);
						return;
					}

					txs.forEach(function (tx, i) {
						self.emit('txAdd', {
							block: block,
							index: i,
							tx: tx,
							chain: self
						});
						tx.active = true;
						tx.save(function (err) {
							if (err) {
								logger.error('Error during reorg'+
											 '(while connecting tx): '+err);
								return;
							}
							self.emit('txSave', {
								block: block,
								index: i,
								tx: tx,
								chain: self
							});
						});
					});
				});
			});

			// TODO: Transactions from the disconnected chain should be added
			//       to the memory pool.
		});
	};

	this.makeBlockObject = function (blockData) {
		return new Block(blockData);
	};

	this.executeOrphanBlockFutures = function (block) {
		var futures = orphanBlockFutures[block.hash];
		if (futures) {
			for (var i in futures) {
				if(futures.hasOwnProperty(i)) {
					futures[i](block);
				}
			}
			delete orphanBlockFutures[block.hash];
		}
	};

	this.init = function () {
		createGenesisBlock(function () {
			loadTopBlock(function () {
				self.emit('initComplete');
			});
		});
	};

	// We can execute block futures as early as the blockAdd, but we have to
	// make sure we catch futures that are added later as well, by listening to
	// blockSave.
	function handleBlockEvent(e) {
		self.executeOrphanBlockFutures(e.block);
	}
	this.on('blockAdd', handleBlockEvent);
	this.on('blockSave', handleBlockEvent);
};

sys.inherits(BlockChain, events.EventEmitter);
<commit_msg>Giving BlockChain object a name in stack traces etc.<commit_after>var sys = require('sys');
var logger = require('./logger');
var Binary = require('binary');
var Util = require('./util');
var BlockLocator = require('./blocklocator').BlockLocator;

var genesis_block = {
	'height': 0,
	'nonce': 2083236893,
	'version': 1,
	'hash': new Buffer('6FE28C0AB6F1B372C1A6A246AE63F74F931E8365E15A089C68D6190000000000', 'hex'),
	'prev_hash': new Buffer(32).clear(),
	'timestamp': 1231006505,
	'merkle_root': new Buffer('3BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A', 'hex'),
	'bits': 486604799
};

var genesis_block_tx = {
	'outs': [{
		'value': new Buffer('00F2052A01000000', 'hex'), // 50 BTC
		'script': Binary.put()
			.word8(65) // ???
			.put(new Buffer('04678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5F', 'hex'))
			.word8(0xAC)
			.buffer() // OP_CHECKSIG
	}],
	'lock_time': 0,
	'version': 1,
	'hash': new Buffer('3BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A', 'hex'),
	'ins': [{
		'sequence': 0xFFFFFFFF,
		'outpoint': {
			'index': 0xFFFFFFFF,
			'hash': new Buffer(32).clear()
		},
		'script': Binary.put()
			.put(new Buffer('04FFFF001D010445', 'hex'))
			.put(new Buffer('The Times 03/Jan/2009 Chancellor on brink of second bailout for banks', 'ascii'))
			.buffer()
	}]
};

var BlockChain = exports.BlockChain = function BlockChain(storage) {
	events.EventEmitter.call(this);

	this.storage = storage;

	var self = this;

	var Block = this.storage.Block;
	var Transaction = this.storage.Transaction;
	var Account = this.storage.Account;

	var genesisBlock = null;
	var currentTopBlock = null;
	var lastRecvBlock = null;
	var orphanBlockFutures = {};
	var queueCount = 0;

	function createGenesisBlock(callback) {
		logger.info("Loading genesis block");

		try {
			genesisBlock = currentTopBlock = new Block(genesis_block);
			genesisBlock.active = true;
			genesisBlock.setChainWork(genesisBlock.getWork());

			// A simple sanity check to make sure our constants are not
			// corrupted and our block hashing algorithm is working.
			if (!genesisBlock.checkHash()) {
				logger.error("Genesis block hash validation failed. There is something wrong with our constants or block hash validation code.");
				return;
			}

			var genesisTransaction = new Transaction(genesis_block_tx);

			self.emit('blockAdd', {block: genesisBlock, txs: [genesisTransaction]});
		} catch (e) {
			logger.error("Error while adding genesis block: "+(e.stack ? e.stack : e));
			return;
		}

		genesisBlock.save(function (err) {
			// It's faster to just ignore the duplicate key error than to
			// check beforehand
			if (err && err.message.indexOf("E11000") == -1) {
				logger.error(err);
				callback(err);
				return;
			}

			if (!genesisTransaction.checkHash()) {
				logger.error("Genesis tx hash validation failed. There is something wrong with our constants or tx hash validation code.");
				return;
			}

			genesisTransaction.block = genesisBlock.getHash();
			genesisTransaction.active = true;

			self.emit('txAdd', {block: genesisBlock, index: 0, tx: genesisTransaction, chain: self});

			genesisTransaction.save(function (err) {
				// It's faster to just ignore the duplicate key error than to
				// check beforehand
				if (err && err.message.indexOf("E11000") == -1) {
					logger.error(err);
					callback(err);
					return;
				}

				self.emit('txAdd', {block: genesisBlock, index: 0, tx: genesisTransaction, chain: self});
			});

			self.emit('blockSave', {block: genesisBlock, txs: [genesisTransaction]});
			callback();
		});
	}

	function loadTopBlock(callback) {
		Block.find().sort('height', -1).limit(1).exec(function (err, block) {
			if (err) {
				logger.error("Error while initializing block chain", err);
				return;
			}
			currentTopBlock = block[0];
			callback();
		});
	}

	this.getBlockByHash = function getBlockByHash(hash, callback) {
		Block.findOne({hash: hash}, function (err, block) {
			if (err) {
				callback(err);
				return;
			}

			callback(err, block);
		});
	};

	this.getBlockByPrev = function getBlockByPrev(block, callback) {
		if ("object" == typeof block && block.hash) {
			block = block.hash;
		}

		Block.findOne({prev_hash: block}, function (err, block) {
			if (err) {
				callback(err);
				return;
			}

			callback(err, block);
		});
	};

	this.getGenesisBlock = function getGenesisBlock() {
		return genesisBlock;
	};

	this.getTopBlock = function getTopBlock() {
		return currentTopBlock;
	};

	this.getBlockLocator = function getBlockLocator(callback) {
		BlockLocator.createFromBlockChain(this, callback);
	};

	/**
	 * Get the last block we received.
	 *
	 * Very untrusted! This is only meant for continuously requesting
	 * blocks during a block chain download. Otherwise always use
	 * getTopBlock().
	 */
	this.getLastRecvBlock = function getLastRecvBlock () {
		return lastRecvBlock;
	};

	this.getQueueCount = function () {
		return queueCount;
	};

	this.add = function add(block, txs, callback) {
		var self = this;

		if (!block instanceof Block) {
			block = this.makeBlockObject(block);
		}

		function connectBlockToParentAndSave(parent) {
			// Our parent block is there, let's attach ourselves
			block.height = parent.height + 1;
			block.setChainWork(parent.getChainWork().add(block.getWork()));

			// Update top block field if this block is a child of it
			if (currentTopBlock.hash.compare(parent.hash) === 0) {
				currentTopBlock = block;
				block.active = true;
			} else {
				// Block belongs to a side chain, switch chains if side
				// chain has more work.
				block.active = false;
				if (block.moreWorkThan(currentTopBlock)) {
					self.reorganize(currentTopBlock, block);
					currentTopBlock = block;
				} else {
					logger.info('Adding block '+Util.formatHash(block.hash)+
								' on side chain');
				}
			}

			self.emit('blockAdd', {block: block, txs: txs, chain: self});

			block.save(function (err) {
				queueCount--;

				if (err) {
					// TODO: Handle if block is a duplicate
					return callback(err);
				}

				// Asynchronously store all of this block's transactions to the database
				self.addTransactions(block, txs);

				// This event will also trigger us saving all child blocks that
				// are currently waiting.
				self.emit('blockSave', {block: block, txs: txs, chain: self});

				callback(err, block);
			});
		}

		// Static checks
		try {
			block.checkBlock();
		} catch (e) {
			callback('Check failed: '+e, null);
		}

		lastRecvBlock = block;

		queueCount++;

		this.getBlockByHash(block.prev_hash, function (err, prevBlock) {
			// Let's see if we are able to connect into the chain
			if (!err && prevBlock && prevBlock.height >= 0) {
				// Our parent is in the chain, connect up and save
				connectBlockToParentAndSave(prevBlock);
			} else {
				// Our parent is not in the chain, create a future to be
				// executed when it is.
				var future = connectBlockToParentAndSave;
				if (!orphanBlockFutures[block.prev_hash]) {
					orphanBlockFutures[block.prev_hash] = {};
				}
				orphanBlockFutures[block.prev_hash][block.hash] = future;
			}
		});
	};

	this.addTransactions = function addTransactions(block, txs) {
		txs.forEach(function (tx, i) {
			tx = new Transaction(tx);

			tx.block = block.getHash();
			tx.active = block.active;

			// Calculate hash
			tx.getHash();

			self.emit('txAdd', {block: block, index: i, tx: tx, chain: self});

			tx.save(function (err) {
				if (err) {
					logger.warn(err);
					return;
				}

				self.emit('txSave', {block: block, index: i, tx: tx, chain: self});
			});
		});
	};

	this.reorganize = function reorganize(oldTopBlock, newTopBlock) {
		logger.info('Reorganize (old head: '+Util.formatHash(oldTopBlock.hash)+
					', new head: '+Util.formatHash(newTopBlock.hash)+')');

		var toDisconnect = [];
		var toConnect = [];

		// Follow the chains down to the fork
		function findFork(bOld, bNew, callback) {
			if (bOld.hash.compare(bNew.hash) === 0) {
				callback(null, bOld);
			}

			if (bOld.height > bNew.height) {
				toDisconnect.push(bOld);
				self.getBlockByPrev(bOld, function (err, bOld) {
					if (err) {
						callback(err);
						return;
					}
					findFork(bOld, bNew, callback);
				});
			} else {
				if (bNew.height <= 0) {
					callback(new Error("No common root found"));
				}
				toConnect.push(bNew);
				self.getBlockByPrev(bNew, function (err, bNew) {
					if (err) {
						callback(err);
						return;
					}
					findFork(bOld, bNew, callback);
				});
			}
		}

		findFork(oldTopBlock, newTopBlock, function (err) {
			if (err) {
				logger.error('Unable to reorganize: '+err);
				return;
			}

			// Disconnect old fork
			toDisconnect.forEach(function (block) {
				block.active = false;

				Transaction.find({block: block.hash}, function (err, txs) {
					if (err) {
						logger.error('Error during reorg (while getting'+
									 'txs to disconnect): '+err);
						return;
					}

					txs.forEach(function (tx, i) {
						self.emit('txRevoke', {
							block: block,
							index: i,
							tx: tx,
							chain: self
						});
						tx.active = false;
						tx.save(function (err) {
							if (err) {
								logger.error('Error during reorg'+
											 '(while disconnecting tx): '+err);
							}
						});
					});
				});

				block.save(function (err) {
					if (err) {
						logger.error('Error during reorg'+
									 '(while disconnecting block): '+err);
					}
				});
			});

			// Connect new fork
			toConnect.forEach(function (block) {
				block.active = true;

				Transaction.find({block: block.hash}, function (err, txs) {
					if (err) {
						logger.error('Error during reorg (while getting'+
									 'txs to connect): '+err);
						return;
					}

					txs.forEach(function (tx, i) {
						self.emit('txAdd', {
							block: block,
							index: i,
							tx: tx,
							chain: self
						});
						tx.active = true;
						tx.save(function (err) {
							if (err) {
								logger.error('Error during reorg'+
											 '(while connecting tx): '+err);
								return;
							}
							self.emit('txSave', {
								block: block,
								index: i,
								tx: tx,
								chain: self
							});
						});
					});
				});
			});

			// TODO: Transactions from the disconnected chain should be added
			//       to the memory pool.
		});
	};

	this.makeBlockObject = function (blockData) {
		return new Block(blockData);
	};

	this.executeOrphanBlockFutures = function (block) {
		var futures = orphanBlockFutures[block.hash];
		if (futures) {
			for (var i in futures) {
				if(futures.hasOwnProperty(i)) {
					futures[i](block);
				}
			}
			delete orphanBlockFutures[block.hash];
		}
	};

	this.init = function () {
		createGenesisBlock(function () {
			loadTopBlock(function () {
				self.emit('initComplete');
			});
		});
	};

	// We can execute block futures as early as the blockAdd, but we have to
	// make sure we catch futures that are added later as well, by listening to
	// blockSave.
	function handleBlockEvent(e) {
		self.executeOrphanBlockFutures(e.block);
	}
	this.on('blockAdd', handleBlockEvent);
	this.on('blockSave', handleBlockEvent);
};

sys.inherits(BlockChain, events.EventEmitter);
<|endoftext|>


<commit_before>import _ from 'lodash'
import logger from 'winston'

// Create all element services
export default async function initializeElements (app, forecast, servicesPath) {
  logger.info('Initializing ' + forecast.name + ' forecast')
  const forecastsService = app.getService('forecasts')
  // Register the forecast model if not already done
  const result = await forecastsService.find({
    query: {
      name: forecast.name,
      $select: ['_id'] // We only need object ID
    }
  })
  if (result.data.length > 0) {
    await forecastsService.patch(result.data[0]._id, forecast)
  } else {
    await forecastsService.create(forecast)
  }

  // Create download buckets
  let elementBuckets = {}
  forecast.elements.forEach(element => {
    const bucket = element.bucket || 0
    // Initialize bucket
    if (!elementBuckets[bucket]) elementBuckets[bucket] = []
    elementBuckets[bucket].push(element)
  })

  // Then generate services for each forecast element in buckets
  // Retrieve generic elements options if any
  const elementServiceOptions = app.getServiceOptions('elements')
  elementBuckets = _.mapValues(elementBuckets, elements => {
    return elements.map(element => app.createElementService(forecast, element, servicesPath,
      Object.assign({}, element.serviceOptions, elementServiceOptions)))
  })

  async function update () {
    // Iterate over buckets
    const buckets = _.keys(elementBuckets)
    for (let i = 0; i < buckets.length; i++) {
      const bucket = buckets[i]
      // For each bucket launch download tasks in parallel
      await Promise.all(elementBuckets[bucket].map(service => {
        return service.updateForecastData().catch(error => {
          logger.error(error.message)
          service.updateRunning = false
        })
      }))
    }
  }

  if (forecast.updateInterval >= 0) {
    // Trigger the initial harvesting, i.e. try data refresh for current time
    // Add a small offset to wait for everything being initialized
    setTimeout(update, 30 * 1000)
    // Then plan next updates according to provided update interval if required
    if (forecast.updateInterval > 0) {
      logger.info('Installing forecast update on ' + forecast.name + ' with interval (s) ' + forecast.updateInterval)
      setInterval(update, 1000 * forecast.updateInterval)
    }
  }

  // Process elements with GridFS data store which requires manual cleanup
  const elementsToClean = forecast.elements.filter(element => element.dataStore === 'gridfs')

  async function clean () {
    // Iterate over required elements
    for (let i = 0; i < elementsToClean.length; i++) {
      let service = app.getService(forecast.name + '/' + elementsToClean[i].name)
      // Launch clean task
      await service.cleanForecastData().catch(error => {
        logger.error(error.message)
        service.cleanupRunning = false
      })
    }
  }

  if (elementsToClean.length > 0) {
    // Trigger the initial cleanup, i.e. try data cleanup for current time
    // Add a small offset to wait for everything being initialized
    setTimeout(clean, 10 * 1000)
    // Then plan next cleanups according to provided clean interval if required, alternatively with data update
    // Provide a default interval if no updates
    const cleanInterval = (forecast.updateInterval >= 0 ? forecast.updateInterval : 30 * 60)
    if (cleanInterval > 0) {
      setTimeout(() => {
        logger.info('Installing forecast cleanup on ' + forecast.name + ' with interval (s) ' + cleanInterval)
        setInterval(clean, 1000 * cleanInterval)
      }, 0.5 * cleanInterval)
    }
  }
}
<commit_msg>Fixed bad try/catch block on clean up<commit_after>import _ from 'lodash'
import logger from 'winston'

// Create all element services
export default async function initializeElements (app, forecast, servicesPath) {
  logger.info('Initializing ' + forecast.name + ' forecast')
  const forecastsService = app.getService('forecasts')
  // Register the forecast model if not already done
  const result = await forecastsService.find({
    query: {
      name: forecast.name,
      $select: ['_id'] // We only need object ID
    }
  })
  if (result.data.length > 0) {
    await forecastsService.patch(result.data[0]._id, forecast)
  } else {
    await forecastsService.create(forecast)
  }

  // Create download buckets
  let elementBuckets = {}
  forecast.elements.forEach(element => {
    const bucket = element.bucket || 0
    // Initialize bucket
    if (!elementBuckets[bucket]) elementBuckets[bucket] = []
    elementBuckets[bucket].push(element)
  })

  // Then generate services for each forecast element in buckets
  // Retrieve generic elements options if any
  const elementServiceOptions = app.getServiceOptions('elements')
  elementBuckets = _.mapValues(elementBuckets, elements => {
    return elements.map(element => app.createElementService(forecast, element, servicesPath,
      Object.assign({}, element.serviceOptions, elementServiceOptions)))
  })

  async function update () {
    // Iterate over buckets
    const buckets = _.keys(elementBuckets)
    for (let i = 0; i < buckets.length; i++) {
      const bucket = buckets[i]
      // For each bucket launch download tasks in parallel
      await Promise.all(elementBuckets[bucket].map(service => {
        return service.updateForecastData().catch(error => {
          logger.error(error.message)
          service.updateRunning = false
        })
      }))
    }
  }

  if (forecast.updateInterval >= 0) {
    // Trigger the initial harvesting, i.e. try data refresh for current time
    // Add a small offset to wait for everything being initialized
    setTimeout(update, 30 * 1000)
    // Then plan next updates according to provided update interval if required
    if (forecast.updateInterval > 0) {
      logger.info('Installing forecast update on ' + forecast.name + ' with interval (s) ' + forecast.updateInterval)
      setInterval(update, 1000 * forecast.updateInterval)
    }
  }

  // Process elements with GridFS data store which requires manual cleanup
  const elementsToClean = forecast.elements.filter(element => element.dataStore === 'gridfs')

  async function clean () {
    // Iterate over required elements
    for (let i = 0; i < elementsToClean.length; i++) {
      let service = app.getService(forecast.name + '/' + elementsToClean[i].name)
      // Launch clean task
      try {
        await service.cleanForecastData()
      } catch (error) {
        logger.error(error.message)
      }
    }
  }

  if (elementsToClean.length > 0) {
    // Trigger the initial cleanup, i.e. try data cleanup for current time
    // Add a small offset to wait for everything being initialized
    setTimeout(clean, 10 * 1000)
    // Then plan next cleanups according to provided clean interval if required, alternatively with data update
    // Provide a default interval if no updates
    const cleanInterval = (forecast.updateInterval >= 0 ? forecast.updateInterval : 30 * 60)
    if (cleanInterval > 0) {
      setTimeout(() => {
        logger.info('Installing forecast cleanup on ' + forecast.name + ' with interval (s) ' + cleanInterval)
        setInterval(clean, 1000 * cleanInterval)
      }, 0.5 * cleanInterval)
    }
  }
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

'use strict';

// Inspired by https://github.com/airbnb/javascript but less opinionated.

// We use eslint-loader so even warnings are very visible.
// This is why we only use "WARNING" level for potential errors,
// and we don't use "ERROR" level at all.

// In the future, we might create a separate list of rules for production.
// It would probably be more strict.

// The ESLint browser environment defines all browser globals as valid,
// even though most people don't know some of them exist (e.g. `name` or `status`).
// This is dangerous as it hides accidentally undefined variables.
// We blacklist the globals that we deem potentially confusing.
// To use them, explicitly reference them, e.g. `window.name` or `window.status`.
const restrictedGlobals = require('confusing-browser-globals');

module.exports = {
  root: true,

  parser: 'babel-eslint',

  plugins: ['import', 'flowtype', 'jsx-a11y', 'react', 'react-hooks'],

  env: {
    browser: true,
    commonjs: true,
    es6: true,
    jest: true,
    node: true,
  },

  parserOptions: {
    ecmaVersion: 2018,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },

  settings: {
    react: {
      version: 'detect',
    },
  },

  overrides: {
    files: ['**/*.ts', '**/*.tsx'],
    parser: '@typescript-eslint/parser',
    parserOptions: {
      ecmaVersion: 2018,
      sourceType: 'module',
      ecmaFeatures: {
        jsx: true,
      },

      // typescript-eslint specific options
      warnOnUnsupportedTypeScriptVersion: true,
    },
    plugins: ['@typescript-eslint'],
    // If adding a typescript-eslint version of an existing ESLint rule,
    // make sure to disable the ESLint rule here.
    rules: {
      // TypeScript's `noFallthroughCasesInSwitch` option is more robust (#6906)
      'default-case': 'off',
      // 'tsc' already handles this (https://github.com/typescript-eslint/typescript-eslint/issues/291)
      'no-dupe-class-members': 'off',
      // 'tsc' already handles this (https://github.com/typescript-eslint/typescript-eslint/issues/477)
      'no-undef': 'off',

      // Add TypeScript specific rules (and turn off ESLint equivalents)
      '@typescript-eslint/no-angle-bracket-type-assertion': 'warn',
      'no-array-constructor': 'off',
      '@typescript-eslint/no-array-constructor': 'warn',
      '@typescript-eslint/no-namespace': 'error',
      'no-use-before-define': 'off',
      '@typescript-eslint/no-use-before-define': [
        'warn',
        {
          functions: false,
          classes: false,
          variables: false,
          typedefs: false,
        },
      ],
      'no-unused-vars': 'off',
      '@typescript-eslint/no-unused-vars': [
        'warn',
        {
          args: 'none',
          ignoreRestSiblings: true,
        },
      ],
      'no-useless-constructor': 'off',
      '@typescript-eslint/no-useless-constructor': 'warn',
    },
  },

  // NOTE: When adding rules here, you need to make sure they are compatible with
  // `typescript-eslint`, as some rules such as `no-array-constructor` aren't compatible.
  rules: {
    // http://eslint.org/docs/rules/
    'array-callback-return': 'warn',
    'default-case': ['warn', { commentPattern: '^no default$' }],
    'dot-location': ['warn', 'property'],
    eqeqeq: ['warn', 'smart'],
    'new-parens': 'warn',
    'no-array-constructor': 'warn',
    'no-caller': 'warn',
    'no-cond-assign': ['warn', 'except-parens'],
    'no-const-assign': 'warn',
    'no-control-regex': 'warn',
    'no-delete-var': 'warn',
    'no-dupe-args': 'warn',
    'no-dupe-class-members': 'warn',
    'no-dupe-keys': 'warn',
    'no-duplicate-case': 'warn',
    'no-empty-character-class': 'warn',
    'no-empty-pattern': 'warn',
    'no-eval': 'warn',
    'no-ex-assign': 'warn',
    'no-extend-native': 'warn',
    'no-extra-bind': 'warn',
    'no-extra-label': 'warn',
    'no-fallthrough': 'warn',
    'no-func-assign': 'warn',
    'no-implied-eval': 'warn',
    'no-invalid-regexp': 'warn',
    'no-iterator': 'warn',
    'no-label-var': 'warn',
    'no-labels': ['warn', { allowLoop: true, allowSwitch: false }],
    'no-lone-blocks': 'warn',
    'no-loop-func': 'warn',
    'no-mixed-operators': [
      'warn',
      {
        groups: [
          ['&', '|', '^', '~', '<<', '>>', '>>>'],
          ['==', '!=', '===', '!==', '>', '>=', '<', '<='],
          ['&&', '||'],
          ['in', 'instanceof'],
        ],
        allowSamePrecedence: false,
      },
    ],
    'no-multi-str': 'warn',
    'no-native-reassign': 'warn',
    'no-negated-in-lhs': 'warn',
    'no-new-func': 'warn',
    'no-new-object': 'warn',
    'no-new-symbol': 'warn',
    'no-new-wrappers': 'warn',
    'no-obj-calls': 'warn',
    'no-octal': 'warn',
    'no-octal-escape': 'warn',
    'no-redeclare': 'warn',
    'no-regex-spaces': 'warn',
    'no-restricted-syntax': ['warn', 'WithStatement'],
    'no-script-url': 'warn',
    'no-self-assign': 'warn',
    'no-self-compare': 'warn',
    'no-sequences': 'warn',
    'no-shadow-restricted-names': 'warn',
    'no-sparse-arrays': 'warn',
    'no-template-curly-in-string': 'warn',
    'no-this-before-super': 'warn',
    'no-throw-literal': 'warn',
    'no-undef': 'error',
    'no-restricted-globals': ['error'].concat(restrictedGlobals),
    'no-unexpected-multiline': 'warn',
    'no-unreachable': 'warn',
    'no-unused-expressions': [
      'error',
      {
        allowShortCircuit: true,
        allowTernary: true,
        allowTaggedTemplates: true,
      },
    ],
    'no-unused-labels': 'warn',
    'no-unused-vars': [
      'warn',
      {
        args: 'none',
        ignoreRestSiblings: true,
      },
    ],
    'no-use-before-define': [
      'warn',
      {
        functions: false,
        classes: false,
        variables: false,
      },
    ],
    'no-useless-computed-key': 'warn',
    'no-useless-concat': 'warn',
    'no-useless-constructor': 'warn',
    'no-useless-escape': 'warn',
    'no-useless-rename': [
      'warn',
      {
        ignoreDestructuring: false,
        ignoreImport: false,
        ignoreExport: false,
      },
    ],
    'no-with': 'warn',
    'no-whitespace-before-property': 'warn',
    'react-hooks/exhaustive-deps': 'warn',
    'require-yield': 'warn',
    'rest-spread-spacing': ['warn', 'never'],
    strict: ['warn', 'never'],
    'unicode-bom': ['warn', 'never'],
    'use-isnan': 'warn',
    'valid-typeof': 'warn',
    'no-restricted-properties': [
      'error',
      {
        object: 'require',
        property: 'ensure',
        message:
          'Please use import() instead. More info: https://facebook.github.io/create-react-app/docs/code-splitting',
      },
      {
        object: 'System',
        property: 'import',
        message:
          'Please use import() instead. More info: https://facebook.github.io/create-react-app/docs/code-splitting',
      },
    ],
    'getter-return': 'warn',

    // https://github.com/benmosher/eslint-plugin-import/tree/master/docs/rules
    'import/first': 'error',
    'import/no-amd': 'error',
    'import/no-webpack-loader-syntax': 'error',

    // https://github.com/yannickcr/eslint-plugin-react/tree/master/docs/rules
    'react/forbid-foreign-prop-types': ['warn', { allowInPropTypes: true }],
    'react/jsx-no-comment-textnodes': 'warn',
    'react/jsx-no-duplicate-props': ['warn', { ignoreCase: true }],
    'react/jsx-no-target-blank': 'warn',
    'react/jsx-no-undef': 'error',
    'react/jsx-pascal-case': [
      'warn',
      {
        allowAllCaps: true,
        ignore: [],
      },
    ],
    'react/jsx-uses-react': 'warn',
    'react/jsx-uses-vars': 'warn',
    'react/no-danger-with-children': 'warn',
    // Disabled because of undesirable warnings
    // See https://github.com/facebook/create-react-app/issues/5204 for
    // blockers until its re-enabled
    // 'react/no-deprecated': 'warn',
    'react/no-direct-mutation-state': 'warn',
    'react/no-is-mounted': 'warn',
    'react/no-typos': 'error',
    'react/react-in-jsx-scope': 'error',
    'react/require-render-return': 'error',
    'react/style-prop-object': 'warn',

    // https://github.com/evcohen/eslint-plugin-jsx-a11y/tree/master/docs/rules
    'jsx-a11y/accessible-emoji': 'warn',
    'jsx-a11y/alt-text': 'warn',
    'jsx-a11y/anchor-has-content': 'warn',
    'jsx-a11y/anchor-is-valid': [
      'warn',
      {
        aspects: ['noHref', 'invalidHref'],
      },
    ],
    'jsx-a11y/aria-activedescendant-has-tabindex': 'warn',
    'jsx-a11y/aria-props': 'warn',
    'jsx-a11y/aria-proptypes': 'warn',
    'jsx-a11y/aria-role': 'warn',
    'jsx-a11y/aria-unsupported-elements': 'warn',
    'jsx-a11y/heading-has-content': 'warn',
    'jsx-a11y/iframe-has-title': 'warn',
    'jsx-a11y/img-redundant-alt': 'warn',
    'jsx-a11y/no-access-key': 'warn',
    'jsx-a11y/no-distracting-elements': 'warn',
    'jsx-a11y/no-redundant-roles': 'warn',
    'jsx-a11y/role-has-required-aria-props': 'warn',
    'jsx-a11y/role-supports-aria-props': 'warn',
    'jsx-a11y/scope': 'warn',

    // https://github.com/facebook/react/tree/master/packages/eslint-plugin-react-hooks
    'react-hooks/rules-of-hooks': 'error',

    // https://github.com/gajus/eslint-plugin-flowtype
    'flowtype/define-flow-type': 'warn',
    'flowtype/require-valid-file-annotation': 'warn',
    'flowtype/use-flow-type': 'warn',
  },
};
<commit_msg>fix: ESLint config overrides key should be an array, not object (#7219)<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

'use strict';

// Inspired by https://github.com/airbnb/javascript but less opinionated.

// We use eslint-loader so even warnings are very visible.
// This is why we only use "WARNING" level for potential errors,
// and we don't use "ERROR" level at all.

// In the future, we might create a separate list of rules for production.
// It would probably be more strict.

// The ESLint browser environment defines all browser globals as valid,
// even though most people don't know some of them exist (e.g. `name` or `status`).
// This is dangerous as it hides accidentally undefined variables.
// We blacklist the globals that we deem potentially confusing.
// To use them, explicitly reference them, e.g. `window.name` or `window.status`.
const restrictedGlobals = require('confusing-browser-globals');

module.exports = {
  root: true,

  parser: 'babel-eslint',

  plugins: ['import', 'flowtype', 'jsx-a11y', 'react', 'react-hooks'],

  env: {
    browser: true,
    commonjs: true,
    es6: true,
    jest: true,
    node: true,
  },

  parserOptions: {
    ecmaVersion: 2018,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },

  settings: {
    react: {
      version: 'detect',
    },
  },

  overrides: [
    {
      files: ['**/*.ts', '**/*.tsx'],
      parser: '@typescript-eslint/parser',
      parserOptions: {
        ecmaVersion: 2018,
        sourceType: 'module',
        ecmaFeatures: {
          jsx: true,
        },

        // typescript-eslint specific options
        warnOnUnsupportedTypeScriptVersion: true,
      },
      plugins: ['@typescript-eslint'],
      // If adding a typescript-eslint version of an existing ESLint rule,
      // make sure to disable the ESLint rule here.
      rules: {
        // TypeScript's `noFallthroughCasesInSwitch` option is more robust (#6906)
        'default-case': 'off',
        // 'tsc' already handles this (https://github.com/typescript-eslint/typescript-eslint/issues/291)
        'no-dupe-class-members': 'off',
        // 'tsc' already handles this (https://github.com/typescript-eslint/typescript-eslint/issues/477)
        'no-undef': 'off',

        // Add TypeScript specific rules (and turn off ESLint equivalents)
        '@typescript-eslint/no-angle-bracket-type-assertion': 'warn',
        'no-array-constructor': 'off',
        '@typescript-eslint/no-array-constructor': 'warn',
        '@typescript-eslint/no-namespace': 'error',
        'no-use-before-define': 'off',
        '@typescript-eslint/no-use-before-define': [
          'warn',
          {
            functions: false,
            classes: false,
            variables: false,
            typedefs: false,
          },
        ],
        'no-unused-vars': 'off',
        '@typescript-eslint/no-unused-vars': [
          'warn',
          {
            args: 'none',
            ignoreRestSiblings: true,
          },
        ],
        'no-useless-constructor': 'off',
        '@typescript-eslint/no-useless-constructor': 'warn',
      },
    },
  ],

  // NOTE: When adding rules here, you need to make sure they are compatible with
  // `typescript-eslint`, as some rules such as `no-array-constructor` aren't compatible.
  rules: {
    // http://eslint.org/docs/rules/
    'array-callback-return': 'warn',
    'default-case': ['warn', { commentPattern: '^no default$' }],
    'dot-location': ['warn', 'property'],
    eqeqeq: ['warn', 'smart'],
    'new-parens': 'warn',
    'no-array-constructor': 'warn',
    'no-caller': 'warn',
    'no-cond-assign': ['warn', 'except-parens'],
    'no-const-assign': 'warn',
    'no-control-regex': 'warn',
    'no-delete-var': 'warn',
    'no-dupe-args': 'warn',
    'no-dupe-class-members': 'warn',
    'no-dupe-keys': 'warn',
    'no-duplicate-case': 'warn',
    'no-empty-character-class': 'warn',
    'no-empty-pattern': 'warn',
    'no-eval': 'warn',
    'no-ex-assign': 'warn',
    'no-extend-native': 'warn',
    'no-extra-bind': 'warn',
    'no-extra-label': 'warn',
    'no-fallthrough': 'warn',
    'no-func-assign': 'warn',
    'no-implied-eval': 'warn',
    'no-invalid-regexp': 'warn',
    'no-iterator': 'warn',
    'no-label-var': 'warn',
    'no-labels': ['warn', { allowLoop: true, allowSwitch: false }],
    'no-lone-blocks': 'warn',
    'no-loop-func': 'warn',
    'no-mixed-operators': [
      'warn',
      {
        groups: [
          ['&', '|', '^', '~', '<<', '>>', '>>>'],
          ['==', '!=', '===', '!==', '>', '>=', '<', '<='],
          ['&&', '||'],
          ['in', 'instanceof'],
        ],
        allowSamePrecedence: false,
      },
    ],
    'no-multi-str': 'warn',
    'no-native-reassign': 'warn',
    'no-negated-in-lhs': 'warn',
    'no-new-func': 'warn',
    'no-new-object': 'warn',
    'no-new-symbol': 'warn',
    'no-new-wrappers': 'warn',
    'no-obj-calls': 'warn',
    'no-octal': 'warn',
    'no-octal-escape': 'warn',
    'no-redeclare': 'warn',
    'no-regex-spaces': 'warn',
    'no-restricted-syntax': ['warn', 'WithStatement'],
    'no-script-url': 'warn',
    'no-self-assign': 'warn',
    'no-self-compare': 'warn',
    'no-sequences': 'warn',
    'no-shadow-restricted-names': 'warn',
    'no-sparse-arrays': 'warn',
    'no-template-curly-in-string': 'warn',
    'no-this-before-super': 'warn',
    'no-throw-literal': 'warn',
    'no-undef': 'error',
    'no-restricted-globals': ['error'].concat(restrictedGlobals),
    'no-unexpected-multiline': 'warn',
    'no-unreachable': 'warn',
    'no-unused-expressions': [
      'error',
      {
        allowShortCircuit: true,
        allowTernary: true,
        allowTaggedTemplates: true,
      },
    ],
    'no-unused-labels': 'warn',
    'no-unused-vars': [
      'warn',
      {
        args: 'none',
        ignoreRestSiblings: true,
      },
    ],
    'no-use-before-define': [
      'warn',
      {
        functions: false,
        classes: false,
        variables: false,
      },
    ],
    'no-useless-computed-key': 'warn',
    'no-useless-concat': 'warn',
    'no-useless-constructor': 'warn',
    'no-useless-escape': 'warn',
    'no-useless-rename': [
      'warn',
      {
        ignoreDestructuring: false,
        ignoreImport: false,
        ignoreExport: false,
      },
    ],
    'no-with': 'warn',
    'no-whitespace-before-property': 'warn',
    'react-hooks/exhaustive-deps': 'warn',
    'require-yield': 'warn',
    'rest-spread-spacing': ['warn', 'never'],
    strict: ['warn', 'never'],
    'unicode-bom': ['warn', 'never'],
    'use-isnan': 'warn',
    'valid-typeof': 'warn',
    'no-restricted-properties': [
      'error',
      {
        object: 'require',
        property: 'ensure',
        message:
          'Please use import() instead. More info: https://facebook.github.io/create-react-app/docs/code-splitting',
      },
      {
        object: 'System',
        property: 'import',
        message:
          'Please use import() instead. More info: https://facebook.github.io/create-react-app/docs/code-splitting',
      },
    ],
    'getter-return': 'warn',

    // https://github.com/benmosher/eslint-plugin-import/tree/master/docs/rules
    'import/first': 'error',
    'import/no-amd': 'error',
    'import/no-webpack-loader-syntax': 'error',

    // https://github.com/yannickcr/eslint-plugin-react/tree/master/docs/rules
    'react/forbid-foreign-prop-types': ['warn', { allowInPropTypes: true }],
    'react/jsx-no-comment-textnodes': 'warn',
    'react/jsx-no-duplicate-props': ['warn', { ignoreCase: true }],
    'react/jsx-no-target-blank': 'warn',
    'react/jsx-no-undef': 'error',
    'react/jsx-pascal-case': [
      'warn',
      {
        allowAllCaps: true,
        ignore: [],
      },
    ],
    'react/jsx-uses-react': 'warn',
    'react/jsx-uses-vars': 'warn',
    'react/no-danger-with-children': 'warn',
    // Disabled because of undesirable warnings
    // See https://github.com/facebook/create-react-app/issues/5204 for
    // blockers until its re-enabled
    // 'react/no-deprecated': 'warn',
    'react/no-direct-mutation-state': 'warn',
    'react/no-is-mounted': 'warn',
    'react/no-typos': 'error',
    'react/react-in-jsx-scope': 'error',
    'react/require-render-return': 'error',
    'react/style-prop-object': 'warn',

    // https://github.com/evcohen/eslint-plugin-jsx-a11y/tree/master/docs/rules
    'jsx-a11y/accessible-emoji': 'warn',
    'jsx-a11y/alt-text': 'warn',
    'jsx-a11y/anchor-has-content': 'warn',
    'jsx-a11y/anchor-is-valid': [
      'warn',
      {
        aspects: ['noHref', 'invalidHref'],
      },
    ],
    'jsx-a11y/aria-activedescendant-has-tabindex': 'warn',
    'jsx-a11y/aria-props': 'warn',
    'jsx-a11y/aria-proptypes': 'warn',
    'jsx-a11y/aria-role': 'warn',
    'jsx-a11y/aria-unsupported-elements': 'warn',
    'jsx-a11y/heading-has-content': 'warn',
    'jsx-a11y/iframe-has-title': 'warn',
    'jsx-a11y/img-redundant-alt': 'warn',
    'jsx-a11y/no-access-key': 'warn',
    'jsx-a11y/no-distracting-elements': 'warn',
    'jsx-a11y/no-redundant-roles': 'warn',
    'jsx-a11y/role-has-required-aria-props': 'warn',
    'jsx-a11y/role-supports-aria-props': 'warn',
    'jsx-a11y/scope': 'warn',

    // https://github.com/facebook/react/tree/master/packages/eslint-plugin-react-hooks
    'react-hooks/rules-of-hooks': 'error',

    // https://github.com/gajus/eslint-plugin-flowtype
    'flowtype/define-flow-type': 'warn',
    'flowtype/require-valid-file-annotation': 'warn',
    'flowtype/use-flow-type': 'warn',
  },
};
<|endoftext|>


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

Blockchain = function(blockchainConfig) {
  this.config = blockchainConfig;
}

Blockchain.prototype.generate_basic_command = function() {
  var config = this.config;
  var address = config.account.address;

  var cmd = "geth ";

  if (config.datadir !== "default") {
    cmd += "--datadir=\"" + config.datadir + "\" ";
    cmd += "--logfile=\"" + config.datadir + ".log\" ";
  }

  cmd += "--port " + config.port + " ";
  cmd += "--rpc ";
  cmd += "--rpcport " + config.rpcPort + " ";
  cmd += "--networkid " + config.networkId + " ";
  cmd += "--rpccorsdomain \"" + config.rpcWhitelist + "\" ";

  if (config.minerthreads !== void 0) {
    cmd += "--minerthreads \"" + config.minerthreads + "\" ";
  }

  cmd += "--mine ";
  if (config.genesisBlock !== void 0) {
    cmd += "--genesis=\"" + config.genesisBlock + "\" ";
  }

  //TODO: this should be configurable
  cmd += "--maxpeers " + config.maxPeers + " ";

  if (config.account.password !== void 0) {
    cmd += "--password " + config.account.password + " ";
  }

  return cmd;
}

Blockchain.prototype.list_command = function() {
  return this.generate_basic_command() + "account list ";
}

Blockchain.prototype.init_command = function() {
  return this.generate_basic_command() + "account new ";
}

Blockchain.prototype.run_command = function(address, use_tmp) {
  var cmd = this.generate_basic_command();
  var config = this.config;

  if (address !== void 0) {
    cmd += "--unlock " + address + " ";
  }

  if (config.console_toggle) {
    cmd += "console";
  }

  if (config.mine_when_needed) {
    if (use_tmp) {
      cmd += "js /tmp/js/mine.js";
    }
    else {
      cmd += "js node_modules/embark-framework/js/mine.js";
    }
  }

  return cmd;
}

Blockchain.prototype.get_address = function() {
  var config = this.config;
  var address = null;

  if (config.account.init) {
    // ensure datadir exists, bypassing the interactive liabilities prompt.
    var newDir = mkdirp.sync(config.datadir);
    if (newDir) {
      console.log("=== datadir created");
    } else {
      console.log("=== datadir already exists");
    }

    console.log("running: " + this.list_command());
    result = exec(this.list_command());

    if (result.output.indexOf("Fatal") < 0) {
      console.log("=== already initialized");
      address = result.output.match(/{(\w+)}/)[1];
    } else {
      console.log("running: " + this.init_command());
      result = exec(this.init_command());
      address = result.output.match(/{(\w+)}/)[1];
    }
  }

  return address;
}

Blockchain.prototype.startChain = function(use_tmp) {
  var address = this.get_address();
  console.log("running: " + this.run_command(address, use_tmp));
  exec(this.run_command(address, use_tmp));
}

module.exports = Blockchain
<commit_msg>Allow blockchain rpchost to be configurable<commit_after>var mkdirp = require('mkdirp');

Blockchain = function(blockchainConfig) {
  this.config = blockchainConfig;
}

Blockchain.prototype.generate_basic_command = function() {
  var config = this.config;
  var address = config.account.address;

  var cmd = "geth ";

  if (config.datadir !== "default") {
    cmd += "--datadir=\"" + config.datadir + "\" ";
    cmd += "--logfile=\"" + config.datadir + ".log\" ";
  }

  cmd += "--port " + config.port + " ";
  cmd += "--rpc ";
  cmd += "--rpcport " + config.rpcPort + " ";
  cmd += "--rpcaddr " + config.rpcHost + " ";
  cmd += "--networkid " + config.networkId + " ";
  cmd += "--rpccorsdomain \"" + config.rpcWhitelist + "\" ";

  if (config.minerthreads !== void 0) {
    cmd += "--minerthreads \"" + config.minerthreads + "\" ";
  }

  cmd += "--mine ";
  if (config.genesisBlock !== void 0) {
    cmd += "--genesis=\"" + config.genesisBlock + "\" ";
  }

  //TODO: this should be configurable
  cmd += "--maxpeers " + config.maxPeers + " ";

  if (config.account.password !== void 0) {
    cmd += "--password " + config.account.password + " ";
  }

  return cmd;
}

Blockchain.prototype.list_command = function() {
  return this.generate_basic_command() + "account list ";
}

Blockchain.prototype.init_command = function() {
  return this.generate_basic_command() + "account new ";
}

Blockchain.prototype.run_command = function(address, use_tmp) {
  var cmd = this.generate_basic_command();
  var config = this.config;

  if (address !== void 0) {
    cmd += "--unlock " + address + " ";
  }

  if (config.console_toggle) {
    cmd += "console";
  }

  if (config.mine_when_needed) {
    if (use_tmp) {
      cmd += "js /tmp/js/mine.js";
    }
    else {
      cmd += "js node_modules/embark-framework/js/mine.js";
    }
  }

  return cmd;
}

Blockchain.prototype.get_address = function() {
  var config = this.config;
  var address = null;

  if (config.account.init) {
    // ensure datadir exists, bypassing the interactive liabilities prompt.
    var newDir = mkdirp.sync(config.datadir);
    if (newDir) {
      console.log("=== datadir created");
    } else {
      console.log("=== datadir already exists");
    }

    console.log("running: " + this.list_command());
    result = exec(this.list_command());

    if (result.output.indexOf("Fatal") < 0) {
      console.log("=== already initialized");
      address = result.output.match(/{(\w+)}/)[1];
    } else {
      console.log("running: " + this.init_command());
      result = exec(this.init_command());
      address = result.output.match(/{(\w+)}/)[1];
    }
  }

  return address;
}

Blockchain.prototype.startChain = function(use_tmp) {
  var address = this.get_address();
  console.log("running: " + this.run_command(address, use_tmp));
  exec(this.run_command(address, use_tmp));
}

module.exports = Blockchain
<|endoftext|>


<commit_before>function mistembed(streamname)
{
	// return the current flash version
	function flashVersion()
	{
		var version = 0;

		try
		{
			// check in the mimeTypes
			version = navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin.description.replace(/([^0-9\.])/g, '').split('.')[0];
		}catch(e){}

		try
		{
			// for our special friend IE
			version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable("$version").replace(/([^0-9\,])/g, '').split(',')[0];
		}catch(e){}

		return parseInt(version, 10);
	};

	// what does the browser support - used in hasSupport()
	supports =
	{
		flashversion: flashVersion()
	};

	// return true if a type is supported
	function hasSupport(type)
	{
		switch(type)
		{
			case 'f4v':		return supports.flashversion >= 11;		break;
			case 'rtmp':	return supports.flashversion >= 10;		break;
			case 'flv':		return supports.flashversion >= 7;		break;

			default:			return false;
		}
	};

	// build HTML for certain kinds of types
	function buildPlayer(src, container, videowidth, videoheight)
	{
		// used to recalculate the width/height
      var ratio;

		// get the container's width/height
		var containerwidth = parseInt(container.scrollWidth, 10);
		var containerheight = parseInt(container.scrollHeight, 10);

		if(videowidth > containerwidth && containerwidth > 0)
		{
			ratio = videowidth / containerwidth;

			videowidth /= ratio;
			videoheight /= ratio;
		}

		if(videoheight > containerheight && containerheight > 0)
		{
			ratio = videoheight / containerheight;

			videowidth /= ratio;
			videoheight /= ratio;
		}

		switch(src.type)
		{
			case 'f4v':
			case 'rtmp':
			case 'flv':
         	container.innerHTML = '<object width="' + videowidth + '" height="' + videoheight + '"><param name="movie" value="http://fpdownload.adobe.com/strobe/FlashMediaPlayback.swf"></param><param name="flashvars" value="src=' + encodeURI(src.url) + '&controlBarMode=floating&expandedBufferTime=4&minContinuousPlaybackTime=10"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://fpdownload.adobe.com/strobe/FlashMediaPlayback.swf" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="' + videowidth + '" height="' + videoheight + '" flashvars="src=' + encodeURI(src.url) + '&controlBarMode=floating&expandedBufferTime=4&minContinuousPlaybackTime=10"></embed></object>';
			break;

			case 'fallback':
				container.innerHTML = 'No support for any player found';
			break;
		}

	};

	var video = mistvideo[streamname],
	    container = document.createElement('div'),
		 scripts = document.getElementsByTagName('script'),
		 me = scripts[scripts.length - 1];

	// create the container
	me.parentNode.insertBefore(container, me);
	// set the class to 'mistvideo'
	container.setAttribute('class', 'mistvideo');
	// remove script tag
	me.parentNode.removeChild(me);

	if(video.error)
	{
		// there was an error; display it
		container.innerHTML = ['Error: ', video.error, ''].join('');
	}else if(video.source.length < 1)
	{
		// no stream sources
		container.innerHTML = 'Error: no streams found';
	}else{
		// no error, and sources found. Check the video types and output the best
		// available video player.
		var i, video
			 foundPlayer = false,
			 len = video.source.length;

		for(i = 0; i < len; i++)
		{
			if( hasSupport( video.source[i].type ) )
			{
				// we support this kind of video, so build it.
				buildPlayer(video.source[i], container.parentNode, video.width, video.height);

				// we've build a player, so we're done here
				foundPlayer = true;
				break;   // break for() loop
			}
		}

		if(!foundPlayer)
		{
			// of all the streams given, none was supported (eg. no flash and HTML5 video). Display error
			buildPlayer({type: 'fallback'}, container.parentNode, video.width, video.height);
		}
	}

}
<commit_msg>added HLS and ISM support to embed.js<commit_after>function mistembed(streamname)
{
	// return the current flash version
	function flash_version()
	{
		var version = 0;

		try
		{
			// check in the mimeTypes
			version = navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin.description.replace(/([^0-9\.])/g, '').split('.')[0];
		}catch(e){}
		try
		{
			// for our special friend IE
			version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable("$version").replace(/([^0-9\,])/g, '').split(',')[0];
		}catch(e){}

		return parseInt(version, 10);
	};

	function html5_video_type(type)
	{
		var support = false;

		try
		{
			var v = document.createElement('video');

			if( v && v.canPlayType(type) != "" )
			{
				support = true;
			}
		}catch(e){}

		return support;
	}

	// what does the browser support - used in hasSupport()
	supports =
	{
		flashversion:	flash_version(),
		hls:				html5_video_type('application/vnd.apple.mpegURL'),
		ism:				html5_video_type('application/vnd.ms-ss')
	};

	// return true if a type is supported
	function hasSupport(type)
	{
		switch(type)
		{
			case 'f4v':		return supports.flashversion >= 11;		break;
			case 'rtmp':	return supports.flashversion >= 10;		break;
			case 'flv':		return supports.flashversion >= 7;		break;

			case 'hls':		return supports.hls;							break;
			case 'ism':		return supports.ism;							break;

			default:			return false;
		}
	};

	// build HTML for certain kinds of types
	function buildPlayer(src, container, videowidth, videoheight, vtype)
	{
		// used to recalculate the width/height
      var ratio;

		// get the container's width/height
		var containerwidth = parseInt(container.scrollWidth, 10);
		var containerheight = parseInt(container.scrollHeight, 10);

		if(videowidth > containerwidth && containerwidth > 0)
		{
			ratio = videowidth / containerwidth;

			videowidth /= ratio;
			videoheight /= ratio;
		}

		if(videoheight > containerheight && containerheight > 0)
		{
			ratio = videoheight / containerheight;

			videowidth /= ratio;
			videoheight /= ratio;
		}

		// if the video type is 'live',
		lappend = vtype == 'live' ? "&streamType=live" : "";

		switch(src.type)
		{
			case 'f4v':
			case 'rtmp':
			case 'flv':
         	container.innerHTML = '<object width="' + videowidth + '" height="' + videoheight + '"><param name="movie" value="http://fpdownload.adobe.com/strobe/FlashMediaPlayback.swf"></param><param name="flashvars" value="src=' + encodeURI(src.url) + '&controlBarMode=floating&expandedBufferTime=4&minContinuousPlaybackTime=10' + lappend + '"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://fpdownload.adobe.com/strobe/FlashMediaPlayback.swf" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="' + videowidth + '" height="' + videoheight + '" flashvars="src=' + encodeURI(src.url) + '&controlBarMode=floating&expandedBufferTime=4&minContinuousPlaybackTime=10"></embed></object>';
			break;

			case 'hls':
			case 'ism':
				container.innerHTML = '<video width="' + videowidth + '" height="' + videoheight + '" src="' + encodeURI(src.url) + '" controls="controls" >No HTML5 video support</video>';
			break;

			case 'fallback':
				container.innerHTML = 'No support for any player found';
			break;
		}

	};

	var video = mistvideo[streamname],
	    container = document.createElement('div'),
		 scripts = document.getElementsByTagName('script'),
		 me = scripts[scripts.length - 1];

	// create the container
	me.parentNode.insertBefore(container, me);
	// set the class to 'mistvideo'
	container.setAttribute('class', 'mistvideo');
	// remove script tag
	me.parentNode.removeChild(me);

	if(video.error)
	{
		// there was an error; display it
		container.innerHTML = ['Error: ', video.error, ''].join('');
	}else if(video.source.length < 1)
	{
		// no stream sources
		container.innerHTML = 'Error: no streams found';
	}else{
		// no error, and sources found. Check the video types and output the best
		// available video player.
		var i, video,
          vtype = video.type ? video.type : 'unknown';
			 foundPlayer = false,
			 len = video.source.length;

		for(i = 0; i < len; i++)
		{
			if( hasSupport( video.source[i].type ) )
			{
				// we support this kind of video, so build it.
				buildPlayer(video.source[i], container.parentNode, video.width, video.height, vtype);

				// we've build a player, so we're done here
				foundPlayer = true;
				break;   // break for() loop
			}
		}

		if(!foundPlayer)
		{
			// of all the streams given, none was supported (eg. no flash and HTML5 video). Display error
			buildPlayer({type: 'fallback'}, container.parentNode, video.width, video.height);
		}
	}

}
<|endoftext|>


<commit_before>'use strict';

var globalHooks = require('../../../hooks');
var hooks = require('feathers-hooks');

exports.before = {
  all: [],
  find: [],
  get: [],
  create: [function(hook){
    hook.data.createdAt = hook.data.created;
    hook.data.modifiedAt = hook.data.modified;
  }],
  update: [],
  patch: [],
  remove: []
};

exports.after = {
  all: [],
  find: [],
  get: [],
  create: [],
  update: [],
  patch: [],
  remove: []
};
<commit_msg>create 2 layers after a content is created<commit_after>'use strict';

var globalHooks = require('../../../hooks');
var hooks = require('feathers-hooks');

exports.before = {
  all: [],
  find: [],
  get: [],
  create: [function(hook){
    hook.data.createdAt = hook.data.created;
    hook.data.modifiedAt = hook.data.modified;
  }],
  update: [],
  patch: [],
  remove: []
};

exports.after = {
  all: [],
  find: [],
  get: [],
  create: [function(hook){
    hook.app.service('layers').create({
      name: 'layer 1',
      contentId: hook.data.id
    }).then(function(result){
      return hook.app.service('layers').create({
            name: 'layer 2',
            contentId: hook.data.id
      }).then(function(result){
        return hook;
      })
    }).catch(function(err){
      console.log('erro');
      console.log(err);
    });
  }],
  update: [function(hook){
  }],
  patch: [],
  remove: []
};
<|endoftext|>


<commit_before>import React from "react";
import { storiesOf } from "@storybook/react";
import { action } from "@storybook/addon-actions";
import { withInfo } from "@storybook/addon-info";
import { fontSizes } from "@crave/farmblocks-theme";
import { alignments } from "@crave/farmblocks-tooltip";

import formInput from ".";

const EnhancedInput = formInput(props => React.createElement("input", props));

storiesOf("HOC formInput", module)
  .add("html text input", withInfo()(() => <EnhancedInput type="text" />))
  .add(
    "html text input with label",
    withInfo()(() => (
      <EnhancedInput
        onChange={action("change event")}
        label="Input Label"
        type="text"
      />
    ))
  )
  .add(
    "html text input with input.onChange and input.value ",
    withInfo()(() => (
      <EnhancedInput
        input={{
          onChange: action("input.onChange"),
          value: "input.value"
        }}
        label="Input Label"
        type="text"
      />
    ))
  )
  .add(
    "two html inputs with label",
    withInfo()(() => (

        <EnhancedInput label="Input Label" type="text" />
        <EnhancedInput label="Input Label" type="checkbox" />

    ))
  )
  .add(
    "html text input with label and placeholder",
    withInfo()(() => (
      <EnhancedInput
        placeholder="a placeholder"
        label="Input Label"
        type="text"
      />
    ))
  )
  .add(
    "html text input with label and focused flag",
    withInfo()(() => <EnhancedInput focused label="Input Label" type="text" />)
  )
  .add(
    "invalid input",
    withInfo()(() => (
      <EnhancedInput label="Input Label" type="text" invalid="true" />
    ))
  )
  .add(
    "html disabled input with label",
    withInfo()(() => (

        <EnhancedInput
          disabled
          label="Input Label"
          type="text"
          value="Disabled field"
        />

    ))
  )
  .add(
    "input with fontSize property SMALL",
    withInfo()(() => <EnhancedInput fontSize={fontSizes.SMALL} />)
  )
  .add("html search input", withInfo()(() => <EnhancedInput type="search" />))
  .add(
    "html search input with value",
    withInfo()(() => <EnhancedInput type="search" value="broccoli" />)
  )
  .add(
    "small html search input with value",
    withInfo()(() => (
      <EnhancedInput
        type="search"
        fontSize={fontSizes.SMALL}
        value="broccoli"
      />
    ))
  )
  .add(
    "html search input with custom clear icon",
    withInfo()(() => (
      <EnhancedInput type="search" value="broccoli" clearIcon="wg-close" />
    ))
  )
  .add(
    "html input with clear button",
    withInfo()(() => <EnhancedInput clearable />)
  )
  .add(
    "html text input with combobox role",
    withInfo()(() => (

        <EnhancedInput role="combobox" placeholder="Select value" />

    ))
  )
  .add(
    "disabled html text input with combobox role",
    withInfo()(() => (

        <EnhancedInput role="combobox" disabled placeholder="Select value" />

    ))
  )
  .add(
    "html text input with combobox readonly role",
    withInfo()(() => (

        <EnhancedInput role="combobox" placeholder="Select value" readOnly />

    ))
  )
  .add(
    "html input with leftIcon",
    withInfo()(() => <EnhancedInput leftIcon="wg-order" value="foo bar" />)
  )
  .add(
    "small html input with leftIcon",
    withInfo()(() => (
      <EnhancedInput
        leftIcon="wg-order"
        fontSize={fontSizes.SMALL}
        value="foo bar"
      />
    ))
  )
  .add(
    "with label and more info",
    withInfo()(() => (
      <EnhancedInput
        onChange={action("change event")}
        label="this is a regular label"
        moreInfoContent="this is a more info text"
        moreInfoAlign={alignments.CENTER}
        type="text"
      />
    ))
  );
<commit_msg>docs(hoc-input): add stories for prefix and suffix<commit_after>import React from "react";
import { storiesOf } from "@storybook/react";
import { action } from "@storybook/addon-actions";
import { withInfo } from "@storybook/addon-info";
import { fontSizes } from "@crave/farmblocks-theme";
import { alignments } from "@crave/farmblocks-tooltip";

import formInput from ".";

const EnhancedInput = formInput(props => React.createElement("input", props));

storiesOf("HOC formInput", module)
  .add("html text input", withInfo()(() => <EnhancedInput type="text" />))
  .add(
    "html text input with label",
    withInfo()(() => (
      <EnhancedInput
        onChange={action("change event")}
        label="Input Label"
        type="text"
      />
    ))
  )
  .add(
    "html text input with input.onChange and input.value ",
    withInfo()(() => (
      <EnhancedInput
        input={{
          onChange: action("input.onChange"),
          value: "input.value"
        }}
        label="Input Label"
        type="text"
      />
    ))
  )
  .add(
    "two html inputs with label",
    withInfo()(() => (

        <EnhancedInput label="Input Label" type="text" />
        <EnhancedInput label="Input Label" type="checkbox" />

    ))
  )
  .add(
    "html text input with label and placeholder",
    withInfo()(() => (
      <EnhancedInput
        placeholder="a placeholder"
        label="Input Label"
        type="text"
      />
    ))
  )
  .add(
    "html text input with label and focused flag",
    withInfo()(() => <EnhancedInput focused label="Input Label" type="text" />)
  )
  .add(
    "invalid input",
    withInfo()(() => (
      <EnhancedInput label="Input Label" type="text" invalid="true" />
    ))
  )
  .add(
    "html disabled input with label",
    withInfo()(() => (

        <EnhancedInput
          disabled
          label="Input Label"
          type="text"
          value="Disabled field"
        />

    ))
  )
  .add(
    "input with fontSize property SMALL",
    withInfo()(() => <EnhancedInput fontSize={fontSizes.SMALL} />)
  )
  .add("html search input", withInfo()(() => <EnhancedInput type="search" />))
  .add(
    "html search input with value",
    withInfo()(() => <EnhancedInput type="search" value="broccoli" />)
  )
  .add(
    "small html search input with value",
    withInfo()(() => (
      <EnhancedInput
        type="search"
        fontSize={fontSizes.SMALL}
        value="broccoli"
      />
    ))
  )
  .add(
    "html search input with custom clear icon",
    withInfo()(() => (
      <EnhancedInput type="search" value="broccoli" clearIcon="wg-close" />
    ))
  )
  .add(
    "html input with clear button",
    withInfo()(() => <EnhancedInput clearable />)
  )
  .add(
    "html text input with combobox role",
    withInfo()(() => (

        <EnhancedInput role="combobox" placeholder="Select value" />

    ))
  )
  .add(
    "disabled html text input with combobox role",
    withInfo()(() => (

        <EnhancedInput role="combobox" disabled placeholder="Select value" />

    ))
  )
  .add(
    "html text input with combobox readonly role",
    withInfo()(() => (

        <EnhancedInput role="combobox" placeholder="Select value" readOnly />

    ))
  )
  .add(
    "html input with leftIcon",
    withInfo()(() => <EnhancedInput leftIcon="wg-order" value="foo bar" />)
  )
  .add(
    "small html input with leftIcon",
    withInfo()(() => (
      <EnhancedInput
        leftIcon="wg-order"
        fontSize={fontSizes.SMALL}
        value="foo bar"
      />
    ))
  )
  .add(
    "with label and more info",
    withInfo()(() => (
      <EnhancedInput
        onChange={action("change event")}
        label="this is a regular label"
        moreInfoContent="this is a more info text"
        moreInfoAlign={alignments.CENTER}
        type="text"
      />
    ))
  )
  .add(
    "with prefix",
    withInfo()(() => (

        <EnhancedInput type="text" prefix="$" label="Default" />
        <EnhancedInput
          type="text"
          prefix="$"
          label="Focused on Mount"
          focused
        />
        <EnhancedInput type="text" prefix="$" label="Disabled" disabled />
        <EnhancedInput type="text" prefix="$" label="Invalid" invalid="true" />
        <EnhancedInput type="search" prefix="$" label="Search" />
        <EnhancedInput
          type="text"
          prefix="$"
          label="Small"
          fontSize={fontSizes.SMALL}
        />

    ))
  )
  .add(
    "with suffix",
    withInfo()(() => (

        <EnhancedInput type="text" suffix="CS" label="Default" />
        <EnhancedInput
          type="text"
          suffix="CS"
          label="Focused on Mount"
          focused
        />
        <EnhancedInput type="text" suffix="CS" label="Disabled" disabled />
        <EnhancedInput type="text" suffix="CS" label="Invalid" invalid="true" />
        <EnhancedInput type="search" suffix="CS" label="Search" />
        <EnhancedInput
          type="text"
          suffix="CS"
          label="Small"
          fontSize={fontSizes.SMALL}
        />

    ))
  )

  .add(
    "with prefix and suffix",
    withInfo()(() => (

        <EnhancedInput type="text" prefix="$" suffix="CS" label="Default" />
        <EnhancedInput
          type="text"
          prefix="$"
          suffix="CS"
          label="Focused on Mount"
          focused
        />
        <EnhancedInput
          type="text"
          prefix="$"
          suffix="CS"
          label="Disabled"
          disabled
        />
        <EnhancedInput
          type="text"
          prefix="$"
          suffix="CS"
          label="Invalid"
          invalid="true"
        />
        <EnhancedInput type="search" prefix="$" suffix="CS" label="Search" />
        <EnhancedInput
          type="text"
          prefix="$"
          suffix="CS"
          label="Small"
          fontSize={fontSizes.SMALL}
        />

    ))
  );
<|endoftext|>


<commit_before>import path from 'path';
import dotenv from 'dotenv';
import Config from '../libs/Config';
import * as middlewares from '../middlewares';

dotenv.config();

process.env.NODE_ENV = process.env.NODE_ENV || 'development';

const config = new Config({ envPrefix: 'OORS_SERVER_CONFIG' });

config.add({
  rootDir: '',
  rootURL: config.ref(() => `http://${config.get('hostname')}:${config.get('port')}`),
  isDev: process.env.NODE_ENV === 'development',
  port: 3000,
  hostname: 'localhost',
  modules: {
    'oors.express': {
      middlewares: config.ref(() => [
        middlewares.cors,
        middlewares.useragent,
        middlewares.helmet,
        {
          ...middlewares.morgan,
          params: 'dev',
          enabled: config.get('isDev'),
        },
        {
          ...middlewares.compression,
          enabled: !config.get('isDev'),
        },
        {
          ...middlewares.bodyParserJSON,
          params: { limit: '20mb' },
        },
        middlewares.bodyParserURLEncoded,
        {
          ...middlewares.cookieParser,
          params: {
            secret: 'THIS_IS_MY_SECRET',
          },
          enabled: false,
        },
        {
          ...middlewares.session,
          params: {
            secret: 'THIS_IS_MY_SECRET',
            resave: false,
            saveUninitialized: true,
          },
        },
        middlewares.isMethod,
        middlewares.validationErrorHandler,
        {
          ...middlewares.boomErrorHandler,
          params: {
            isDev: config.get('isDev'),
          },
        },
        {
          ...middlewares.errorHandler,
          params: {
            isDev: config.get('isDev'),
          },
        },
      ]),
    },
    'oors.rad': {
      autoload: {
        services: true,
        methods: true,
      },
    },
    'oors.mongodb': {
      connections: [
        {
          name: 'default',
          url: 'mongodb://localhost:27017/oors',
        },
      ],
      logQueries: config.ref('isDev'),
      migrationsDir: config.ref(() => path.resolve(config.get('rootDir'), './migrations')),
      addTimestamps: true,
      autoloadRepositories: false,
    },
    'oors.user': {
      rootURL: config.ref('rootURL'),
      jwtSecret: 'MY_JWT_SECRET',
      jwtConfig: {
        expiresIn: '1d',
      },
      mockUserMiddlewarePivot: {
        before: 'apolloServer',
      },
      passportMiddlewarePivot: {
        after: 'session',
      },
      jwtMiddlewarePivot: {
        before: 'apolloServer',
      },
      mockUserConfig: {
        enabled: false,
        path: '/graphql',
        params: {}, // no params means an empty query - just load any db user
      },
      passportConfig: {
        enabled: false,
      },
    },
    'oors.mailer': {
      transport: {
        jsonTransport: true,
      },
      saveToDisk: true,
      emailsDir: config.ref(() => path.resolve(config.get('rootDir'), './emails')),
      templatesDir: '',
      middlewarePivot: {
        before: 'isMethod',
      },
    },
    'oors.upload': {
      uploadDir: config.ref(() => path.resolve(config.get('rootDir'), './uploads')),
    },
    'oors.graphql': {
      serverOptions: {
        introspection: config.ref('isDev'),
      },
    },
    'oors.router': {
      middlewarePivot: {
        after: 'isMethod',
      },
    },
    'oors.logger': {
      logsDir: config.ref(() => path.resolve(config.get('rootDir'), './logs')),
    },
    'oors.cache': {
      defaultCache: {
        name: 'cache',
        options: {},
      },
    },
  },
});

export default config;
<commit_msg>better defaults<commit_after>import path from 'path';
import dotenv from 'dotenv';
import Config from '../libs/Config';
import * as middlewares from '../middlewares';

dotenv.config();

process.env.NODE_ENV = process.env.NODE_ENV || 'development';

const config = new Config({ envPrefix: 'OORS_SERVER_CONFIG' });

config.add({
  rootDir: '',
  rootURL: config.ref(() => `http://${config.get('hostname')}:${config.get('port')}`),
  isDev: process.env.NODE_ENV === 'development',
  port: 3000,
  hostname: 'localhost',
  modules: {
    'oors.express': {
      middlewares: config.ref(() => [
        middlewares.cors,
        middlewares.useragent,
        middlewares.helmet,
        {
          ...middlewares.morgan,
          params: 'dev',
          enabled: config.get('isDev'),
        },
        {
          ...middlewares.compression,
          enabled: !config.get('isDev'),
        },
        {
          ...middlewares.bodyParserJSON,
          params: { limit: '20mb' },
        },
        middlewares.bodyParserURLEncoded,
        {
          ...middlewares.cookieParser,
          params: {
            secret: 'THIS_IS_MY_SECRET',
          },
        },
        {
          ...middlewares.session,
          params: {
            secret: 'THIS_IS_MY_SECRET',
            resave: false,
            saveUninitialized: true,
          },
          enabled: false,
        },
        middlewares.isMethod,
        middlewares.validationErrorHandler,
        {
          ...middlewares.boomErrorHandler,
          params: {
            isDev: config.get('isDev'),
          },
        },
        {
          ...middlewares.errorHandler,
          params: {
            isDev: config.get('isDev'),
          },
        },
      ]),
    },
    'oors.rad': {
      autoload: {
        services: true,
        methods: true,
      },
    },
    'oors.mongodb': {
      connections: [
        {
          name: 'default',
          url: 'mongodb://localhost:27017/oors',
        },
      ],
      logQueries: config.ref('isDev'),
      migrationsDir: config.ref(() => path.resolve(config.get('rootDir'), './migrations')),
      addTimestamps: true,
      autoloadRepositories: false,
    },
    'oors.user': {
      rootURL: config.ref('rootURL'),
      jwtSecret: 'MY_JWT_SECRET',
      jwtConfig: {
        expiresIn: '1d',
      },
      mockUserMiddlewarePivot: {
        before: 'apolloServer',
      },
      passportMiddlewarePivot: {
        after: 'cookieParser',
      },
      jwtMiddlewarePivot: {
        before: 'apolloServer',
      },
      mockUserConfig: {
        enabled: false,
        path: '/graphql',
        params: {}, // no params means an empty query - just load any db user
      },
      passportConfig: {
        enabled: false,
      },
    },
    'oors.mailer': {
      transport: {
        jsonTransport: true,
      },
      saveToDisk: true,
      emailsDir: config.ref(() => path.resolve(config.get('rootDir'), './emails')),
      templatesDir: '',
      middlewarePivot: {
        before: 'isMethod',
      },
    },
    'oors.upload': {
      uploadDir: config.ref(() => path.resolve(config.get('rootDir'), './uploads')),
    },
    'oors.graphql': {
      serverOptions: {
        introspection: config.ref('isDev'),
      },
    },
    'oors.router': {
      middlewarePivot: {
        after: 'isMethod',
      },
    },
    'oors.logger': {
      logsDir: config.ref(() => path.resolve(config.get('rootDir'), './logs')),
    },
    'oors.cache': {
      defaultCache: {
        name: 'cache',
        options: {},
      },
    },
  },
});

export default config;
<|endoftext|>


<commit_before>'use strict';

module.exports = require('../text');

require('./_relation');
require('./base');
require('./boolean');
require('./number');
require('./object');
require('./string');
<commit_msg>Add dateTime control to index<commit_after>'use strict';

module.exports = require('../text');

require('./_relation');
require('./base');
require('./boolean');
require('./date-time');
require('./number');
require('./object');
require('./string');
<|endoftext|>


<commit_before>const
// PACKET TYPE
PT_HEAD = 1,
PT_CRED = 2,
PT_BODY = 3,

crypto = require('crypto'),
qs = require('querystring'),
PJSON= require('pico-common').export('pico/json'),
auth = function(head, body, cb){
    if (!body.length) return cb()

    const
    t = head.date,
    dt = Date.now() - t

    if (cullAge && (!t || dt > cullAge || dt < -cullAge)) return cb(`timed error request: api[${head.api}]t[${t}]dt[${dt}]`)

    if (secretKey){
        const hmac = crypto.createHmac('md5', secretKey+t)

        for(let i=0,l=body.length; i<l; i++) hmac.update(body[i]);

        const key = hmac.digest('base64')

        if (key !== head.key) return cb(`key error request: api[${head.api}]t[${t}]key[${key}]`)
    }
    cb()
}

let cullAge, secretKey, sep

module.exports = {
    setup(age, key, delimiter){
        cullAge = age
        secretKey = key
        sep = delimiter
    },
	parseBody(req,cb){
		const body = []

		req.on('data', (chuck)=>{
			body.push(chuck)

			// Too much POST data, kill the connection!
			if (body.length > 128) req.connection.destroy()
		})
		req.on('end', ()=>{
			try{
				const str=Buffer.concat(body).toString()
				switch(req.headers['content-type']){
				case 'application/json': return cb(null, JSON.parse(str))
				case 'application/x-www-form-urlencoded': return cb(null, qs.parse(str))
				default: return cb(null, str)
				}
			}catch(exp){
				cb(exp)
			}
		})
		req.on('error', (err)=>{
			cb(err)
		})
	},
    parse(req, cb){
        const error = function(err){
            req.pause()
            orders = []
            cb(err)
            cb=undefined
        }

        let
        pt = PT_HEAD,
        data = '',
        endPos = 0,
        sepLen = sep.length,
        orders = [],
        remain = '',
        head, cred, body

        req.on('data', (chunk)=>{
            remain += chunk.toString()
            try{
                while(remain){
                    endPos = remain.indexOf(sep)
                    if (-1 === endPos) break
                    switch(pt){
                    case PT_HEAD:
                        head = JSON.parse(remain.substring(0, endPos))
                        orders.push(head)
                        body = []
                        pt = (head.len > 0) ? PT_CRED : PT_HEAD
                        break
					case PT_CRED:
                        head.cred= JSON.parse(remain.substring(0, endPos))
                        pt = (head.len > 1) ? PT_BODY : PT_HEAD
						break
                    case PT_BODY:
                        body.push(remain.substring(0, endPos))
                        if (head.len === body.length+1){
                            pt = PT_HEAD
                            auth(head, body, (err)=>{
                                if (err){
                                    remain = null
                                    return error(err)
                                }
                                head.data = PJSON.parse(body)
                            })
                        }
                        break
                    }
                    remain = remain.substr(endPos+sepLen)
                }
            }catch(exp){
                return error(exp)
            }
        })
        req.on('end', ()=>{
            if (cb) cb(orders.length ? null : 'missing or invalid orders', orders)
        })
    },
    error(query,err){
        // TODO: better error handling
        query = query || {}
        const
        str = JSON.stringify(err),
        t = Date.now(),
        head = secretKey ? {
            api: query.api || '',
            reqId: query.reqId || 0,
            resId: 0,
            len: 0,
            date: t,
            key: crypto.createHmac('md5', secretKey+t).update(str).digest('base64'),
            error:null
        } : {
            api: query.api || '',
            reqId: query.reqId || 0,
            resId: 0,
            len: 0,
            error:null
        }
        return JSON.stringify(head).replace('null',str)+sep
    },
    render(query,data){
        const
        t = Date.now(),
        body = PJSON.stringify(data||{})
        let head

        if(secretKey) {
            const hmac = crypto.createHmac('md5', secretKey+t)
            for(let i=0,l=body.length; i<l; i++) hmac.update(body[i]);
            head = {
                api: query.api,
                reqId: query.reqId,
                resId: 0,
                len: body.length,
                date: t,
                key: hmac.digest('base64')
            }
        }else{
            head = {
                api: query.api,
                reqId: query.reqId,
                resId: 0,
                len: body.length
            }
        }

        return JSON.stringify(head)+sep+body.join(sep)+sep
    }
}
<commit_msg>ignore auth at earlier stage<commit_after>const
// PACKET TYPE
PT_HEAD = 1,
PT_CRED = 2,
PT_BODY = 3,

crypto = require('crypto'),
qs = require('querystring'),
PJSON= require('pico-common').export('pico/json'),
auth = function(head, body, cb){
    if ((!cullAge && !secretKey) || !body.length) return cb()

    const
    t = head.date,
    dt = Date.now() - t

    if (cullAge && (!t || dt > cullAge || dt < -cullAge)) return cb(`timed error request: api[${head.api}]t[${t}]dt[${dt}]`)

    if (secretKey){
        const hmac = crypto.createHmac('md5', secretKey+t)

        for(let i=0,l=body.length; i<l; i++) hmac.update(body[i]);

        const key = hmac.digest('base64')

        if (key !== head.key) return cb(`key error request: api[${head.api}]t[${t}]key[${key}]`)
    }
    cb()
}

let cullAge, secretKey, sep

module.exports = {
    setup(age, key, delimiter){
        cullAge = age
        secretKey = key
        sep = delimiter
    },
	parseBody(req,cb){
		const body = []

		req.on('data', (chuck)=>{
			body.push(chuck)

			// Too much POST data, kill the connection!
			if (body.length > 128) req.connection.destroy()
		})
		req.on('end', ()=>{
			try{
				const str=Buffer.concat(body).toString()
				switch(req.headers['content-type']){
				case 'application/json': return cb(null, JSON.parse(str))
				case 'application/x-www-form-urlencoded': return cb(null, qs.parse(str))
				default: return cb(null, str)
				}
			}catch(exp){
				cb(exp)
			}
		})
		req.on('error', (err)=>{
			cb(err)
		})
	},
    parse(req, cb){
        const error = function(err){
            req.pause()
            orders = []
            cb(err)
            cb=undefined
        }

        let
        pt = PT_HEAD,
        data = '',
        endPos = 0,
        sepLen = sep.length,
        orders = [],
        remain = '',
        head, cred, body

        req.on('data', (chunk)=>{
            remain += chunk.toString()
            try{
                while(remain){
                    endPos = remain.indexOf(sep)
                    if (-1 === endPos) break
                    switch(pt){
                    case PT_HEAD:
                        head = JSON.parse(remain.substring(0, endPos))
                        orders.push(head)
                        body = []
                        pt = (head.len > 0) ? PT_CRED : PT_HEAD
                        break
					case PT_CRED:
                        head.cred= JSON.parse(remain.substring(0, endPos))
                        pt = (head.len > 1) ? PT_BODY : PT_HEAD
						break
                    case PT_BODY:
                        body.push(remain.substring(0, endPos))
                        if (head.len === body.length+1){
                            pt = PT_HEAD
                            auth(head, body, (err)=>{
                                if (err){
                                    remain = null
                                    return error(err)
                                }
                                head.data = PJSON.parse(body)
                            })
                        }
                        break
                    }
                    remain = remain.substr(endPos+sepLen)
                }
            }catch(exp){
                return error(exp)
            }
        })
        req.on('end', ()=>{
            if (cb) cb(orders.length ? null : 'missing or invalid orders', orders)
        })
    },
    error(query,err){
        // TODO: better error handling
        query = query || {}
        const
        str = JSON.stringify(err),
        t = Date.now(),
        head = secretKey ? {
            api: query.api || '',
            reqId: query.reqId || 0,
            resId: 0,
            len: 0,
            date: t,
            key: crypto.createHmac('md5', secretKey+t).update(str).digest('base64'),
            error:null
        } : {
            api: query.api || '',
            reqId: query.reqId || 0,
            resId: 0,
            len: 0,
            error:null
        }
        return JSON.stringify(head).replace('null',str)+sep
    },
    render(query,data){
        const
        t = Date.now(),
        body = PJSON.stringify(data||{})
        let head

        if(secretKey) {
            const hmac = crypto.createHmac('md5', secretKey+t)
            for(let i=0,l=body.length; i<l; i++) hmac.update(body[i]);
            head = {
                api: query.api,
                reqId: query.reqId,
                resId: 0,
                len: body.length,
                date: t,
                key: hmac.digest('base64')
            }
        }else{
            head = {
                api: query.api,
                reqId: query.reqId,
                resId: 0,
                len: body.length
            }
        }

        return JSON.stringify(head)+sep+body.join(sep)+sep
    }
}
<|endoftext|>


<commit_before>LargeLocalStorage.URLCache = (function() {

	function add(cache, path, url) {
		var parts = path.split('/');
	}

	function expunge(cache, path) {

	}

	function expungByUrl(cache, url) {

	}

	function setAttachment(path, blob) {
		expunge(this._cache, path);
		return this._lls.setAttachment(path, blob);
	}

	function rmAttachment(path) {
		expunge(this._cache, path);
		return this._lls.rmAttachment(path);
	}

	function rm(path) {
		delete this._cache[path];
		return this._lls.rm(path);
	}

	function revokeAttachmentURL(url) {
		expungByUrl(this._cache, url);
		return this._lls.revokeAttachmentURL(url);
	}

	function getAttachmentURL(path) {
		var promise = this._lls.getAttachmentURL(path);
		promise.then(function(url) {
			add(this._cache, path, url);
		});

		return promise;
	}

	function getAllAttachmentURLs(path) {
		var promise = this._lls.getAllAttachmentURLs(path);
		promise.then(function(urls) {
			// TODO: the return will have to be a urls,paths pair...
			addAll(this._cache, path, urls);
		});

		return promise;
	}

	return {
		apply: function(lls) {
			var obj = {};

			obj._lls = lls;
			obj._cache = {};

			lls.setAttachment = setAttachment.bind(obj);
			lls.rmAttachment = rmAttachment.bind(obj);
			lls.rm = rm.bind(obj);
			lls.revokeAttachmentURL = revokeAttachmentURL.bind(obj);
			lls.getAttachmentURL = getAttachmentURL.bind(obj);
			lls.getAllAttachmentURLs = getAllAttachmentURLs.bind(obj);

			return lls;
		}
	}
});<commit_msg>URL cache<commit_after>LargeLocalStorage.URLCache = (function() {

	function add(cache, docKey, attachKey, url) {
		var mainCache = cache.main;
		var docCache = mainCache[docKey];
		if (!docCache) {
			docCache = {};
			mainCache[docKey] = docCache;
		}

		mainCache[attachKey] = url;
		cache.reverse[url] = {docKey: docKey, attachKey: attachKey};
	}

	function addAll(cache, urlEntries) {
		for (var i = 0; i < urlEntries.length; ++i) {
			add(cache, entry.docKey, entry.attachKey, entry.url);
		}
	}

	function expunge(cache, docKey, attachKey) {
		if (attachKey) {
			var docCache = cache.main[docKey];
			if (docCache) {
				var url = docCache[attachKey];
				delete docCache[attachKey];
				delete cache.reverse[url];
			}
		} else {
			var docCache = cache.main[docKey];
			if (docCache) {
				for (var attachKey in docCache) {
					var url = docCache[attachKey];
					delete docCache[attachKey];
					delete cache.reverse[url];
				}
			}
		}
	}

	function expungByUrl(cache, url) {
		var keys = cache.reverse[url];
		if (keys) {
			expunge(cache, keys.docKey, keys.attachKey);
		}
	}

	function setAttachment(docKey, attachKey, blob) {
		expunge(this._cache, docKey, attachKey);
		return this._lls.setAttachment(path, blob);
	}

	function rmAttachment(docKey, attachKey) {
		expunge(this._cache, docKey, attachKey);
		return this._lls.rmAttachment(docKey, attachKey);
	}

	function rm(docKey) {
		expunge(this._cache, docKey);
		return this._lls.rm(docKey);
	}

	function revokeAttachmentURL(url) {
		expungByUrl(this._cache, url);
		return this._lls.revokeAttachmentURL(url);
	}

	function getAttachmentURL(docKey, attachKey) {
		var promise = this._lls.getAttachmentURL(docKey, attachKey);
		promise.then(function(url) {
			add(this._cache, docKey, attachKey, url);
		});

		return promise;
	}

	function getAllAttachmentURLs(docKey) {
		var promise = this._lls.getAllAttachmentURLs(docKey);
		promise.then(function(urls) {
			// TODO: the return will have to be a urls,paths pair...
			addAll(this._cache, urls);
		});

		return promise;
	}

	return {
		apply: function(lls) {
			var obj = {};

			obj._lls = lls;
			obj._cache = {};

			lls.setAttachment = setAttachment.bind(obj);
			lls.rmAttachment = rmAttachment.bind(obj);
			lls.rm = rm.bind(obj);
			lls.revokeAttachmentURL = revokeAttachmentURL.bind(obj);
			lls.getAttachmentURL = getAttachmentURL.bind(obj);
			lls.getAllAttachmentURLs = getAllAttachmentURLs.bind(obj);

			return lls;
		}
	}
});<|endoftext|>