Last active
July 7, 2020 18:55
-
-
Save gianpaj/63e04baed150f30b8976c16b16a0010c to your computer and use it in GitHub Desktop.
console.table for mongo shell - v1.0.2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// console.table for mongo shell - v1.0.2 | |
// https://gist.github.com/gianpaj/63e04baed150f30b8976c16b16a0010c | |
// originally from 447dc8b on 18 Apr 2015 | |
// https://github.com/chinchang/konsole.table/blob/447dc8be4bcb463865f0527ed6aef4da864d6558/index.js | |
var SEPARATOR = '│'; | |
/** | |
* Repeat provided string a given no. of times. | |
* @param {number} amount Number of times to repeat. | |
* @param {string} str Character(s) to repeat | |
* @return {string} Repeated string. | |
*/ | |
function repeatString(amount, str) { | |
str = str || ' '; | |
return Array.apply(0, Array(amount)).join(str); | |
} | |
/** | |
* Formats certain type of values for more readability. | |
* @param {...} value Value to format. | |
* @param {Boolean} isHeaderValue Is this a value in the table header. | |
* @return {string} Formatted value. | |
*/ | |
function getFormattedString(value, isHeaderValue) { | |
if (isHeaderValue) {} else if (typeof value === 'string') { | |
// Wrap strings in inverted commans. | |
return '"' + value.replace(/\s/g, '\\n') + '"'; | |
} else if (typeof value === 'function') { | |
// Just show `function` for a function. | |
return 'function'; | |
} else if (typeof value === 'object') { | |
// Just show `function` for a function. | |
return JSON.stringify(value); | |
} else if (typeof value === 'undefined') { | |
return ''; | |
} | |
return value + ''; | |
} | |
/** | |
* Colorize and format given value. | |
* @param {...} value Value to colorize. | |
* @param {Boolean} isHeaderValue Is this a value in the table header. | |
* @return {string} Colorized + formatted value. | |
*/ | |
function getColoredAndFormattedString(value, isHeaderValue) { | |
var color; | |
if (isHeaderValue) {} else if (typeof value === 'number' || typeof value === 'boolean') { | |
color = 'blue'; | |
} else if (typeof value === 'string') { | |
color = 'red'; | |
} | |
value = getFormattedString(value, isHeaderValue); | |
if (color) { | |
return colorize(value, { | |
color: color | |
}); | |
} | |
return value + ''; | |
} | |
function printRows(rows) { | |
if (!rows.length) return; | |
var row, | |
rowString, | |
i, | |
j, | |
padding, | |
tableWidth = 0, | |
numCols = rows[0].length; | |
// For every column, calculate the maximum width in any row. | |
for (j = 0; j < numCols; j++) { | |
var maxLengthForColumn = 0; | |
for (i = 0; i < rows.length; i++) { | |
maxLengthForColumn = Math.max(getFormattedString(rows[i][j], !i || !j).length, maxLengthForColumn); | |
} | |
// Give some more padding to biggest string. | |
maxLengthForColumn += 4; | |
tableWidth += maxLengthForColumn; | |
// Give padding to rows for current column. | |
for (i = 0; i < rows.length; i++) { | |
padding = maxLengthForColumn - getFormattedString(rows[i][j], !i || !j).length; | |
// Distribute padding - 1 in starting, rest at the end. | |
rows[i][j] = ' ' + getColoredAndFormattedString(rows[i][j], !i || !j) + repeatString(padding - 1); | |
} | |
} | |
// HACK: Increase table width just by 1 to make it look good. | |
tableWidth += 1; | |
print('┌' + repeatString(tableWidth - 1, '─') + '┐'); | |
for (i = 0; i < rows.length; i++) { | |
row = rows[i]; | |
rowString = SEPARATOR; | |
for (var j = 0; j < row.length; j++) { | |
rowString += row[j] + SEPARATOR; | |
} | |
print(rowString); | |
// Draw border after table header. | |
if (!i) { | |
print('├' + repeatString(tableWidth - 1, '─') + '┤'); | |
} | |
} | |
print('└' + repeatString(tableWidth - 1, '─') + '┘'); | |
} | |
function table(data, keys) { | |
var i, | |
j, | |
rows = [], | |
row, | |
entry, | |
objKeys, | |
tempData; | |
// Simply print if an `object` type wasn't passed. | |
if (typeof data !== 'object') { | |
print(data); | |
return; | |
} | |
// If an object was passed, create data from its properties instead. | |
if (!(data instanceof Array)) { | |
tempData = []; | |
// `objKeys` are now used to index every row. | |
objKeys = Object.keys(data); | |
for (var key in data) { | |
// Avoiding `hasOwnProperty` check because Chrome shows prototype properties | |
// as well. | |
tempData.push(data[key]); | |
} | |
data = tempData; | |
} | |
if (data.length < 1) return; | |
// Get the keys from first data entry if custom keys are not passed. | |
if (!keys) { | |
keys = Object.keys(data[0]); | |
keys.sort(); | |
} | |
// Create header row. | |
rows.push([]); | |
row = rows[rows.length - 1]; | |
row.push('(index)'); | |
for (i = 0; i < keys.length; i++) { | |
row.push(keys[i]); | |
} | |
for (j = 0; j < data.length; j++) { | |
entry = data[j]; | |
rows.push([]); | |
row = rows[rows.length - 1]; | |
// Push entry for 1st column (index). | |
row.push(objKeys ? objKeys[j] : j); | |
for (i = 0; i < keys.length; i++) { | |
row.push(entry[keys[i]]); | |
} | |
} | |
printRows(rows); | |
} | |
DBQuery.prototype.table = function(...args) { | |
const fieldsObj = getFields(args) | |
let keysArray; | |
if (args.length && args[0]) keysArray = args[0].split(' '); | |
table(this.select(fieldsObj).toArray(), keysArray) | |
}; | |
function getFields(fields) { | |
const obj = {} | |
if (fields.length) { | |
fields = fields.toString().split(' '); | |
for (let i = 0; i < fields.length; i++) { | |
const element = fields[i]; | |
if (element) { | |
obj[element] = 1; | |
} | |
} | |
} | |
return obj | |
} | |
// for quick iteration and to re-run the file after it has been updated, install nodemon globally and use: | |
// | |
// nodemon --quiet --watch consoletable.js --exec 'echo "db.test.find()" | \mongo --shell consoletable.js --quiet' | |
// for testing quickly, uncomment the last line and run: | |
// | |
// $ mongo --quiet consoletable.js | |
// | |
// > db.products.find().limit(10).table('createdAt uuid') | |
// ┌───────────────────────────────────────────────────────┐ | |
// │ (index) │ createdAt │ uuid │ | |
// ├───────────────────────────────────────────────────────┤ | |
// │ 0 │ "2020-06-10T23:37:18.082Z" │ "0rXCpR_AM" │ | |
// │ 1 │ "2020-06-12T14:33:21.834Z" │ "YriJcNVnO" │ | |
// └───────────────────────────────────────────────────────┘ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment