commit f34a02708128bbce55fc4dc911f3702547968b34 Author: coldstar Date: Sun May 23 14:48:26 2021 -0700 first commit diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..00cbbdf --- /dev/null +++ b/.gitignore @@ -0,0 +1,59 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..1fcc40b --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Dan Janosik + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100755 index 0000000..0716bce --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ + +Simple, stateless Vivocoin blockchain explorer, via RPC. Built with Node.js, express, bootstrap-v4. + +This tool is intended to be a simple, stateless, self-hosted explorer for the Vivocoin blockchain, driven by RPC calls to your own smartcashd node. This tool is easy to run but lacks features compared to full-fledged (stateful) explorers. + +I built this tool because I wanted to use it myself. Whatever reasons one might have for running a full node (trustlessness, technical curiosity, etc) it's helpful to appreciate the "fullness" of a node. + +# Features + +* List of recent blocks +* Browse blocks by height, in ascending or descending order +* View block details +* View transaction details, with navigation backward via spent outputs +* View raw JSON output used to generate most pages +* Mempool/unconfirmed transaction counts by fee (sat/B) diff --git a/app.js b/app.js new file mode 100755 index 0000000..c79d4aa --- /dev/null +++ b/app.js @@ -0,0 +1,131 @@ +#!/usr/bin/env node + +'use strict'; + +var express = require('express'); +var path = require('path'); +var favicon = require('serve-favicon'); +var logger = require('morgan'); +var cookieParser = require('cookie-parser'); +var bodyParser = require('body-parser'); +var session = require("express-session"); +var env = require("./app/env.js"); +var simpleGit = require('simple-git'); +var utils = require("./app/utils.js"); +var moment = require("moment"); +var Decimal = require('decimal.js'); +var bitcoin = require("bitcoin"); +var momentDurationFormat = require("moment-duration-format"); + + +var baseActionsRouter = require('./routes/baseActionsRouter'); + +var app = express(); + +// view engine setup +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'pug'); + +// uncomment after placing your favicon in /public +//app.use(favicon(__dirname + '/public/favicon.ico')); +app.use(logger('dev')); +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: false })); +app.use(cookieParser()); +app.use(session({ + secret: env.cookiePassword, + resave: false, + saveUninitialized: false +})); +app.use(express.static(path.join(__dirname, 'public'))); + + +// Make our db accessible to our router +app.use(function(req, res, next) { + // make session available in templates + res.locals.session = req.session; + res.locals.debug = env.debug; + + if (env.smartcashd && env.smartcashd.rpc) { + req.session.host = env.smartcashd.host; + req.session.port = env.smartcashd.port; + req.session.username = env.smartcashd.rpc.username; + + global.client = new bitcoin.Client({ + host: env.smartcashd.host, + port: env.smartcashd.port, + user: env.smartcashd.rpc.username, + pass: env.smartcashd.rpc.password, + timeout: 5000 + }); + } + + res.locals.host = req.session.host; + res.locals.port = req.session.port; + +/* if (!["/", "/connect"].includes(req.originalUrl)) { + if (utils.redirectToConnectPageIfNeeded(req, res)) { + return; + } + } +*/ + if (req.session.userMessage) { + res.locals.userMessage = req.session.userMessage; + + if (req.session.userMessageType) { + res.locals.userMessageType = req.session.userMessageType; + + } else { + res.locals.userMessageType = "info"; + } + } + + req.session.userMessage = null; + req.session.userMessageType = null; + + // make some var available to all request + // ex: req.cheeseStr = "cheese"; + + next(); +}); + +app.use('/', baseActionsRouter); + +/// catch 404 and forwarding to error handler +app.use(function(req, res, next) { + var err = new Error('Not Found'); + err.status = 404; + next(err); +}); + +/// error handlers + +// development error handler +// will print stacktrace +if (app.get('env') === 'development') { + app.use(function(err, req, res, next) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: err + }); + }); +} + +// production error handler +// no stacktraces leaked to user +app.use(function(err, req, res, next) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: {} + }); +}); + +app.locals.moment = moment; +app.locals.Decimal = Decimal; +app.locals.utils = utils; + + + +module.exports = app; diff --git a/app/env.js b/app/env.js new file mode 100755 index 0000000..8feeaac --- /dev/null +++ b/app/env.js @@ -0,0 +1,16 @@ +module.exports = { + cookiePassword: "0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f", + debug: false, + + // Uncomment "smartcashd" below to automatically connect via RPC. + // Otherwise, you can manually connect via the UI. + + smartcashd:{ + host:"127.0.0.1", + port:5567, + rpc: { + username:"vivorpc", + password:"c46d58eb99da24bb0392875f" + } + } +}; diff --git a/app/rpcApi.js b/app/rpcApi.js new file mode 100755 index 0000000..ab8b83f --- /dev/null +++ b/app/rpcApi.js @@ -0,0 +1,446 @@ + +var fs = require('fs'); +var stream = fs.createWriteStream("proglog.txt"); +var utils = require("./utils.js"); + + + +var genesisCoinbaseTransactionTxid = "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"; +var genesisCoinbaseTransaction = { + "hex": "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d02fd04ffffffff0100f2052a01000000434104f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446aac00000000", + "txid": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b", + "hash": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b", + "size": 204, + "vsize": 204, + "version": 1, + "confirmations":475000, + "vin": [ + { + "coinbase": "04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73", + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 50, + "n": 0, + "scriptPubKey": { + "asm": "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a OP_CHECKSIG", + "hex": "4104f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446aac", + "reqSigs": 1, + "type": "pubkey", + "addresses": [ + "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa" + ] + } + } + ], + "blockhash": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f", + "time": 1230988505, + "blocktime": 1230988505 +}; + +function getInfo() { + return new Promise(function(resolve, reject) { + client.cmd('getinfo', function(err, result, resHeaders) { + if (err) { + console.log("Error 3207fh0f: " + err); + + reject(err); + + return; + } + + resolve(result); + }); + }); +} + +function getMiningInfo() { + return new Promise(function(resolve, reject) { + client.cmd('getmininginfo', function(err, result, resHeaders) { + if (err) { + console.log("Error 3207fh0f: " + err); + + reject(err); + + return; + } + + resolve(result); + }); + }); +} + +function getMempoolInfo() { + return new Promise(function(resolve, reject) { + client.cmd('getmempoolinfo', function(err, result, resHeaders) { + if (err) { + console.log("Error 23407rhwe07fg: " + err); + + reject(err); + + return; + } + + resolve(result); + }); + }); +} + +function getMempoolStats() { + return new Promise(function(resolve, reject) { + client.cmd('getrawmempool', true, function(err, result, resHeaders) { + if (err) { + console.log("Error 428thwre0ufg: " + err); + + reject(err); + + return; + } + + var compiledResult = {}; + compiledResult.count = 0; + compiledResult.fee_0_5 = 0; + compiledResult.fee_6_10 = 0; + compiledResult.fee_11_25 = 0; + compiledResult.fee_26_50 = 0; + compiledResult.fee_51_75 = 0; + compiledResult.fee_76_100 = 0; + compiledResult.fee_101_150 = 0; + compiledResult.fee_151_max = 0; + + var totalFee = 0; + for (var txid in result) { + var txMempoolInfo = result[txid]; + totalFee += txMempoolInfo.modifiedfee; + var feeRate = Math.round(txMempoolInfo.modifiedfee * 100000000 / txMempoolInfo.size); + + if (feeRate <= 5) { + compiledResult.fee_0_5++; + + } else if (feeRate <= 10) { + compiledResult.fee_6_10++; + + } else if (feeRate <= 25) { + compiledResult.fee_11_25++; + + } else if (feeRate <= 50) { + compiledResult.fee_26_50++; + + } else if (feeRate <= 75) { + compiledResult.fee_51_75++; + + } else if (feeRate <= 100) { + compiledResult.fee_76_100++; + + } else if (feeRate <= 150) { + compiledResult.fee_101_150++; + + } else { + compiledResult.fee_151_max++; + } + + compiledResult.count++; + } + + compiledResult.totalFee = totalFee; + + resolve(compiledResult); + }); + }); +} + + +function getBlockByHeight(blockHeight) { + console.log("getBlockByHeightzz: " + blockHeight); + console.log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxx \n"); +//************************************************************************************* + +stream.write('block:'+blockHeight); + + + return new Promise(function(resolve, reject) { + var client = global.client; + + client.cmd('getblockhash', blockHeight, function(err, result, resHeaders) { + if (err) { + console.log("Error 0928317yr3w: " + err); + + reject(err); + + return; + } + + client.cmd('getblock', result, function(err2, result2, resHeaders2) { + if (err2) { + console.log("Error 320fh7e0hg: " + err2); + + reject(err2); + + return; + } + + resolve({ success:true, getblockhash:result, getblock:result2 }); + }); + }); + }); +} + + + +function getBlocksByHeight(blockHeights) { + console.log("getBlocksByHeight: " + blockHeights); + + + console.log("getBlockByHeightzz: " + blockHeights); + console.log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxx \n"); +//************************************************************************************* + +stream.write('block:'+blockHeights+"\n"); + + + + return new Promise(function(resolve, reject) { + var batch = []; + for (var i = 0; i < blockHeights.length; i++) { + batch.push({ + method: 'getblockhash', + params: [ blockHeights[i] ] + }); + } + + var blockHashes = []; + client.cmd(batch, function(err, result, resHeaders) { + blockHashes.push(result); + + if (blockHashes.length == batch.length) { + var batch2 = []; + for (var i = 0; i < blockHashes.length; i++) { + batch2.push({ + method: 'getblock', + params: [ blockHashes[i] ] + }); + } + + var blocks = []; + client.cmd(batch2, function(err2, result2, resHeaders2) { + if (err2) { + console.log("Error 138ryweufdf: " + err2); + } + + blocks.push(result2); + if (blocks.length == batch2.length) { + resolve(blocks); + } + }); + } + }); + }); +} + +function getBlockByHash(blockHash) { + console.log("getBlockByHash: " + blockHash); + + return new Promise(function(resolve, reject) { + var client = global.client; + + client.cmd('getblock', blockHash, function(err, result, resHeaders) { + if (err) { + console.log("Error 0u2fgewue: " + err); + + reject(err); + + return; + } + + resolve(result); + }); + }); +} + +function getTransactionInputs(rpcClient, transaction, inputLimit=0) { + console.log("getTransactionInputs: " + transaction.txid); + + return new Promise(function(resolve, reject) { + var txids = []; + for (var i = 0; i < transaction.vin.length; i++) { + if (i < inputLimit || inputLimit == 0) { + txids.push(transaction.vin[i].txid); + } + } + + getRawTransactions(txids).then(function(inputTransactions) { + resolve({ txid:transaction.txid, inputTransactions:inputTransactions }); + }); + }); +} + +function getRawTransaction(txid) { + return new Promise(function(resolve, reject) { + if (txid == genesisCoinbaseTransactionTxid) { + getBlockByHeight(0).then(function(blockZeroResult) { + var result = genesisCoinbaseTransaction; + result.confirmations = blockZeroResult.getblock.confirmations; + + resolve(result); + }); + + return; + } + + client.cmd('getrawtransaction', txid, 1, function(err, result, resHeaders) { + if (err) { + console.log("Error 329813yre823: " + err); + + reject(err); + + return; + } + + resolve(result); + }); + }); +} + +function getRawTransactions(txids) { + console.log("getRawTransactions: " + txids); + + return new Promise(function(resolve, reject) { + if (!txids || txids.length == 0) { + resolve([]); + + return; + } + + if (txids.length == 1 && txids[0] == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b") { + // copy the "confirmations" field from genesis block to the genesis-coinbase tx + getBlockByHeight(0).then(function(blockZeroResult) { + var result = genesisCoinbaseTransaction; + result.confirmations = blockZeroResult.getblock.confirmations; + + resolve([result]); + + }).catch(function(err) { + reject(err); + + return; + }); + + return; + } + + var requests = []; + for (var i = 0; i < txids.length; i++) { + var txid = txids[i]; + + if (txid) { + requests.push({ + method: 'getrawtransaction', + params: [ txid, 1 ] + }); + } + } + + var requestBatches = utils.splitArrayIntoChunks(requests, 20); + + executeBatchesSequentially(requestBatches, function(results) { + resolve(results); + }); + }); +} + +function executeBatchesSequentially(batches, resultFunc) { + var batchId = utils.getRandomString(20, 'aA#'); + + console.log("Starting " + batches.length + "-item batch " + batchId + "..."); + + executeBatchesSequentiallyInternal(batchId, batches, 0, [], resultFunc); +} + +function executeBatchesSequentiallyInternal(batchId, batches, currentIndex, accumulatedResults, resultFunc) { + if (currentIndex == batches.length) { + console.log("Finishing batch " + batchId + "..."); + + resultFunc(accumulatedResults); + + return; + } + + console.log("Executing item #" + (currentIndex + 1) + " (of " + batches.length + ") for batch " + batchId); + + var count = batches[currentIndex].length; + + client.cmd(batches[currentIndex], function(err, result, resHeaders) { + if (err) { + console.log("Error f83024hf4: " + err); + } + + accumulatedResults.push(result); + + count--; + + if (count == 0) { + executeBatchesSequentiallyInternal(batchId, batches, currentIndex + 1, accumulatedResults, resultFunc); + } + }); +} + +function getBlockData(rpcClient, blockHash, txLimit, txOffset) { + console.log("getBlockData: " + blockHash); + + return new Promise(function(resolve, reject) { + client.cmd('getblock', blockHash, function(err2, result2, resHeaders2) { + if (err2) { + console.log("Error 3017hfwe0f: " + err2); + + reject(err2); + + return; + } + + var txids = []; + for (var i = txOffset; i < Math.min(txOffset + txLimit, result2.tx.length); i++) { + txids.push(result2.tx[i]); + } + + getRawTransactions(txids).then(function(transactions) { + var txInputsByTransaction = {}; + + var promises = []; + for (var i = 0; i < transactions.length; i++) { + var transaction = transactions[i]; + + if (transaction) { + promises.push(getTransactionInputs(client, transaction, 10)); + } + } + + Promise.all(promises).then(function() { + var results = arguments[0]; + for (var i = 0; i < results.length; i++) { + var resultX = results[i]; + + txInputsByTransaction[resultX.txid] = resultX.inputTransactions; + } + + resolve({ getblock:result2, transactions:transactions, txInputsByTransaction:txInputsByTransaction }); + }); + }); + }); + }); +} + +module.exports = { + getInfo: getInfo, + getMiningInfo: getMiningInfo, + getMempoolInfo: getMempoolInfo, + getBlockByHeight: getBlockByHeight, + getBlocksByHeight: getBlocksByHeight, + getBlockByHash: getBlockByHash, + getTransactionInputs: getTransactionInputs, + getBlockData: getBlockData, + getRawTransaction: getRawTransaction, + getRawTransactions: getRawTransactions, + getMempoolStats: getMempoolStats +}; \ No newline at end of file diff --git a/app/utils.js b/app/utils.js new file mode 100755 index 0000000..4c9bd5e --- /dev/null +++ b/app/utils.js @@ -0,0 +1,103 @@ + + +var Decimal = require("decimal.js"); +Decimal8 = Decimal.clone({ precision:8, rounding:8 }); + +function doSmartRedirect(req, res, defaultUrl) { + if (req.session.redirectUrl) { + res.redirect(req.session.redirectUrl); + req.session.redirectUrl = null; + + } else { + res.redirect(defaultUrl); + } + + res.end(); +} + +function redirectToConnectPageIfNeeded(req, res) { + if (!req.session.host) { + req.session.redirectUrl = req.originalUrl; + + res.redirect("/"); + res.end(); + + return true; + } + + return false; +} + +function hex2ascii(hex) { + var str = ""; + for (var i = 0; i < hex.length; i += 2) { + str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); + } + + return str; +} + +function getBlockReward(blockHeight) { + + var nSubsidy = 10 * 100000000; + var prevBlock = blockHeight -1; + + // yearly decline of production by 10% per year, projected 136m coins max by year 2050+. + + var i =0; + + for (i = 262800; i <= prevBlock ; i += 262800 ) { + + nSubsidy -= nSubsidy/10; + + } + + return nSubsidy/100000000; +} + +function splitArrayIntoChunks(array, chunkSize) { + var j = array.length; + var chunks = []; + + for (var i = 0; i < j; i += chunkSize) { + chunks.push(array.slice(i, i + chunkSize)); + } + + return chunks; +} + +function getRandomString(length, chars) { + var mask = ''; + + if (chars.indexOf('a') > -1) { + mask += 'abcdefghijklmnopqrstuvwxyz'; + } + + if (chars.indexOf('A') > -1) { + mask += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + } + + if (chars.indexOf('#') > -1) { + mask += '0123456789'; + } + + if (chars.indexOf('!') > -1) { + mask += '~`!@#$%^&*()_+-={}[]:";\'<>?,./|\\'; + } + + var result = ''; + for (var i = length; i > 0; --i) { + result += mask[Math.floor(Math.random() * mask.length)]; + } + + return result; +} + +module.exports = { + doSmartRedirect: doSmartRedirect, + redirectToConnectPageIfNeeded: redirectToConnectPageIfNeeded, + hex2ascii: hex2ascii, + getBlockReward: getBlockReward, + splitArrayIntoChunks: splitArrayIntoChunks, + getRandomString: getRandomString +}; diff --git a/bin/www b/bin/www new file mode 100755 index 0000000..2f01f1b --- /dev/null +++ b/bin/www @@ -0,0 +1,31 @@ +#!/usr/bin/env node +var debug = require('debug')('my-application'); +var app = require('../app'); +var http = require('http'); +var https = require('https'); +var fs = require('fs'); + +// Https run +/* +const httpsOptions = { + cert: fs.readFileSync('/etc/letsencrypt/live/rpcexplorer.smartcash.cc/fullchain.pem'), + key: fs.readFileSync('/etc/letsencrypt/live/rpcexplorer.smartcash.cc/privkey.pem') +} + +https.createServer(httpsOptions, app).listen(443, function() { + debug('Https/Express server listening on port 443'); +}); + +// Forwarding http to https +http.createServer(function (req, res) { + res.writeHead(301, { "Location": "https://" + req.headers['host'] + req.url }); + res.end(); +}).listen(80); +*/ + +// Http run +app.set('port', process.env.PORT || 80); +var server = app.listen(app.get('port'), function() { + debug('Express server listening on port ' + server.address().port); +}); + diff --git a/docs/Server-Setup.md b/docs/Server-Setup.md new file mode 100755 index 0000000..7260a46 --- /dev/null +++ b/docs/Server-Setup.md @@ -0,0 +1,22 @@ +### Setup of https://btc-explorer.com on Ubuntu 16.04 + + apt update + apt upgrade + apt install git python-software-properties software-properties-common nginx + curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - + npm install pm2 --global + add-apt-repository ppa:certbot/certbot + apt update + apt upgrade + apt install python-certbot-nginx + +Copy content from [./btc-explorer.com.conf](./btc-explorer.com.conf) into `/etc/nginx/sites-available/btc-explorer.com.conf` + + certbot --nginx -d btc-explorer.com + cd /etc/ssl/certs + openssl dhparam -out dhparam.pem 4096 + cd /home/bitcoin + git clone https://github.com/janoside/btc-rpc-explorer.git + cd /home/bitcoin/btc-rpc-explorer + npm install + pm2 start bin/www --name "btc-rpc-explorer" diff --git a/docs/btc-explorer.com.conf b/docs/btc-explorer.com.conf new file mode 100755 index 0000000..66f1277 --- /dev/null +++ b/docs/btc-explorer.com.conf @@ -0,0 +1,32 @@ +## http://domain.com redirects to https://domain.com +server { + server_name btc-explorer.com; + listen 80; + #listen [::]:80 ipv6only=on; + + location / { + return 301 https://btc-explorer.com$request_uri; + } +} + +## Serves httpS://domain.com +server { + server_name btc-explorer.com; + listen 443 ssl http2; + #listen [::]:443 ssl http2 ipv6only=on; + + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_dhparam /etc/ssl/certs/dhparam.pem; + + location / { + proxy_pass http://localhost:3002; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100755 index 0000000..8ade94b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2766 @@ +{ + "name": "rpc-explorer", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bitcoin": "3.0.1", + "body-parser": "~1.16.0", + "cookie-parser": "~1.4.3", + "crypto-js": "3.1.9-1", + "debug": "~2.6.0", + "decimal.js": "7.2.3", + "express": "~4.14.1", + "express-session": "1.15.2", + "jstransformer-markdown-it": "^2.0.0", + "moment": "^2.18.1", + "moment-duration-format": "1.3.0", + "monk": "^4.0.0", + "morgan": "~1.7.0", + "pug": "2.0.0-rc.2", + "serve-favicon": "~2.3.2", + "simple-git": "1.73.0" + } + }, + "node_modules/@types/babel-types": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.9.tgz", + "integrity": "sha512-qZLoYeXSTgQuK1h7QQS16hqLGdmqtRmN8w/rl3Au/l5x/zkHx+a4VHrHyBsi1I1vtK2oBHxSzKIu0R5p6spdOA==" + }, + "node_modules/@types/babylon": { + "version": "6.16.5", + "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.5.tgz", + "integrity": "sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w==", + "dependencies": { + "@types/babel-types": "*" + } + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", + "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=", + "dependencies": { + "acorn": "^4.0.4" + } + }, + "node_modules/align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dependencies": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dependencies": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "node_modules/babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "bin": { + "babylon": "bin/babylon.js" + } + }, + "node_modules/basic-auth": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", + "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/bitcoin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/bitcoin/-/bitcoin-3.0.1.tgz", + "integrity": "sha1-/54LYqcbu4rd2zTuLkJ9rCHBCW8=", + "deprecated": "Use npmjs.com/bitcoin-core instead as this package is no longer maintained.", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/body-parser": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.16.1.tgz", + "integrity": "sha1-UVQNBFrfp6DGmVoBS7ax7ZuAIyk=", + "dependencies": { + "bytes": "2.4.0", + "content-type": "~1.0.2", + "debug": "2.6.1", + "depd": "~1.1.0", + "http-errors": "~1.5.1", + "iconv-lite": "0.4.15", + "on-finished": "~2.3.0", + "qs": "6.2.1", + "raw-body": "~2.2.0", + "type-is": "~1.6.14" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.1.tgz", + "integrity": "sha1-eYVQkLosTjEVzH2HaUkdWPBJE1E=", + "dependencies": { + "ms": "0.7.2" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + }, + "node_modules/bson": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz", + "integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg==", + "deprecated": "Fixed a critical issue with BSON serialization documented in CVE-2019-2391, see https://bit.ly/2KcpXdo for more details", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" + }, + "node_modules/bytes": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=" + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dependencies": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/character-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", + "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=", + "dependencies": { + "is-regex": "^1.0.3" + } + }, + "node_modules/clean-css": { + "version": "3.4.28", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", + "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", + "dependencies": { + "commander": "2.8.x", + "source-map": "0.4.x" + }, + "bin": { + "cleancss": "bin/cleancss" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dependencies": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "node_modules/commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "dependencies": { + "graceful-readlink": ">= 1.0.0" + }, + "engines": { + "node": ">= 0.6.x" + } + }, + "node_modules/constantinople": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.2.tgz", + "integrity": "sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw==", + "dependencies": { + "@types/babel-types": "^7.0.0", + "@types/babylon": "^6.16.2", + "babel-types": "^6.26.0", + "babylon": "^6.18.0" + } + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz", + "integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==", + "dependencies": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.", + "hasInstallScript": true + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz", + "integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms=" + }, + "node_modules/crypto-js": { + "version": "3.1.9-1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz", + "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decimal.js": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-7.2.3.tgz", + "integrity": "sha512-AoFI37QS0S87Ft0r3Bdz4q9xSpm1Paa9lSeKLXgMPk/u/+QPIM5Gy4DHcZQS1seqPJH4gHLauPGn347z0HbsrA==" + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/doctypes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", + "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "node_modules/es6-promise": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", + "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.14.1.tgz", + "integrity": "sha1-ZGwjf3ZvFIwhIK/wc4F7nk1+DTM=", + "dependencies": { + "accepts": "~1.3.3", + "array-flatten": "1.1.1", + "content-disposition": "0.5.2", + "content-type": "~1.0.2", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "~2.2.0", + "depd": "~1.1.0", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "etag": "~1.7.0", + "finalhandler": "0.5.1", + "fresh": "0.3.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.1", + "path-to-regexp": "0.1.7", + "proxy-addr": "~1.1.3", + "qs": "6.2.0", + "range-parser": "~1.2.0", + "send": "0.14.2", + "serve-static": "~1.11.2", + "type-is": "~1.6.14", + "utils-merge": "1.0.0", + "vary": "~1.1.0" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-session": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.2.tgz", + "integrity": "sha1-2YUWRDpMy4aI4XJa5YTALapAk9Q=", + "dependencies": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "crc": "3.4.4", + "debug": "2.6.3", + "depd": "~1.1.0", + "on-headers": "~1.0.1", + "parseurl": "~1.3.1", + "uid-safe": "~2.1.4", + "utils-merge": "1.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session/node_modules/debug": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.3.tgz", + "integrity": "sha1-D364wwll7AjHKsz6ATDIt5mEFB0=", + "dependencies": { + "ms": "0.7.2" + } + }, + "node_modules/express-session/node_modules/ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + }, + "node_modules/express/node_modules/cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dependencies": { + "ms": "0.7.1" + } + }, + "node_modules/express/node_modules/ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + }, + "node_modules/express/node_modules/qs": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz", + "integrity": "sha1-O3hIwDwt7OaalSKw+ujEEm10Xzs=", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/finalhandler": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.1.tgz", + "integrity": "sha1-LEANjUUwk1vCMlScX6OF7Afeb80=", + "dependencies": { + "debug": "~2.2.0", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dependencies": { + "ms": "0.7.1" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + }, + "node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gitbook-plugin-github": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gitbook-plugin-github/-/gitbook-plugin-github-2.0.0.tgz", + "integrity": "sha1-UWbnY8/MQC1DKIC3pshcHFS1ao0=", + "engines": { + "gitbook": ">=2.5.0" + } + }, + "node_modules/graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-errors": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz", + "integrity": "sha1-eIwNLB3iyBuebowBhDtrl+uSB1A=", + "dependencies": { + "inherits": "2.0.3", + "setprototypeof": "1.0.2", + "statuses": ">= 1.3.1 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/ipaddr.js": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", + "integrity": "sha1-KWrKh4qCGBbluF0KKFqZvP9FgvA=", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-expression": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz", + "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=", + "dependencies": { + "acorn": "~4.0.2", + "object-assign": "^4.0.1" + } + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "node_modules/is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "dependencies": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/js-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", + "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=" + }, + "node_modules/jstransformer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", + "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=", + "dependencies": { + "is-promise": "^2.0.0", + "promise": "^7.0.1" + } + }, + "node_modules/jstransformer-markdown-it": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/jstransformer-markdown-it/-/jstransformer-markdown-it-2.1.0.tgz", + "integrity": "sha1-aewwzkUYvtWZezjwJ2SOjChekvc=", + "dependencies": { + "markdown-it": "^8.0.0" + }, + "engines": { + "node": ">=7" + } + }, + "node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/markdown-it": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", + "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", + "dependencies": { + "argparse": "^1.0.7", + "entities": "~1.1.1", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", + "bin": { + "mime": "cli.js" + } + }, + "node_modules/mime-db": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "dependencies": { + "mime-db": "1.47.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-duration-format": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/moment-duration-format/-/moment-duration-format-1.3.0.tgz", + "integrity": "sha1-VBdxtfh6BJzGVUBHXTrZZnN9aQg=" + }, + "node_modules/mongodb": { + "version": "2.2.36", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.36.tgz", + "integrity": "sha512-P2SBLQ8Z0PVx71ngoXwo12+FiSfbNfGOClAao03/bant5DgLNkOPAck5IaJcEk4gKlQhDEURzfR3xuBG1/B+IA==", + "dependencies": { + "es6-promise": "3.2.1", + "mongodb-core": "2.1.20", + "readable-stream": "2.2.7" + }, + "engines": { + "node": ">=0.10.3" + } + }, + "node_modules/mongodb-core": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.20.tgz", + "integrity": "sha512-IN57CX5/Q1bhDq6ShAR6gIv4koFsZP7L8WOK1S0lR0pVDQaScffSMV5jxubLsmZ7J+UdqmykKw4r9hG3XQEGgQ==", + "dependencies": { + "bson": "~1.0.4", + "require_optional": "~1.0.0" + } + }, + "node_modules/monk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/monk/-/monk-4.1.0.tgz", + "integrity": "sha1-x+VA6GquaQ1xLD4KtwYa2LpaOio=", + "dependencies": { + "debug": "*", + "gitbook-plugin-github": "2.0.0", + "mongodb": "^2.1.18" + } + }, + "node_modules/morgan": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.7.0.tgz", + "integrity": "sha1-6xDKjlDRq+D409rVwCAdBS2YHGI=", + "dependencies": { + "basic-auth": "~1.0.3", + "debug": "~2.2.0", + "depd": "~1.1.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dependencies": { + "ms": "0.7.1" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "node_modules/process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dependencies": { + "asap": "~2.0.3" + } + }, + "node_modules/proxy-addr": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", + "integrity": "sha1-ccDuOxAt4/IC87ZPYI0XP8uhqRg=", + "dependencies": { + "forwarded": "~0.1.0", + "ipaddr.js": "1.4.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/pug": { + "version": "2.0.0-rc.2", + "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.0-rc.2.tgz", + "integrity": "sha1-B4RVJ3kKssa+Z9z16x8xgECB8Eo=", + "dependencies": { + "pug-code-gen": "^1.1.1", + "pug-filters": "^2.1.3", + "pug-lexer": "^3.1.0", + "pug-linker": "^3.0.1", + "pug-load": "^2.0.7", + "pug-parser": "^3.0.0", + "pug-runtime": "^2.0.3", + "pug-strip-comments": "^1.0.2" + } + }, + "node_modules/pug-attrs": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.4.tgz", + "integrity": "sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ==", + "dependencies": { + "constantinople": "^3.0.1", + "js-stringify": "^1.0.1", + "pug-runtime": "^2.0.5" + } + }, + "node_modules/pug-code-gen": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-1.1.1.tgz", + "integrity": "sha1-HPcnRO8qA56uajNAyqoRBYcSWOg=", + "dependencies": { + "constantinople": "^3.0.1", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.1", + "pug-attrs": "^2.0.2", + "pug-error": "^1.3.2", + "pug-runtime": "^2.0.3", + "void-elements": "^2.0.1", + "with": "^5.0.0" + } + }, + "node_modules/pug-error": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.3.tgz", + "integrity": "sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ==" + }, + "node_modules/pug-filters": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-2.1.5.tgz", + "integrity": "sha512-xkw71KtrC4sxleKiq+cUlQzsiLn8pM5+vCgkChW2E6oNOzaqTSIBKIQ5cl4oheuDzvJYCTSYzRaVinMUrV4YLQ==", + "dependencies": { + "clean-css": "^3.3.0", + "constantinople": "^3.0.1", + "jstransformer": "1.0.0", + "pug-error": "^1.3.2", + "pug-walk": "^1.1.5", + "resolve": "^1.1.6", + "uglify-js": "^2.6.1" + } + }, + "node_modules/pug-lexer": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-3.1.0.tgz", + "integrity": "sha1-/QhzdtSmdbT1n4/vQiiDQ06VgaI=", + "dependencies": { + "character-parser": "^2.1.1", + "is-expression": "^3.0.0", + "pug-error": "^1.3.2" + } + }, + "node_modules/pug-linker": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.6.tgz", + "integrity": "sha512-bagfuHttfQOpANGy1Y6NJ+0mNb7dD2MswFG2ZKj22s8g0wVsojpRlqveEQHmgXXcfROB2RT6oqbPYr9EN2ZWzg==", + "dependencies": { + "pug-error": "^1.3.3", + "pug-walk": "^1.1.8" + } + }, + "node_modules/pug-load": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.12.tgz", + "integrity": "sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg==", + "dependencies": { + "object-assign": "^4.1.0", + "pug-walk": "^1.1.8" + } + }, + "node_modules/pug-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-3.0.1.tgz", + "integrity": "sha512-YNcfPtamkJ6Blgdev1keI1rK5UZ5TtYS4r1lZw1/lhFhyEVAwKtzOsv6aqxI0xBWfCia/vNWhdtdaqoMRB2jcQ==", + "dependencies": { + "pug-error": "^1.3.2", + "token-stream": "0.0.1" + } + }, + "node_modules/pug-runtime": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.5.tgz", + "integrity": "sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw==" + }, + "node_modules/pug-strip-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.4.tgz", + "integrity": "sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw==", + "dependencies": { + "pug-error": "^1.3.3" + } + }, + "node_modules/pug-walk": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.8.tgz", + "integrity": "sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA==" + }, + "node_modules/qs": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz", + "integrity": "sha1-zgPF/wk1vB2daanxTL0Y5WjWdiU=", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz", + "integrity": "sha1-mUl2z2pQlqQRYoQEkvC9xdbn+5Y=", + "dependencies": { + "bytes": "2.4.0", + "iconv-lite": "0.4.15", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", + "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", + "dependencies": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "dependencies": { + "resolve-from": "^2.0.0", + "semver": "^5.1.0" + } + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dependencies": { + "align-text": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/send": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.14.2.tgz", + "integrity": "sha1-ObBDiz9RC+Xcb2Z6EfcWiTaM3u8=", + "dependencies": { + "debug": "~2.2.0", + "depd": "~1.1.0", + "destroy": "~1.0.4", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "etag": "~1.7.0", + "fresh": "0.3.0", + "http-errors": "~1.5.1", + "mime": "1.3.4", + "ms": "0.7.2", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.3.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dependencies": { + "ms": "0.7.1" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + }, + "node_modules/send/node_modules/ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + }, + "node_modules/serve-favicon": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", + "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", + "dependencies": { + "etag": "~1.7.0", + "fresh": "0.3.0", + "ms": "0.7.2", + "parseurl": "~1.3.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-favicon/node_modules/ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + }, + "node_modules/serve-static": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.2.tgz", + "integrity": "sha1-LPmIm9RDWjIMw2iVyapXvWYuasc=", + "dependencies": { + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "parseurl": "~1.3.1", + "send": "0.14.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz", + "integrity": "sha1-gaVSFB7BBLiOic44MQOtXGZWTQg=" + }, + "node_modules/simple-git": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.73.0.tgz", + "integrity": "sha1-h2g6cpsb7gFqMYL5Wiq3Ixe7AjA=", + "dependencies": { + "debug": "^2.6.7" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "node_modules/statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/token-stream": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz", + "integrity": "sha1-zu78cXp2xDFvEm0LnbqlXX598Bo=" + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, + "node_modules/uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dependencies": { + "source-map": "~0.5.1", + "yargs": "~3.10.0" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + }, + "optionalDependencies": { + "uglify-to-browserify": "~1.0.0" + } + }, + "node_modules/uglify-js/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/with": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz", + "integrity": "sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=", + "dependencies": { + "acorn": "^3.1.0", + "acorn-globals": "^3.0.0" + } + }, + "node_modules/with/node_modules/acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dependencies": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + } + }, + "dependencies": { + "@types/babel-types": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.9.tgz", + "integrity": "sha512-qZLoYeXSTgQuK1h7QQS16hqLGdmqtRmN8w/rl3Au/l5x/zkHx+a4VHrHyBsi1I1vtK2oBHxSzKIu0R5p6spdOA==" + }, + "@types/babylon": { + "version": "6.16.5", + "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.5.tgz", + "integrity": "sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w==", + "requires": { + "@types/babel-types": "*" + } + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" + }, + "acorn-globals": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", + "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=", + "requires": { + "acorn": "^4.0.4" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + }, + "basic-auth": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", + "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=" + }, + "bitcoin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/bitcoin/-/bitcoin-3.0.1.tgz", + "integrity": "sha1-/54LYqcbu4rd2zTuLkJ9rCHBCW8=" + }, + "body-parser": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.16.1.tgz", + "integrity": "sha1-UVQNBFrfp6DGmVoBS7ax7ZuAIyk=", + "requires": { + "bytes": "2.4.0", + "content-type": "~1.0.2", + "debug": "2.6.1", + "depd": "~1.1.0", + "http-errors": "~1.5.1", + "iconv-lite": "0.4.15", + "on-finished": "~2.3.0", + "qs": "6.2.1", + "raw-body": "~2.2.0", + "type-is": "~1.6.14" + }, + "dependencies": { + "debug": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.1.tgz", + "integrity": "sha1-eYVQkLosTjEVzH2HaUkdWPBJE1E=", + "requires": { + "ms": "0.7.2" + } + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + } + } + }, + "bson": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz", + "integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg==" + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" + }, + "bytes": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "character-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", + "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=", + "requires": { + "is-regex": "^1.0.3" + } + }, + "clean-css": { + "version": "3.4.28", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", + "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", + "requires": { + "commander": "2.8.x", + "source-map": "0.4.x" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "constantinople": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.2.tgz", + "integrity": "sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw==", + "requires": { + "@types/babel-types": "^7.0.0", + "@types/babylon": "^6.16.2", + "babel-types": "^6.26.0", + "babylon": "^6.18.0" + } + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-parser": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz", + "integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==", + "requires": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6" + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz", + "integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms=" + }, + "crypto-js": { + "version": "3.1.9-1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz", + "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decimal.js": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-7.2.3.tgz", + "integrity": "sha512-AoFI37QS0S87Ft0r3Bdz4q9xSpm1Paa9lSeKLXgMPk/u/+QPIM5Gy4DHcZQS1seqPJH4gHLauPGn347z0HbsrA==" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "doctypes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", + "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "es6-promise": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", + "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "etag": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=" + }, + "express": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.14.1.tgz", + "integrity": "sha1-ZGwjf3ZvFIwhIK/wc4F7nk1+DTM=", + "requires": { + "accepts": "~1.3.3", + "array-flatten": "1.1.1", + "content-disposition": "0.5.2", + "content-type": "~1.0.2", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "~2.2.0", + "depd": "~1.1.0", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "etag": "~1.7.0", + "finalhandler": "0.5.1", + "fresh": "0.3.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.1", + "path-to-regexp": "0.1.7", + "proxy-addr": "~1.1.3", + "qs": "6.2.0", + "range-parser": "~1.2.0", + "send": "0.14.2", + "serve-static": "~1.11.2", + "type-is": "~1.6.14", + "utils-merge": "1.0.0", + "vary": "~1.1.0" + }, + "dependencies": { + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + }, + "qs": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz", + "integrity": "sha1-O3hIwDwt7OaalSKw+ujEEm10Xzs=" + } + } + }, + "express-session": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.2.tgz", + "integrity": "sha1-2YUWRDpMy4aI4XJa5YTALapAk9Q=", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "crc": "3.4.4", + "debug": "2.6.3", + "depd": "~1.1.0", + "on-headers": "~1.0.1", + "parseurl": "~1.3.1", + "uid-safe": "~2.1.4", + "utils-merge": "1.0.0" + }, + "dependencies": { + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "debug": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.3.tgz", + "integrity": "sha1-D364wwll7AjHKsz6ATDIt5mEFB0=", + "requires": { + "ms": "0.7.2" + } + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + } + } + }, + "finalhandler": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.1.tgz", + "integrity": "sha1-LEANjUUwk1vCMlScX6OF7Afeb80=", + "requires": { + "debug": "~2.2.0", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + } + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "gitbook-plugin-github": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gitbook-plugin-github/-/gitbook-plugin-github-2.0.0.tgz", + "integrity": "sha1-UWbnY8/MQC1DKIC3pshcHFS1ao0=" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + }, + "http-errors": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz", + "integrity": "sha1-eIwNLB3iyBuebowBhDtrl+uSB1A=", + "requires": { + "inherits": "2.0.3", + "setprototypeof": "1.0.2", + "statuses": ">= 1.3.1 < 2" + } + }, + "iconv-lite": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", + "integrity": "sha1-KWrKh4qCGBbluF0KKFqZvP9FgvA=" + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "requires": { + "has": "^1.0.3" + } + }, + "is-expression": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz", + "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=", + "requires": { + "acorn": "~4.0.2", + "object-assign": "^4.0.1" + } + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "requires": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "js-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", + "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=" + }, + "jstransformer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", + "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=", + "requires": { + "is-promise": "^2.0.0", + "promise": "^7.0.1" + } + }, + "jstransformer-markdown-it": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/jstransformer-markdown-it/-/jstransformer-markdown-it-2.1.0.tgz", + "integrity": "sha1-aewwzkUYvtWZezjwJ2SOjChekvc=", + "requires": { + "markdown-it": "^8.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "requires": { + "uc.micro": "^1.0.1" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "markdown-it": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", + "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", + "requires": { + "argparse": "^1.0.7", + "entities": "~1.1.1", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" + }, + "mime-db": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" + }, + "mime-types": { + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "requires": { + "mime-db": "1.47.0" + } + }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + }, + "moment-duration-format": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/moment-duration-format/-/moment-duration-format-1.3.0.tgz", + "integrity": "sha1-VBdxtfh6BJzGVUBHXTrZZnN9aQg=" + }, + "mongodb": { + "version": "2.2.36", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.36.tgz", + "integrity": "sha512-P2SBLQ8Z0PVx71ngoXwo12+FiSfbNfGOClAao03/bant5DgLNkOPAck5IaJcEk4gKlQhDEURzfR3xuBG1/B+IA==", + "requires": { + "es6-promise": "3.2.1", + "mongodb-core": "2.1.20", + "readable-stream": "2.2.7" + } + }, + "mongodb-core": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.20.tgz", + "integrity": "sha512-IN57CX5/Q1bhDq6ShAR6gIv4koFsZP7L8WOK1S0lR0pVDQaScffSMV5jxubLsmZ7J+UdqmykKw4r9hG3XQEGgQ==", + "requires": { + "bson": "~1.0.4", + "require_optional": "~1.0.0" + } + }, + "monk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/monk/-/monk-4.1.0.tgz", + "integrity": "sha1-x+VA6GquaQ1xLD4KtwYa2LpaOio=", + "requires": { + "debug": "*", + "gitbook-plugin-github": "2.0.0", + "mongodb": "^2.1.18" + } + }, + "morgan": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.7.0.tgz", + "integrity": "sha1-6xDKjlDRq+D409rVwCAdBS2YHGI=", + "requires": { + "basic-auth": "~1.0.3", + "debug": "~2.2.0", + "depd": "~1.1.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "~2.0.3" + } + }, + "proxy-addr": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", + "integrity": "sha1-ccDuOxAt4/IC87ZPYI0XP8uhqRg=", + "requires": { + "forwarded": "~0.1.0", + "ipaddr.js": "1.4.0" + } + }, + "pug": { + "version": "2.0.0-rc.2", + "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.0-rc.2.tgz", + "integrity": "sha1-B4RVJ3kKssa+Z9z16x8xgECB8Eo=", + "requires": { + "pug-code-gen": "^1.1.1", + "pug-filters": "^2.1.3", + "pug-lexer": "^3.1.0", + "pug-linker": "^3.0.1", + "pug-load": "^2.0.7", + "pug-parser": "^3.0.0", + "pug-runtime": "^2.0.3", + "pug-strip-comments": "^1.0.2" + } + }, + "pug-attrs": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.4.tgz", + "integrity": "sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ==", + "requires": { + "constantinople": "^3.0.1", + "js-stringify": "^1.0.1", + "pug-runtime": "^2.0.5" + } + }, + "pug-code-gen": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-1.1.1.tgz", + "integrity": "sha1-HPcnRO8qA56uajNAyqoRBYcSWOg=", + "requires": { + "constantinople": "^3.0.1", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.1", + "pug-attrs": "^2.0.2", + "pug-error": "^1.3.2", + "pug-runtime": "^2.0.3", + "void-elements": "^2.0.1", + "with": "^5.0.0" + } + }, + "pug-error": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.3.tgz", + "integrity": "sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ==" + }, + "pug-filters": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-2.1.5.tgz", + "integrity": "sha512-xkw71KtrC4sxleKiq+cUlQzsiLn8pM5+vCgkChW2E6oNOzaqTSIBKIQ5cl4oheuDzvJYCTSYzRaVinMUrV4YLQ==", + "requires": { + "clean-css": "^3.3.0", + "constantinople": "^3.0.1", + "jstransformer": "1.0.0", + "pug-error": "^1.3.2", + "pug-walk": "^1.1.5", + "resolve": "^1.1.6", + "uglify-js": "^2.6.1" + } + }, + "pug-lexer": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-3.1.0.tgz", + "integrity": "sha1-/QhzdtSmdbT1n4/vQiiDQ06VgaI=", + "requires": { + "character-parser": "^2.1.1", + "is-expression": "^3.0.0", + "pug-error": "^1.3.2" + } + }, + "pug-linker": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.6.tgz", + "integrity": "sha512-bagfuHttfQOpANGy1Y6NJ+0mNb7dD2MswFG2ZKj22s8g0wVsojpRlqveEQHmgXXcfROB2RT6oqbPYr9EN2ZWzg==", + "requires": { + "pug-error": "^1.3.3", + "pug-walk": "^1.1.8" + } + }, + "pug-load": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.12.tgz", + "integrity": "sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg==", + "requires": { + "object-assign": "^4.1.0", + "pug-walk": "^1.1.8" + } + }, + "pug-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-3.0.1.tgz", + "integrity": "sha512-YNcfPtamkJ6Blgdev1keI1rK5UZ5TtYS4r1lZw1/lhFhyEVAwKtzOsv6aqxI0xBWfCia/vNWhdtdaqoMRB2jcQ==", + "requires": { + "pug-error": "^1.3.2", + "token-stream": "0.0.1" + } + }, + "pug-runtime": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.5.tgz", + "integrity": "sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw==" + }, + "pug-strip-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.4.tgz", + "integrity": "sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw==", + "requires": { + "pug-error": "^1.3.3" + } + }, + "pug-walk": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.8.tgz", + "integrity": "sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA==" + }, + "qs": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz", + "integrity": "sha1-zgPF/wk1vB2daanxTL0Y5WjWdiU=" + }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz", + "integrity": "sha1-mUl2z2pQlqQRYoQEkvC9xdbn+5Y=", + "requires": { + "bytes": "2.4.0", + "iconv-lite": "0.4.15", + "unpipe": "1.0.0" + } + }, + "readable-stream": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", + "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", + "requires": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "requires": { + "resolve-from": "^2.0.0", + "semver": "^5.1.0" + } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "^0.1.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "send": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.14.2.tgz", + "integrity": "sha1-ObBDiz9RC+Xcb2Z6EfcWiTaM3u8=", + "requires": { + "debug": "~2.2.0", + "depd": "~1.1.0", + "destroy": "~1.0.4", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "etag": "~1.7.0", + "fresh": "0.3.0", + "http-errors": "~1.5.1", + "mime": "1.3.4", + "ms": "0.7.2", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.3.1" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + }, + "dependencies": { + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + } + } + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + } + } + }, + "serve-favicon": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", + "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", + "requires": { + "etag": "~1.7.0", + "fresh": "0.3.0", + "ms": "0.7.2", + "parseurl": "~1.3.1" + }, + "dependencies": { + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + } + } + }, + "serve-static": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.2.tgz", + "integrity": "sha1-LPmIm9RDWjIMw2iVyapXvWYuasc=", + "requires": { + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "parseurl": "~1.3.1", + "send": "0.14.2" + } + }, + "setprototypeof": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz", + "integrity": "sha1-gaVSFB7BBLiOic44MQOtXGZWTQg=" + }, + "simple-git": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.73.0.tgz", + "integrity": "sha1-h2g6cpsb7gFqMYL5Wiq3Ixe7AjA=", + "requires": { + "debug": "^2.6.7" + } + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": ">=0.0.4" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" + }, + "token-stream": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz", + "integrity": "sha1-zu78cXp2xDFvEm0LnbqlXX598Bo=" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "~1.0.0" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" + }, + "with": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz", + "integrity": "sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=", + "requires": { + "acorn": "^3.1.0", + "acorn-globals": "^3.0.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" + } + } + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100755 index 0000000..0a14484 --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "rpc-explorer", + "version": "1.0.0", + "scripts": { + "start": "node ./bin/www" + }, + "repository": { + "type": "git", + "url": "https://github.com/smartcash/rpc-explorer.git" + }, + "dependencies": { + "bitcoin": "3.0.1", + "body-parser": "~1.16.0", + "cookie-parser": "~1.4.3", + "crypto-js": "3.1.9-1", + "debug": "~2.6.0", + "decimal.js": "7.2.3", + "express": "~4.14.1", + "express-session": "1.15.2", + "jstransformer-markdown-it": "^2.0.0", + "moment": "^2.18.1", + "moment-duration-format": "1.3.0", + "monk": "^4.0.0", + "morgan": "~1.7.0", + "pug": "2.0.0-rc.2", + "serve-favicon": "~2.3.2", + "simple-git": "1.73.0" + }, + "license": "MIT" +} diff --git a/proglog.txt b/proglog.txt new file mode 100755 index 0000000..be753a4 --- /dev/null +++ b/proglog.txt @@ -0,0 +1,113 @@ +block:896936,896935,896934,896933,896932,896931,896930,896929,896928,896927 +block:896936,896935,896934,896yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3475689.919block:8yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3620550.313359255 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3620550.313359255 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3620550.313359255 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3620550.313359255 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3620550.313359255 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3620550.313359255 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3620550.313359255 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3620550.313359255 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3620550.313359255 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3097414.750693175 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3097414.750693175 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3097414.750693175 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3063122.423659674 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3064355.489685315 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3064355.489685315 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3025464.432089422 +yyyyyyyyyyyyyyyyyyyyyyy +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:3025464.432089422 +mininghash:3025464.432089422 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:2373157.008316292 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:2425140.595686032 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:2363615.794209859 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:2297304.049850194 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:2109127.042296987 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:2109127.042296987 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:1887491.861699247 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:1887491.861699247 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:1806276.69781136 +yyyyyyyyyyyyyyyyyyyyyyy +mininghash:1751051.827217125 +009,897008,897007 +block:897062,897061,897060,897059,897058,897057,897056,897055,897054,897053 +block:897132,897131,897130,897129,897128,897127,897126,897125,897124,897123 +block:897155,897154,897153,897152,897151,897150,897149,897148,897147,897146 +block:897194,897193,897192,897191,897190,897189,897188,897187,897186,897185 +block:897196,897195,897194,897193,897192,897191,897190,897189,897188,897187 +block:897197,897196,897195,897194,897193,897192,897191,897190,897189,897188,897187,897186,897185,897184,897183,897182,897181,897180,897179,897178 +block:897177,897176,897175,897174,897173,897172,897171,897170,897169,897168,897167,897166,897165,897164,897163,897162,897161,897160,897159,897158 +block:897157,897156,897155,897154,897153,897152,897151,897150,897149,897148,897147,897146,897145,897144,897143,897142,897141,897140,897139,897138 +block:897117,897116,897115,897114,897113,897112,897111,897110,897109,897108,897107,897106,897105,897104,897103,897102,897101,897100,897099,897098 +block:897097,897096,897095,897094,897093,897092,897091,897090,897089,897088,897087,897086,897085,897084,897083,897082,897081,897080,897079,897078 +block:897077,897076,897075,897074,897073,897072,897071,897070,897069,897068,897067,897066,897065,897064,897063,897062,897061,897060,897059,897058 +block:897057,897056,897055,897054,897053,897052,897051,897050,897049,897048,897047,897046,897045,897044,897043,897042,897041,897040,897039,897038 +block:897037,897036,897035,897034,897033,897032,897031,897030,897029,897028,897027,897026,897025,897024,897023,897022,897021,897020,897019,897018 +block:897017,897016,897015,897014,897013,897012,897011,897010,897009,897008,897007,897006,897005,897004,897003,897002,897001,897000,896999,896998 +block:896997,896996,896995,896994,896993,896992,896991,896990,896989,896988,896987,896986,896985,896984,896983,896982,896981,896980,896979,896978 +block:896977,896976,896975,896974,896973,896972,896971,896970,896969,896968,896967,896966,896965,896964,896963,896962,896961,896960,896959,896958 +block:896957,896956,896955,896954,896953,896952,896951,896950,896949,896948,896947,896946,896945,896944,896943,896942,896941,896940,896939,896938 +block:896937,896936,896935,896934,896933,896932,896931,896930,896929,896928,896927,896926,896925,896924,896923,896922,896921,896920,896919,896918 +block:896917,896916,896915,896914,896913,896912,896911,896910,896909,896908,896907,896906,896905,896904,896903,896902,896901,896900,896899,896898 +block:896897,896896,896895,896894,896893,896892,896891,896890,896889,896888,896887,896886,896885,896884,896883,896882,896881,896880,896879,896878 +block:897197,897196,897195,897194,897193,897192,897191,897190,897189,897188 +block:897197,897196,897195,897194,897193,897192,897191,897190,897189,897188,897187,897186,897185,897184,897183,897182,897181,897180,897179,897178 +block:897197,897196,897195,897194,897193,897192,897191,897190,897189,897188 +block:897200,897199,897198,897197,897196,897195,897194,897193,897192,897191 +block:897201,897200,897199,897198,897197,897196,897195,897194,897193,897192 +block:897203,897202,897201,897200,897199,897198,897197,897196,897195,897194 +block:897206,897205,897204,897203,897202,897201,897200,897199,897198,897197 +block:897206,897205,897204,897203,897202,897201,897200,897199,897198,897197,897196,897195,897194,897193,897192,897191,897190,897189,897188,897187 +block:897208,897207,897206,897205,897204,897203,897202,897201,897200,897199 +block:897209,897208,897207,897206,897205,897204,897203,897202,897201,897200 +block:897211,897210,897209,897208,897207,897206,897205,897204,897203,897202 +block:897215,897214,897213,897212,897211,897210,897209,897208,897207,897206 +block:897242,897241,897240,897239,897238,897237,897236,897235,897234,897233 +block:897258,897257,897256,897255,897254,897253,897252,897251,897250,897249 +block:897258,897257,897256,897255,897254,897253,897252,897251,897250,897249 +block:897258,897257,897256,897255,897254,897253,897252,897251,897250,897249 +block:897258,897257,897256,897255,897254,897253,897252,897251,897250,897249,897248,897247,897246,897245,897244,897243,897242,897241,897240,897239 +block:897218,897217,897216,897215,897214,897213,897212,897211,897210,897209,897208,897207,897206,897205,897204,897203,897202,897201,897200,897199 +block:897259,897258,897257,897256,897255,897254,897253,897252,897251,897250 +block:897259,897258,897257,897256,897255,897254,897253,897252,897251,897250 +block:897262,897261,897260,897259,897258,897257,897256,897255,897254,897253 +block:897262,897261,897260,897259,897258,897257,897256,897255,897254,897253 +block:897262,897261,897260,897259,897258,897257,897256,897255,897254,897253 +block:897262,897261,897260,897259,897258,897257,897256,897255,897254,897253 +block:897262,897261,897260,897259,897258,897257,897256,897255,897254,897253 +block:897262,897261,897260,897259,897258,897257,897256,897255,897254,897253 +block:897262,897261,897260,897259,897258,897257,897256,897255,897254,897253 +block:897263,897262,897261,897260,897259,897258,897257,897256,897255,897254 +block:897265,897264,897263,897262,897261,897260,897259,897258,897257,897256 +block:897265,897264,897263,897262,897261,897260,897259,897258,897257,897256 +block:897265,897264,897263,897262,897261,897260,897259,897258,897257,897256 +block:897265,897264,897263,897262,897261,897260,897259,897258,897257,897256 +block:897271,897270,897269,897268,897267,897266,897265,897264,897263,897262 +block:897272,897271,897270,897269,897268,897267,897266,897265,897264,897263 diff --git a/public/css/styling.css b/public/css/styling.css new file mode 100755 index 0000000..3d70467 --- /dev/null +++ b/public/css/styling.css @@ -0,0 +1,179 @@ +body { + font: 14px 'Open Sans', "Lucida Grande", Helvetica, Arial, sans-serif; + background-color: #F3FAED; +} + +code { + background-color: #C4F5EE; +} + +hr { + margin: 15px 0; +} + +a { + color: #16548A; + font-weight: bold; +} + +a:hover { + color: #26296D; +} + +::selection { + background-color: #AE95F1; +} + +thead { + background-color: #9CFFF8!important; +} + +.table td, .table th { + border-top: 1px solid #4DA2AF; +} + +img.header-image { + margin-top: -10px; + margin-bottom: -5px; + width: 30px; + height: 30px; + margin-right: 10px; +} + +code, .monospace { + font-family: "Cousine", monospace; +} + +.properties-header { + width: 180px; + text-align: right; +} + +.word-wrap { + word-wrap: break-word; + word-break: break-all; +} + +.tag { + border-radius: 4px; + background-color: #0275D8; + color: white; + padding: 2px 5px; + margin-right: 4px; +} + +#subheader a { + margin-right: 20px; +} + +.data-cell, .data-header { + text-align: right; +} + +.btn-primary { + color: black; + background-color: #73DFF5; + border-color: #386CA0; +} + +.btn-primary:hover { + color: black; + background-color: #43EFE4; + border-color: #386CA0; +} + +.btn-primary:active { + color: white!important; + background-color: #43EFE4!important; + border-color: #386CA0!important; + box-shadow: 0px 1px 1px #9CFFF8 inset, 2px 2px 4px #739AF5!important; +} + +.btn-primary:focus { + box-shadow: 0px 1px 1px #739AF5 inset, 2px 2px 4px #739AF5!important; +} + +.bg-dark { + background-color: #9CFFF8!important; +} + +.navbar-brand { + font-weight: bold; +} + +.nav-link { + border-color: #125DA7!important; + font-weight: bold; +} + +.nav-link:hover { + background-color: #9CFFF8!important; +} + +.nav-link.active { + color: #420857!important; + background-color: #9CFFF8!important; + border-color: #125DA7!important; +} + +.alert-info { + background-color: #C55AF3; + border-color: #739AF5; + color: black; +} + +.alert-success { + background-color: #C4FF80; + border-color: #5F8660; + color: black; +} + +.form-control { + background-color: #D4EFFF; +} + +.form-control:hover { + background-color: #F3FAED; + box-shadow: 0px 1px 1px #739AF5 inset, 2px 2px 4px #739AF5!important; +} + +.form-control:focus { + background-color: #F3FAED; + box-shadow: 0px 1px 1px #739AF5 inset, 2px 2px 4px #739AF5!important; +} + +.card { + background-color: #D4EFFF; +} + +.tag { + color: black; + background-color: #9CFFF8; +} + + +.page-link { + color: #420857!important; + border-color: #35769C!important; +} + +.page-link:hover { + background-color: #9CFFF8!important; + box-shadow: 0px 1px 1px #739AF5 inset, 1px 1px 2px #739AF5!important; + border-color: #125DA7!important; +} + +.page-item.active .page-link { + color: #420857!important; + background-color: #9CFFF8!important; + border-color: #125DA7!important; +} + +.pagination-lg .page-link { + padding: .25rem 0.75rem; + font-size: 1.0rem; + line-height: 1.5; +} + + + diff --git a/public/img/favicons/android-chrome-192x192.png b/public/img/favicons/android-chrome-192x192.png new file mode 100755 index 0000000..ea40742 Binary files /dev/null and b/public/img/favicons/android-chrome-192x192.png differ diff --git a/public/img/favicons/android-chrome-512x512.png b/public/img/favicons/android-chrome-512x512.png new file mode 100755 index 0000000..95bdffb Binary files /dev/null and b/public/img/favicons/android-chrome-512x512.png differ diff --git a/public/img/favicons/apple-touch-icon.png b/public/img/favicons/apple-touch-icon.png new file mode 100755 index 0000000..335d59a Binary files /dev/null and b/public/img/favicons/apple-touch-icon.png differ diff --git a/public/img/favicons/browserconfig.xml b/public/img/favicons/browserconfig.xml new file mode 100755 index 0000000..e32a1f4 --- /dev/null +++ b/public/img/favicons/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #ffc40d + + + diff --git a/public/img/favicons/favicon-16x16.png b/public/img/favicons/favicon-16x16.png new file mode 100755 index 0000000..7e45603 Binary files /dev/null and b/public/img/favicons/favicon-16x16.png differ diff --git a/public/img/favicons/favicon-32x32.png b/public/img/favicons/favicon-32x32.png new file mode 100755 index 0000000..36b53e2 Binary files /dev/null and b/public/img/favicons/favicon-32x32.png differ diff --git a/public/img/favicons/favicon.ico b/public/img/favicons/favicon.ico new file mode 100755 index 0000000..881b1b0 Binary files /dev/null and b/public/img/favicons/favicon.ico differ diff --git a/public/img/favicons/manifest.json b/public/img/favicons/manifest.json new file mode 100755 index 0000000..ed6d4fd --- /dev/null +++ b/public/img/favicons/manifest.json @@ -0,0 +1,19 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/public/img/favicons/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/public/img/favicons/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/public/img/favicons/mstile-150x150.png b/public/img/favicons/mstile-150x150.png new file mode 100755 index 0000000..6cc026b Binary files /dev/null and b/public/img/favicons/mstile-150x150.png differ diff --git a/public/img/favicons/vivobluelogo.png b/public/img/favicons/vivobluelogo.png new file mode 100755 index 0000000..ef4eda0 Binary files /dev/null and b/public/img/favicons/vivobluelogo.png differ diff --git a/public/img/icon.png b/public/img/icon.png new file mode 100755 index 0000000..2478c15 Binary files /dev/null and b/public/img/icon.png differ diff --git a/public/img/logo-256.png b/public/img/logo-256.png new file mode 100755 index 0000000..2083df6 Binary files /dev/null and b/public/img/logo-256.png differ diff --git a/public/img/logo/logo-64.png b/public/img/logo/logo-64.png new file mode 100755 index 0000000..9eae418 Binary files /dev/null and b/public/img/logo/logo-64.png differ diff --git a/public/img/logo/logo-64a.png b/public/img/logo/logo-64a.png new file mode 100755 index 0000000..e1f146e Binary files /dev/null and b/public/img/logo/logo-64a.png differ diff --git a/public/img/logo/vivobluelogo.png b/public/img/logo/vivobluelogo.png new file mode 100755 index 0000000..ef4eda0 Binary files /dev/null and b/public/img/logo/vivobluelogo.png differ diff --git a/routes/baseActionsRouter.js b/routes/baseActionsRouter.js new file mode 100755 index 0000000..fcb16b7 --- /dev/null +++ b/routes/baseActionsRouter.js @@ -0,0 +1,367 @@ +var express = require('express'); +var router = express.Router(); +var util = require('util'); +var moment = require('moment'); +var utils = require('./../app/utils'); +var env = require("./../app/env"); +var bitcoin = require("bitcoin"); +var rpcApi = require("./../app/rpcApi"); + +var fs = require('fs'); +var stream = fs.createWriteStream("proglog.txt"); + + +router.get("/", function(req, res) { + if (!req.session.host) { + if (req.cookies['rpc-host']) { + res.locals.host = req.cookies['rpc-host']; + } + + if (req.cookies['rpc-port']) { + res.locals.port = req.cookies['rpc-port']; + } + + if (req.cookies['rpc-username']) { + res.locals.username = req.cookies['rpc-username']; + } + + res.render("connect"); + res.end(); + + return; + } + + var client = global.client; + + rpcApi.getInfo().then(function(getinfo) { + res.locals.getinfo = getinfo; + + var blockHeights = []; + if (getinfo.blocks) { + for (var i = 0; i < 10; i++) { + blockHeights.push(getinfo.blocks - i); + } + } + + rpcApi.getBlocksByHeight(blockHeights).then(function(latestBlocks) { + res.locals.latestBlocks = latestBlocks; + + res.render("index"); + }); + }).catch(function(err) { + console.log(err); + res.locals.userMessage = "Unable to connect to Vivocoin Node at " + req.session.host + ":" + req.session.port; + res.render("index"); + }); +}); + +router.get("/node-info", function(req, res) { + var client = global.client; + + stream.write("yyyyyyyyyyyyyyyyyyyyyyy\n"); + + rpcApi.getInfo().then(function(getinfo) { + res.locals.getinfo = getinfo; + + rpcApi.getMiningInfo().then(function(getmininginfo) { + res.locals.getmininginfo = getmininginfo; + + console.log(getmininginfo); + stream.write('mininghash:'+ getmininginfo.networkhashps +"\n"); + + + res.render("node-info"); + + }); + }).catch(function(err) { + res.locals.userMessage = "Unable to connect to Vivocoin Node at " + req.session.host + ":" + req.session.port; + console.log(err); + res.render("node-info"); + }); +}); + +router.get("/mempool", function(req, res) { + var client = global.client; + + rpcApi.getMempoolInfo().then(function(getmempoolinfo) { + res.locals.getmempoolinfo = getmempoolinfo; + + rpcApi.getMempoolStats().then(function(mempoolstats) { + res.locals.mempoolstats = mempoolstats; + + res.render("mempool"); + }); + }).catch(function(err) { + res.locals.userMessage = "Unable to connect to Vivocoin Node at " + req.session.host + ":" + req.session.port; + console.log(err); + res.render("mempool"); + }); +}); + +router.post("/connect", function(req, res) { + var host = req.body.host; + var port = req.body.port; + var username = req.body.username; + var password = req.body.password; + + res.cookie('rpc-host', host); + res.cookie('rpc-port', port); + res.cookie('rpc-username', username); + + req.session.host = host; + req.session.port = port; + req.session.username = username; + + var client = new bitcoin.Client({ + host: host, + port: port, + user: username, + pass: password, + timeout: 30000 + }); + + console.log("created client: " + client); + + global.client = client; + + req.session.userMessage = "Connected via RPC: " + username + " @ " + host + ":" + port; + req.session.userMessageType = "success"; + + res.redirect("/"); +}); + +router.get("/blocks", function(req, res) { + var limit = 20; + var offset = 0; + var sort = "desc"; + + if (req.query.limit) { + limit = parseInt(req.query.limit); + } + + if (req.query.offset) { + offset = parseInt(req.query.offset); + } + + if (req.query.sort) { + sort = req.query.sort; + } + + res.locals.limit = limit; + res.locals.offset = offset; + res.locals.sort = sort; + res.locals.paginationBaseUrl = "/blocks"; + + rpcApi.getInfo().then(function(getinfo) { + res.locals.blockCount = getinfo.blocks; + res.locals.blockOffset = offset; + + var blockHeights = []; + if (sort == "desc") { + for (var i = (getinfo.blocks - offset); i > (getinfo.blocks - offset - limit); i--) { + blockHeights.push(i); + } + } else { + for (var i = offset; i < (offset + limit); i++) { + blockHeights.push(i); + } + } + + rpcApi.getBlocksByHeight(blockHeights).then(function(blocks) { + res.locals.blocks = blocks; + + res.render("blocks"); + }); + }).catch(function(err) { + res.locals.userMessage = "Unable to connect to Vivocoin Node at " + req.session.host + ":" + req.session.port; + console.log(err); + res.render("blocks"); + }); +}); + +router.post("/search", function(req, res) { + if (!req.body.query) { + req.session.userMessage = "Enter a block height, block hash, or transaction id."; + + res.redirect("/"); + + return; + } + + var query = req.body.query.toLowerCase(); + + rpcApi.getRawTransaction(query).then(function(tx) { + if (tx) { + res.redirect("/tx/" + query); + + return; + } + }).catch(function(err) { + rpcApi.getBlockByHash(query).then(function(blockByHash) { + if (blockByHash) { + res.redirect("/block/" + query); + + return; + } + }).catch(function(err) { + if (isNaN(query)) { + req.session.userMessage = "No results found for query: " + query; + + res.redirect("/"); + + return; + } + + rpcApi.getBlockByHeight(parseInt(query)).then(function(blockByHeight) { + if (blockByHeight) { + res.redirect("/block-height/" + query); + + return; + } + }).catch(function(err) { + req.session.userMessage = "No results found for query: " + query; + + res.redirect("/"); + }); + }); + }); +}); + +router.get("/block-height/:blockHeight", function(req, res) { + var client = global.client; + + var blockHeight = parseInt(req.params.blockHeight); + + res.locals.blockHeight = blockHeight; + + res.locals.result = {}; + + var limit = 20; + var offset = 0; + + if (req.query.limit) { + limit = parseInt(req.query.limit); + } + + if (req.query.offset) { + offset = parseInt(req.query.offset); + } + + res.locals.limit = limit; + res.locals.offset = offset; + res.locals.paginationBaseUrl = "/block-height/" + blockHeight; + + client.cmd('getblockhash', blockHeight, function(err, result, resHeaders) { + if (err) { + // TODO handle RPC error + return console.log(err); + } + + res.locals.result.getblockhash = result; + + rpcApi.getBlockData(client, result, limit, offset).then(function(result) { + res.locals.result.getblock = result.getblock; + res.locals.result.transactions = result.transactions; + res.locals.result.txInputsByTransaction = result.txInputsByTransaction; + + res.render("block-height"); + }); + }); +}); + +router.get("/block/:blockHash", function(req, res) { + var blockHash = req.params.blockHash; + + res.locals.blockHash = blockHash; + + res.locals.result = {}; + + var limit = 20; + var offset = 0; + + if (req.query.limit) { + limit = parseInt(req.query.limit); + } + + if (req.query.offset) { + offset = parseInt(req.query.offset); + } + + res.locals.limit = limit; + res.locals.offset = offset; + res.locals.paginationBaseUrl = "/block/" + blockHash; + + // TODO handle RPC error + rpcApi.getBlockData(client, blockHash, limit, offset).then(function(result) { + res.locals.result.getblock = result.getblock; + res.locals.result.transactions = result.transactions; + res.locals.result.txInputsByTransaction = result.txInputsByTransaction; + + res.render("block"); + }); +}); + +router.get("/tx/:transactionId", function(req, res) { + var txid = req.params.transactionId; + + var output = -1; + if (req.query.output) { + output = parseInt(req.query.output); + } + + res.locals.txid = txid; + res.locals.output = output; + + res.locals.result = {}; + + // TODO handle RPC error + rpcApi.getRawTransaction(txid).then(function(rawTxResult) { + res.locals.result.getrawtransaction = rawTxResult; + + client.cmd('getblock', rawTxResult.blockhash, function(err3, result3, resHeaders3) { + res.locals.result.getblock = result3; + + var txids = []; + for (var i = 0; i < rawTxResult.vin.length; i++) { + if (!rawTxResult.vin[i].coinbase) { + txids.push(rawTxResult.vin[i].txid); + } + } + + rpcApi.getRawTransactions(txids).then(function(txInputs) { + res.locals.result.txInputs = txInputs; + + res.render("transaction"); + }); + }); + }); +}); + +router.get("/terminal", function(req, res) { + if (!env.debug) { + res.send("Debug mode is off."); + + return; + } + + res.render("terminal"); +}); + +router.post("/terminal", function(req, res) { + if (!env.debug) { + res.send("Debug mode is off."); + + return; + } + + client.cmd(req.body.cmd, function(err, result, resHeaders) { + console.log(result); + console.log(err); + console.log(resHeaders); + + res.send(JSON.stringify(result, null, 4)); + }); +}); + + +module.exports = router; diff --git a/views/block-height.pug b/views/block-height.pug new file mode 100755 index 0000000..bb5c16b --- /dev/null +++ b/views/block-height.pug @@ -0,0 +1,10 @@ +extends layout + +block headContent + title Block #{blockHeight} + +block content + h1(class="h2") Block #{blockHeight} + hr + + include includes/block-content.pug diff --git a/views/block.pug b/views/block.pug new file mode 100755 index 0000000..3eb8760 --- /dev/null +++ b/views/block.pug @@ -0,0 +1,12 @@ +extends layout + +block headContent + title Block #{blockHash} + +block content + h1(class="h2") Block + br + small(class="monospace") #{result.getblock.hash} + hr + + include includes/block-content.pug diff --git a/views/blocks.pug b/views/blocks.pug new file mode 100755 index 0000000..f6ee75c --- /dev/null +++ b/views/blocks.pug @@ -0,0 +1,35 @@ +extends layout + +block content + h1(class="h2") Blocks + hr + + if (blocks) + nav(aria-label="Page navigation") + ul(class="pagination justify-content-center") + li(class="page-item", class=(sort == "asc" ? "active" : false)) + a(class="page-link", href=(sort == "asc" ? "javascript:void(0)" : "/blocks?limit=" + limit + "&offset=0" + "&sort=asc")) + span(aria-hidden="true") Oldest blocks first + li(class="page-item", class=(sort == "desc" ? "active" : false)) + a(class="page-link", href=(sort == "desc" ? "javascript:void(0)" : "/blocks?limit=" + limit + "&offset=0" + "&sort=desc")) + span(aria-hidden="true") Newest blocks first + + include includes/blocks-list.pug + + hr + + if (blockCount > limit) + - var pageNumber = offset / limit + 1; + - var pageCount = Math.floor(blockCount / limit); + - if (pageCount * limit < blockCount) { + - pageCount++; + - } + - var paginationUrlFunction = function(x) { + - return paginationBaseUrl + "?limit=" + limit + "&offset=" + ((x - 1) * limit + "&sort=" + sort); + - } + + hr + + include includes/pagination.pug + else + p No blocks found \ No newline at end of file diff --git a/views/btcprice.pug b/views/btcprice.pug new file mode 100755 index 0000000..f3eb638 --- /dev/null +++ b/views/btcprice.pug @@ -0,0 +1 @@ +td(class="monospace") 0000002 \ No newline at end of file diff --git a/views/connect.pug b/views/connect.pug new file mode 100755 index 0000000..9b262a6 --- /dev/null +++ b/views/connect.pug @@ -0,0 +1,37 @@ +extends layout + +block content + h1 Vivocoin RPC Explorer + hr + + :markdown-it + This tool is intended to be a simple, stateless, self-hosted explorer for the Vivocoin blockchain, driven by RPC calls to your own vivod node. Because it is stateless, it is easy to run but lacks some (many?) of the features of other explorers. + + Start by connecting to your full, archiving smartcashd node. Make sure that the node you'll be connecting to has `txindex=1` set. + + form(method="post", action="/connect") + div(class="card") + div(class="card-body") + h4(class="card-title") RPC Connect + + hr + + div(class="form-group") + label(for="input-host") Host / IP + input(type="text", name="host", class="form-control", value=host) + + div(class="form-group") + label(for="input-host") Port + input(type="text", name="port", class="form-control", value=port) + + div(class="form-group") + label(for="input-host") Username + input(type="text", name="username", class="form-control", value=username) + + div(class="form-group") + label(for="input-host") Password + input(type="password", name="password", class="form-control") + + hr + + input(type="submit", class="btn btn-primary btn-block" value="Connect") diff --git a/views/error.pug b/views/error.pug new file mode 100755 index 0000000..7d34a22 --- /dev/null +++ b/views/error.pug @@ -0,0 +1,14 @@ +extends layout + +block content + h1 Error + hr + + if (message) + p !{message} + else + p Unknown error + + if (error) + h2 #{error.status} + pre #{error.stack} diff --git a/views/includes/block-content.pug b/views/includes/block-content.pug new file mode 100755 index 0000000..d3eacd9 --- /dev/null +++ b/views/includes/block-content.pug @@ -0,0 +1,245 @@ +ul(class='nav nav-tabs mb-3') + li(class="nav-item") + a(data-toggle="tab", href="#tab-summary", class="nav-link active", role="tab") Summary + li(class="nav-item") + a(data-toggle="tab", href="#tab-raw", class="nav-link", role="tab") Raw + +- var txCount = result.getblock.tx.length; + +div(class="tab-content") + div(id="tab-summary", class="tab-pane active", role="tabpanel") + table(class="table") + tr + th(class="table-active properties-header") Block Hash + td(class="monospace") + a(href=("/block/" + result.getblock.hash)) #{result.getblock.hash} + + tr + th(class="table-active properties-header") Previous Block Hash + td(class="monospace") + if (result.getblock.previousblockhash) + a(href=("/block/" + result.getblock.previousblockhash)) #{result.getblock.previousblockhash} + + tr + th(class="table-active properties-header") Next Block Hash + td(class="monospace") + if (result.getblock.nextblockhash) + a(href=("/block/" + result.getblock.nextblockhash)) #{result.getblock.nextblockhash} + else + span None + span(class="text-muted") (latest block) + + tr + th(class="table-active properties-header") Block Height + td(class="monospace") + a(href=("/block-height/" + result.getblock.height)) #{result.getblock.height} + + tr + th(class="table-active properties-header") Timestamp + td(class="monospace") #{moment.utc(new Date(result.getblock.time * 1000)).format("Y-MM-DD HH:mm:ss")} (utc) + + tr + th(class="table-active properties-header") Transaction Count + td(class="monospace") #{result.getblock.tx.length.toLocaleString()} + + tr + th(class="table-active properties-header") Size + td(class="monospace") + span #{result.getblock.size.toLocaleString()} bytes + if (result.getblock.weight) + br + span(class="text-muted") (weight: #{result.getblock.weight.toLocaleString()}) + + tr + th(class="table-active properties-header") Confirmations + td(class="monospace") + if (result.getblock.confirmations < 6) + strong(class="text-warning") #{result.getblock.confirmations} + else + strong(class="text-success") #{result.getblock.confirmations.toLocaleString()} + + tr + - var scales = [ {val:1000000000000000, name:"quadrillion"}, {val:1000000000000, name:"trillion"}, {val:1000000000, name:"billion"}, {val:1000000, name:"million"} ]; + - var scaleDone = false; + th(class="table-active properties-header") Difficulty + td(class="monospace") + span #{result.getblock.difficulty.toLocaleString()} + each item in scales + if (!scaleDone) + - var fraction = Math.floor(result.getblock.difficulty / item.val); + if (fraction >= 1) + - scaleDone = true; + span(class="text-muted") (#{fraction} #{item.name}) + + + tr + th(class="table-active text-right") Version + td(class="monospace") 0x#{result.getblock.versionHex} + span(class="text-muted") (decimal: #{result.getblock.version}) + + tr + th(class="table-active text-right") Nonce + td(class="monospace") #{result.getblock.nonce} + + tr + th(class="table-active text-right") Bits + td(class="monospace") #{result.getblock.bits} + + tr + th(class="table-active text-right") Merkle Root + td(class="monospace") #{result.getblock.merkleroot} + + tr + th(class="table-active text-right") Chainwork + td(class="monospace") #{result.getblock.chainwork} + + hr + h2(class="h4") Transactions (#{txCount.toLocaleString()}) + small - Showing + if (txCount <= limit) + span all + else + span #{(offset + 1)} - #{Math.min(offset + limit, txCount)} + + each tx, txIndex in result.transactions + //pre + // code #{JSON.stringify(tx, null, 4)} + div(class="card mb-3") + div(class="card-header") + if (tx && tx.txid) + a(href=("/tx/" + tx.txid), class="monospace") #{tx.txid} + else if (result.getblock.height == 0) + a(href=(""), class="monospace") #{result.getblock.tx} + div(class="card-body") + //pre + // code #{JSON.stringify(result.txInputsByTransaction[tx.txid], null, 4)} + if (tx && tx.txid) + div(class="row") + div(class="col-md-6") + h6 Input (#{tx.vin.length.toLocaleString()}) + if (result.txInputsByTransaction[tx.txid]) + - var totalInputValue = new Decimal(0); + table(class="table mb-0") + thead + tr + th(style="width: 40px;") + th Input + th Amount + tbody + + if (tx.vin[0].coinbase) + - totalInputValue = totalInputValue.plus(new Decimal(utils.getBlockReward(result.getblock.height))); + tr + th 1 + td + span(class="tag monospace") coinbase + span(class="monospace") Newly minted VIVO + td(class="monospace") Σ #{utils.getBlockReward(result.getblock.height)} + + each txInput, txInputIndex in result.txInputsByTransaction[tx.txid] + if (txInput) + - var vout = txInput.vout[tx.vin[txInputIndex].vout]; + + tr + th #{(txInputIndex + 1)} + //pre + // code #{JSON.stringify(txInput)} + + td + if (vout.scriptPubKey && vout.scriptPubKey.addresses) + span(class="monospace") #{vout.scriptPubKey.addresses[0]} + br + span(class="monospace text-muted") via tx + a(href=("/tx/" + txInput.txid + "#output-" + tx.vin[txInputIndex].vout), class="monospace") #{txInput.txid.substring(0, 14)}..., Output ##{tx.vin[txInputIndex].vout + 1} + td + if (vout.value) + - totalInputValue = totalInputValue.plus(new Decimal(vout.value)); + span(class="monospace") Σ #{vout.value} + + - var coinbaseCount = tx.vin[0].coinbase ? 1 : 0; + if ((tx.vin.length - coinbaseCount) > result.txInputsByTransaction[tx.txid].length) + tr + td + td + //span(class="monospace text-muted") #{(tx.vin.length - result.txInputsByTransaction[tx.txid].length).toLocaleString()} : click on transaction id for all ... + + //span(class="monospace text-muted") a(href=("/tx/" + tx.txid), click on transaction id for all ....)} + //a(href=""/tx/" + #{tx.txid}", class="nav-link") more ... #{tx.txid} + //a(href=("/tx/" + tx.txid), class="monospace") #{tx.txid} + + span(class="monospace text-muted") #{(tx.vin.length - result.txInputsByTransaction[tx.txid].length).toLocaleString()}: + + //a(href=("/tx/" + tx.txid), class="monospace") + + a(href=("/tx/" + tx.txid), class="monospace") more .. + + td + else + tr + td + td + td + strong(class="monospace") Σ #{totalInputValue} + + + div(class="col-md-6") + h6 Output (#{tx.vout.length.toLocaleString()}) + - var totalOutputValue = new Decimal(0); + table(class="table mb-0") + thead + tr + th + th Output + th Amount + + tbody + each vout, voutIndex in tx.vout + tr + th #{(voutIndex + 1)} + td + if (vout.scriptPubKey) + if (vout.scriptPubKey.addresses) + a(id="output-" + voutIndex) + span(class="monospace") #{vout.scriptPubKey.addresses[0]} + + else if (vout.scriptPubKey.hex && vout.scriptPubKey.hex.startsWith('6a24aa21a9ed')) + span(class="monospace") Segregated Witness committment - + a(href="https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#commitment-structure") docs + i(class="fa fa-external-link") + else if (vout.scriptPubKey.asm && vout.scriptPubKey.asm.startsWith('OP_RETURN ')) + span(class="monospace") OP_RETURN: + span(class="monospace text-muted") #{utils.hex2ascii(vout.scriptPubKey.asm.substring("OP_RETURN ".length))} + td + span(class="monospace") Σ #{vout.value} + - totalOutputValue = totalOutputValue.plus(vout.value); + + tr + td + td + td + strong(class="monospace") Σ #{totalOutputValue} + else if (result.getblock.height == 0) + table(class="table mb-0") + thead + tr + th(style="text-align: center;") Genesis + //pre + // code #{JSON.stringify(tx, null, 4)} + + if (txCount > limit) + - var pageNumber = offset / limit + 1; + - var pageCount = Math.floor(txCount / limit); + - if (pageCount * limit < txCount) { + - pageCount++; + - } + - var paginationUrlFunction = function(x) { + - return paginationBaseUrl + "?limit=" + limit + "&offset=" + ((x - 1) * limit); + - } + + hr + + include ./pagination.pug + + div(id="tab-raw", class="tab-pane", role="tabpanel") + pre + code #{JSON.stringify(result.getblock, null, 4)} diff --git a/views/includes/blocks-list.pug b/views/includes/blocks-list.pug new file mode 100755 index 0000000..f4fd8a0 --- /dev/null +++ b/views/includes/blocks-list.pug @@ -0,0 +1,22 @@ +table(class="table table-striped") + thead + tr + th + th(class="data-header") Height + th(class="data-header") Timestamp (utc) + th(class="data-header") Age (seconds) + th(class="data-header") Transactions + //th(class="data-header") Size (bytes) + tbody + each block, blockIndex in blocks + if (block) + tr + th #{(blockIndex + blockOffset + 1).toLocaleString()} + td(class="data-cell monospace") + a(href=("/block-height/" + block.height)) #{block.height} + td(class="data-cell monospace") #{moment.utc(new Date(parseInt(block.time) * 1000)).format("Y-MM-DD HH:mm:ss")} + + - var timeAgo = moment.duration(moment.utc(new Date()).diff(moment.utc(new Date(parseInt(block.time) * 1000)))); + td(class="data-cell monospace") #{timeAgo.format()} + td(class="data-cell monospace") #{block.tx.length.toLocaleString()} + //td(class="data-cell monospace") #{block.size.toLocaleString()} \ No newline at end of file diff --git a/views/includes/pagination.pug b/views/includes/pagination.pug new file mode 100755 index 0000000..4f216a8 --- /dev/null +++ b/views/includes/pagination.pug @@ -0,0 +1,26 @@ +- var pageNumbers = []; +- for (var x = 1; x <= pageCount; x++) { + - pageNumbers.push(x); +- } + +nav(aria-label="Page navigation") + ul(class="pagination pagination-lg justify-content-center") + li(class="page-item", class=(pageNumber == 1 ? "disabled" : false)) + a(class="page-link", href=(pageNumber == 1 ? "javascript:void(0)" : paginationUrlFunction(pageNumber - 1)), aria-label="Previous") + span(aria-hidden="true") « + each x, xIndex in pageNumbers + if (x >= (pageNumber - 4) && x <= (pageNumber + 4) || xIndex == 0 || xIndex == (pageNumbers.length - 1)) + li(class="page-item", class=(x == pageNumber ? "active" : false)) + a(class="page-link", href=(paginationUrlFunction(x))) #{x} + + if (x == 1 && pageNumber > 6) + li(class="page-item disabled") + a(class="page-link", href="javascript:void(0)") ... + + else if (x == (pageCount - 1) && pageNumber < (pageCount - 5)) + li(class="page-item disabled") + a(class="page-link", href="javascript:void(0)") ... + + li(class="page-item", class=(pageNumber == pageCount ? "disabled" : false)) + a(class="page-link", href=(pageNumber == pageCount ? "javascript:void(0)" : paginationUrlFunction(pageNumber + 1)), aria-label="Next") + span(aria-hidden="true") » \ No newline at end of file diff --git a/views/index.pug b/views/index.pug new file mode 100755 index 0000000..5285607 --- /dev/null +++ b/views/index.pug @@ -0,0 +1,31 @@ +extends layout + +block headContent + title Home + +block content + h1 Vivocoin Quick Explorer + hr + + :markdown-it + **Vivocoin Explorer 3** is an explorer with fast setup time. The Larger Explorers are at [http://explorer7.vivocoin.net](http://explorer7.vivocoin.net) and [http://explorer6.vivocoin.net](http://explorer6.vivocoin.net) + + + if (latestBlocks) + h3 Latest Blocks + + - var blocks = latestBlocks; + - var blockOffset = 0; + + include includes/blocks-list.pug + + hr + a(href="/blocks", class="btn btn-primary btn-block") See more + + hr + + div(class="text-center") + :markdown-it + More information available on Website: [http://vivocoin.net](http://vivocoin.net) + + [© 2021 Vivocoin](http://vivocoin.net/) diff --git a/views/layout.pug b/views/layout.pug new file mode 100755 index 0000000..b6f4c62 --- /dev/null +++ b/views/layout.pug @@ -0,0 +1,74 @@ +doctype html +html + head + meta(charset="utf-8") + meta(name="viewport", content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0, shrink-to-fit=no") + + link(rel="stylesheet", href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css", integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb", crossorigin="anonymous") + link(rel="stylesheet", href="https://netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css") + link(rel="stylesheet", href="https://fonts.googleapis.com/css?family=Lato|Open+Sans|Cousine") + link(rel="stylesheet", href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css") + link(rel='stylesheet', href='/css/styling.css') + + link(rel="icon", type="image/png", sizes="32x32", href="/img/favicons/favicon-32x32.png") + link(rel="icon", type="image/png", sizes="96x96", href="/img/favicons/favicon-96x96.png") + link(rel="icon", type="image/png", sizes="16x16", href="/img/favicons/favicon-16x16.png") + + block headContent + title Vivocoin Explorer + + body + nav(class="navbar navbar-expand-lg navbar-light bg-dark mb-4") + div(class="container") + a(class="navbar-brand", href="/") + span + img(src="/img/logo/logo-64.png", class="header-image") + span Vivocoin Explorer + + button(type="button", class="navbar-toggler navbar-toggler-right", data-toggle="collapse", data-target="#navbarNav") + span(class="navbar-toggler-icon") + + div(class="collapse navbar-collapse", id="navbarNav") + if (client) + ul(class="navbar-nav mr-auto") + if (debug) + li(class="nav-item") + a(href="/terminal", class="nav-link") RPC Terminal + li(class="nav-item") + a(href="/node-info", class="nav-link") Node Info + li(class="nav-item") + a(href="/mempool", class="nav-link") Mempool Info + form(method="post", action="/search", class="form-inline") + div(class="input-group") + input(type="text", class="form-control form-control-sm", name="query", placeholder="block height, block hash, txid", style="width: 250px;") + span(class="input-group-btn") + input(type="submit", class="btn btn-primary", value="Search") + + div(class="container") + if (userMessage) + div(class="alert", class=(userMessageType ? ("alert-" + userMessageType) : "alert-info"), role="alert") + span !{userMessage} + + block content + + div(style="margin-bottom: 30px;") + + script(src="https://code.jquery.com/jquery-3.2.1.min.js", integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=", crossorigin="anonymous") + script(src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js", integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh", crossorigin="anonymous") + script(src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js", integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb", crossorigin="anonymous") + script(src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js", integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1", crossorigin="anonymous") + + script(src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js") + + script(src="https://cdn.ravenjs.com/3.9.1/raven.min.js") + script. + Raven.config('https://0bf20e8357a748cab8aa9d35c0f790dd@sentry.io/130800').install(); + + $(document).ready(function() { + $('[data-toggle="tooltip"]').tooltip(); + $('[data-toggle="popover"]').popover({html:true}); + }); + + hljs.initHighlightingOnLoad(); + + block endOfBody diff --git a/views/mempool.pug b/views/mempool.pug new file mode 100755 index 0000000..1e82b28 --- /dev/null +++ b/views/mempool.pug @@ -0,0 +1,75 @@ +extends layout + +block headContent + title Mempool Info + +block content + h1 Mempool Info + hr + + if (getmempoolinfo) + p Data from RPC command + a(href="https://bitcoin.org/en/developer-reference#getmempoolinfo") getmempoolinfo + + table(class="table") + tr + th(class="table-active properties-header") Transaction Count + td #{getmempoolinfo.size.toLocaleString()} + tr + - var scales = [ {val:1000000000, name:"GB"}, {val:1000000, name:"MB"}, {val:1000, name:"kB"} ]; + - var scaleDone = false; + th(class="table-active properties-header") Tx Size + td(class="monospace") + span #{getmempoolinfo.bytes.toLocaleString()} bytes + each item in scales + if (!scaleDone) + - var fraction = Math.floor(getmempoolinfo.bytes / item.val); + if (fraction >= 1) + - scaleDone = true; + span(class="text-muted") (#{fraction} #{item.name}) + tr + - var scales = [ {val:1000000000, name:"GB"}, {val:1000000, name:"MB"}, {val:1000, name:"kB"} ]; + - var scaleDone = false; + th(class="table-active properties-header") Total Size + td(class="monospace") + span #{getmempoolinfo.usage.toLocaleString()} bytes + each item in scales + if (!scaleDone) + - var fraction = Math.floor(getmempoolinfo.usage / item.val); + if (fraction >= 1) + - scaleDone = true; + span(class="text-muted") (#{fraction} #{item.name}) + tr + th(class="table-active properties-header") Max Size + td(class="monospace") #{getmempoolinfo.maxmempool.toLocaleString()} + tr + th(class="table-active properties-header") Min Fee + td(class="monospace") #{getmempoolinfo.mempoolminfee.toLocaleString()} + tr + th(class="table-active properties-header") Total Fees + td(class="monospace") #{mempoolstats.totalFee.toLocaleString()} + + + h4 Transaction count by fee level + hr + + if (false) + #{JSON.stringify(mempoolstats)} + + - var feeBucketLabels = [ "0 - 5 sat/B", "6 - 10 sat/B", "11 - 25 sat/B", "26 - 50 sat/B", "51 - 75 sat/B", "76 - 100 sat/B", "101 - 150 sat/B", "151+ sat/B" ]; + - var feeBucketTxCounts = [ mempoolstats.fee_0_5, mempoolstats.fee_6_10, mempoolstats.fee_11_25, mempoolstats.fee_26_50, mempoolstats.fee_51_75, mempoolstats.fee_76_100, mempoolstats.fee_101_150, mempoolstats.fee_151_max ]; + - var bgColors = [ "bg-primary", "bg-success", "bg-info", "bg-warning", "bg-danger", "bg-primary progress-bar-striped", "bg-success progress-bar-striped", "bg-info progress-bar-striped" ]; + + table(class="table") + each feeBucketLabel, index in feeBucketLabels + tr + th(class=("properties-header " + bgColors[index])) #{feeBucketLabel} + td(class="monospace") #{feeBucketTxCounts[index].toLocaleString()} + + div(class="progress") + each txCount, index in feeBucketTxCounts + - var percent = 100 * txCount / getmempoolinfo.size; + + div(class=("progress-bar " + bgColors[index]), role="progressbar", style=("width: " + percent + "%;"), aria-valuenow=percent, aria-valuemin="0", aria-valuemax="100") + span #{txCount} + diff --git a/views/node-info.pug b/views/node-info.pug new file mode 100755 index 0000000..f99ec17 --- /dev/null +++ b/views/node-info.pug @@ -0,0 +1,75 @@ +extends layout + +block headContent + title Node Info + +block content + h1 Node Info + hr + + if (getinfo) + //p Data from RPC command + // a(href="https://bitcoin.org/en/developer-reference#getinfo") getinfo + + if (false) + pre + code #{JSON.stringify(getinfo, null, 4)} + + if (true) + table(class="table") + tr + th(class="table-active properties-header") BTC Price + include btcprice + tr + th(class="table-active properties-header") Hash amount + td(class="monospace") #{getmininginfo.networkhashps.toLocaleString()} + tr + th(class="table-active properties-header") Block Count + td(class="monospace") #{getinfo.blocks} + tr + th(class="table-active properties-header") Version + td(class="monospace") #{getinfo.version} + tr + th(class="table-active properties-header") Protocol Version + td(class="monospace") #{getinfo.protocolversion} + tr + th(class="table-active properties-header") Connections + td(class="monospace") #{getinfo.connections.toLocaleString()} + tr + th(class="table-active properties-header") Testnet? + td(class="monospace") #{getinfo.testnet} + tr + th(class="table-active properties-header") Errors + td(class="monospace") #{getinfo.errors} + + + //tr + // th(class="table-active properties-header") Hash Amount + // td(class="monospace") #{getmininginfo.networkhashps} + + tr + - var scales = [ {val:1000000000000000, name:"quadrillion"}, {val:1000000000000, name:"trillion"}, {val:1000000000, name:"billion"}, {val:1000000, name:"million"} ]; + - var scaleDone = false; + th(class="table-active properties-header") Difficulty + td(class="monospace") + span #{getinfo.difficulty.toLocaleString()} + each item in scales + if (!scaleDone) + - var fraction = Math.floor(getinfo.difficulty / item.val); + if (fraction >= 1) + - scaleDone = true; + span(class="text-muted") (#{fraction} #{item.name}) + //tr + // th(class="table-active properties-header") Nodes + // td + // a(href="https://smartcash.bitcoiner.me/smartnodes/worldmap/") + // img(src="https://smartcash.bitcoiner.me/smartnodes/worldmap/map.php") + + //if (getmininginfo) + // table(class="table") + // tr + // th(class="table-active properties-header") Hash Amount + // td(class="monospace") #{getmininginfo.networkhashps} + tr + th(class="table-active properties-header") Version + td(class="monospace") #{getinfo.version} diff --git a/views/terminal.pug b/views/terminal.pug new file mode 100755 index 0000000..d5762f0 --- /dev/null +++ b/views/terminal.pug @@ -0,0 +1,54 @@ +extends layout + +block content + h1 Terminal + hr + + :markdown-it + Use this interactive terminal to send RPC commands to your node. Results will be shown inline. + + div(class="card mb-3") + div(class="card-body") + form(id="terminal-form") + div(class="form-group") + label(for="input-cmd") Command + input(type="text", id="input-cmd", name="cmd", class="form-control") + + input(type="submit", class="btn btn-primary btn-block", value="Send") + + hr + + div(id="terminal-output") + +block endOfBody + script. + $(document).ready(function() { + $("#terminal-form").submit(function(e) { + e.preventDefault(); + + var cmd = $("#input-cmd").val() + + var postData = {}; + postData.cmd = cmd; + + $.post( + "/terminal", + postData, + function(response, textStatus, jqXHR) { + var t = new Date().getTime(); + + $("#terminal-output").prepend("
" + cmd + "
" + response + "
"); + console.log(response); + + $("#output-" + t + " pre code").each(function(i, block) { + hljs.highlightBlock(block); + }); + + return false; + }) + .done(function(data) { + }); + + return false; + }); + }); \ No newline at end of file diff --git a/views/transaction.pug b/views/transaction.pug new file mode 100755 index 0000000..0535de0 --- /dev/null +++ b/views/transaction.pug @@ -0,0 +1,267 @@ +extends layout + +block headContent + title Transaction #{txid} + style. + .field { + word-wrap: break-word; + } + + +block content + h1(class="h2") Transaction + br + small(class="monospace") #{txid} + hr + + ul(class='nav nav-tabs mb-3') + li(class="nav-item") + a(data-toggle="tab", href="#tab-summary", class="nav-link active", role="tab") Summary + li(class="nav-item") + a(data-toggle="tab", href="#tab-scripts", class="nav-link", role="tab") Scripts + li(class="nav-item") + a(data-toggle="tab", href="#tab-raw", class="nav-link", role="tab") Raw + + - DecimalRounded = Decimal.clone({ precision: 4, rounding: 2 }) + + - var totalInputValue = new Decimal(0); + if (result.getrawtransaction.vin[0].coinbase) + - totalInputValue = totalInputValue.plus(new Decimal(utils.getBlockReward(result.getblock.height))); + each txInput, txInputIndex in result.txInputs + if (txInput) + - var vout = txInput.vout[result.getrawtransaction.vin[txInputIndex].vout]; + if (vout.value) + - totalInputValue = totalInputValue.plus(new Decimal(vout.value)); + + - var totalOutputValue = new Decimal(0); + each vout, voutIndex in result.getrawtransaction.vout + - totalOutputValue = totalOutputValue.plus(new Decimal(vout.value)); + + div(class="tab-content") + div(id="tab-summary", class="tab-pane active", role="tabpanel") + if (txid == "00000f6be3e151f9082a2b82c2916192a791090015b80979934a45d625460d62") + div(class="alert alert-warning", style="padding-bottom: 0;") + h4(class="alert-heading h5") This transaction doesn't really exist! + :markdown-it + This is the coinbase transaction of the [Vivocoin Genesis Block](/block/00000f6be3e151f9082a2b82c2916192a791090015b80979934a45d625460d62). For more background about this special-case transaction, you can read [this brief discussion](https://github.com/bitcoin/bitcoin/issues/3303) among some of the [Vivocoin Core](https://bitcoin.org) developers. + + table(class="table") + tr + th(class="table-active properties-header") Included in Block + td(class="monospace") + if (result.getblock) + a(href=("/block/" + result.getrawtransaction.blockhash)) #{result.getrawtransaction.blockhash} + if (result.getblock.height) + span(class="text-muted") (#{result.getblock.height.toLocaleString()}) + else + span N/A + span(class="text-muted") (unconfirmed) + + tr + th(class="table-active properties-header") Timestamp + if (result.getrawtransaction.time) + td(class="monospace") #{moment.utc(new Date(result.getrawtransaction["time"] * 1000)).format("Y-MM-DD HH:mm:ss")} (utc) + else + td(class="monospace") N/A + span(class="text-muted") (unconfirmed) + + //tr + // th(class="table-active properties-header") Transaction ID + // td #{txid} + + tr + th(class="table-active properties-header") Version + td(class="monospace") #{result.getrawtransaction.version} + + if (result.getrawtransaction.locktime > 0) + tr + th(class="table-active properties-header") + span Locktime + td(class="monospace") + if (result.getrawtransaction.locktime < 500000000) + span Spendable in block + a(href=("/block-height/" + result.getrawtransaction.locktime)) #{result.getrawtransaction.locktime} + span or later - ( + a(href="https://bitcoin.org/en/developer-guide#locktime-and-sequence-number", title="Locktime documentation") + span docs + i(class="fa fa-external-link") + span ) + else + span Spendable after #{moment.utc(new Date(result.getrawtransaction.locktime * 1000)).format("Y-MM-DD HH:mm:ss")} (utc) - ( + a(href="https://bitcoin.org/en/developer-guide#locktime-and-sequence-number", title="Locktime documentation") + span docs + i(class="fa fa-external-link") + span ) + + tr + th(class="table-active properties-header") Confirmations + td(class="monospace") + if (!result.getrawtransaction.confirmations || result.getrawtransaction.confirmations == 0) + strong(class="text-danger") 0 (unconfirmed) + else if (result.getrawtransaction.confirmations < 6) + strong(class="text-warning") #{result.getrawtransaction.confirmations} + else + strong(class="text-success") #{result.getrawtransaction.confirmations.toLocaleString()} + + if (result.getrawtransaction.vin[0].coinbase) + tr + th(class="table-active properties-header") Total Network Fees + //td(class="monospace") Σ #{new Decimal(totalOutputValue).minus(totalInputValue)} + td(class="monospace") Σ #{(totalOutputValue - totalInputValue)} + else + tr + th(class="table-active properties-header") Network Fee Paid + td(class="monospace") + strong #{new Decimal(totalInputValue).minus(totalOutputValue)} + //span(class="text-muted") (#{totalInputValue} - #{totalOutputValue}) + //br + //span ~#{new DecimalRounded(totalInputValue).minus(totalOutputValue).dividedBy(result.getrawtransaction.size).times(100000000)} sat/B + + if (result.getrawtransaction.vin[0].coinbase) + div(class="card mb-3") + div(class="card-header") + h2(class="h5 mb-0") Coinbase + div(class="card-body") + h6 Hex + div(style="background-color: #fafafa; padding: 5px 10px;", class="mb-3") + span(class="monospace word-wrap") #{result.getrawtransaction.vin[0].coinbase} + + h6 Decoded + div(style="background-color: #fafafa; padding: 5px 10px;", class="mb-3") + span(class="monospace word-wrap") #{utils.hex2ascii(result.getrawtransaction.vin[0].coinbase)} + + div(class="card mb-3") + div(class="card-header") + div(class="row") + div(class="col-md-6") + h2(class="h5 mb-0") Input (#{result.getrawtransaction.vin.length.toLocaleString()}) + div(class="col-md-6") + h2(class="h5 mb-0") Output (#{result.getrawtransaction.vout.length.toLocaleString()}) + div(class="card-body") + div(class="row") + div(class="col-md-6") + if (result.txInputs) + table(class="table mb-0") + thead + tr + th(style="width: 40px;") + th Input + th Amount + tbody + + if (result.getrawtransaction.vin[0].coinbase) + tr + th 1 + td + span(class="tag monospace") coinbase + span(class="monospace") Newly minted VIVO + td(class="monospace") Σ #{utils.getBlockReward(result.getblock.height)} + + each txInput, txInputIndex in result.txInputs + if (txInput) + - var vout = txInput.vout[result.getrawtransaction.vin[txInputIndex].vout]; + + tr + th #{(txInputIndex + 1)} + //pre + // code #{JSON.stringify(txInput)} + + td + if (vout.scriptPubKey && vout.scriptPubKey.addresses) + span(class="monospace") #{vout.scriptPubKey.addresses[0]} + br + span(class="monospace text-muted") via tx + a(href=("/tx/" + txInput.txid + "#output-" + result.getrawtransaction.vin[txInputIndex].vout), class="monospace") #{txInput.txid.substring(0, 14)}..., Output ##{result.getrawtransaction.vin[txInputIndex].vout + 1} + td + if (vout.value) + span(class="monospace") Σ #{vout.value} + + tr + td + td + td + strong(class="monospace") Σ #{totalInputValue} + + + div(class="col-md-6") + table(class="table mb-0") + thead + tr + th + th Output + th Amount + + tbody + each vout, voutIndex in result.getrawtransaction.vout + tr + th #{(voutIndex + 1)} + td + if (vout.scriptPubKey) + if (vout.scriptPubKey.addresses) + a(id="output-" + voutIndex) + span(class="monospace") #{vout.scriptPubKey.addresses[0]} + + else if (vout.scriptPubKey.hex && vout.scriptPubKey.hex.startsWith('6a24aa21a9ed')) + span(class="monospace") Segregated Witness committment - + a(href="https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#commitment-structure") docs + i(class="fa fa-external-link") + else if (vout.scriptPubKey.asm && vout.scriptPubKey.asm.startsWith('OP_RETURN ')) + span(class="monospace") OP_RETURN: + span(class="monospace text-muted") #{utils.hex2ascii(vout.scriptPubKey.asm.substring("OP_RETURN ".length))} + td + span(class="monospace") Σ #{vout.value} + + tr + td + td + td + strong(class="monospace") Σ #{totalOutputValue} + + div(id="tab-scripts", class="tab-pane", role="tabpanel") + h3 Input Scripts + table(class="table table-striped") + thead + tr + th(style="width: 50px;") + th Script Sig (asm) + tbody + each vin, vinIndex in result.getrawtransaction.vin + tr + th #{vinIndex + 1} + td + if (vin.scriptSig && vin.scriptSig.asm) + span(class="word-wrap monospace") #{vin.scriptSig.asm} + + else if (vin.coinbase) + div(style="line-height: 1.75em;") + span(class="tag") coinbase + br + span(class="word-wrap monospace") #{vin.coinbase} + br + span(class="word-wrap monospace text-muted") (decoded) #{utils.hex2ascii(vin.coinbase)} + + h3 Output Scripts + table(class="table table-striped") + thead + tr + th(style="width: 50px;") + th Script Pub Key (asm) + tbody + each vout, voutIndex in result.getrawtransaction.vout + tr + th #{voutIndex + 1} + td + if (vout.scriptPubKey && vout.scriptPubKey.asm) + span(class="word-wrap monospace") #{vout.scriptPubKey.asm} + if (vout.scriptPubKey.asm.startsWith("OP_RETURN")) + br + span(class="word-wrap monospace text-muted") (decoded) #{utils.hex2ascii(vout.scriptPubKey.asm)} + + div(id="tab-raw", class="tab-pane", role="tabpanel") + div(class="highlight") + pre + code(class="language-json", data-lang="json") #{JSON.stringify(result.getrawtransaction, null, 4)} + + //pre #{JSON.stringify(result.txInputs, null, 4)} + +