diff --git a/index.js b/index.js new file mode 100644 index 0000000..cecfc36 --- /dev/null +++ b/index.js @@ -0,0 +1,162 @@ + + +// ,---, ,-. +// .' .' `\ ,--/ /| +// ,---.' \ ,--, ,--. :/ | __ ,-. +// | | .`\ | ,'_ /| : : ' / ,' ,'/ /| +// : : | ' | .--. | | : ,---. | ' / ,---. ' | |' | +// | ' ' ; :,'_ /| : . | / \ ' | : / \ | | ,' +// ' | ; . || ' | | . . / / ' | | \ / / |' : / +// | | : | '| | ' | | | . ' / ' : |. \ . ' / || | ' +// ' : | / ; : | : ; ; | ' ; :__ | | ' \ \' ; /|; : | +// | | '` ,/ ' : `--' \' | '.'|' : |--' ' | / || , ; +// ; : .' : , .-./| : :; |,' | : | ---' +// | ,.' `--`----' \ \ / '--' \ \ / +// '---' `----' `----' +// Built by: Fernando Martin Garcia Del Angel +// Built because I was bored + +const StackTrace = require('stacktrace-js') +const utils = require('./utilities/utils') +const QUACK = '🦆 {Quack}' + +/** + * Quacks! + * @param {string} group Counts from a custom group + * @param {boolean} debug Prints the stack or not + * @param {number} level Number of leves of stack to print + * @param {boolean} detailed Prints the complete stack trace + */ +function quack(group = QUACK, debug = false, level = 2, detailed = false) { + console.count(group) + if(debug) { + printStack(level,detailed) + } +} + +/** + * Prints the stack into a simple, readable table + * @param {number} level level of depth to print on the stack + * @param {boolean} detailed prints the source or not + */ +function printStack(level,detailed) { + var stack = StackTrace.getSync().slice(0,level) + for(var i = 0; i < stack.length; i++) { + stack[i] = utils.renameKeys(stack[i],{ + columnNumber: 'column', + lineNumber: 'line', + }) + if (!detailed) { + delete stack[i].source + } + } + console.table(stack) +} + +/** + * Verifies wether value is truthy or not + * @param {any} value Value tested for being truthy + */ +function check(value) { + console.log(QUACK) + let type = '' + console.log('This value is of type %s',typeof value) + console.group() + switch(typeof value) { + case 'number' : + console.log('-> Its value is %f',value) + break + case 'object' : + if(utils.isEmpty(value)) { + console.log('-> Its value is empty') + } else { + if (value[0] == undefined) { + categorizer(value) + } else { + console.log('-> Array type. First value structure:') + categorizer(value[0]) + } + } + break + case 'boolean' : + console.log('-> Its value is %s',value == null ? 'null' : value.toString()) + } + console.groupEnd() +} + +/** + * Starts a timer between two segments of code + * @param {string} group custom grouping variable + */ +function go(group = QUACK) { + console.time(group) +} + +/** + * Stops a previously started timer + * @param {string} group custom grouping variable + */ +function stop(group = QUACK) { + console.timeEnd(group) +} + +/** + * Tests a certain function (Async or not) and checks if the desired result is gotten + * @param {function} testable Function to be tested + * @param {array} args Arguments to pass to the function as an Array (ex. [1,2]) + * @param {any} expectedResult Expected result + * @param {boolean} debug Flag to determine if the stack should be printed + * @param {number} level Level of detail of the stack + * @param {flag} detailed Flag to determine if all data from the stack should be printed + */ +async function test(testable,args,expectedResult, debug = false, level = 3, detailed = false) { + console.log(QUACK) + console.log('Function name: '+testable.name) + console.group('--Result') + let result + switch(testable.constructor.name) { + case 'Function' : + result = testable(...args) + console.log('Function Result: '+result) + console.log('Expected Result: '+expectedResult) + console.log(result === expectedResult ? 'Test successful!' : 'Test failed!') + break + case 'AsyncFunction' : + result = await testable(...args) + console.log('Function Result: '+result) + console.log('Expected Result: '+expectedResult) + console.log(result === expectedResult ? 'Test successful!' : 'Test failed!') + break + default : + console.log('dedault') + break + } + if(debug) { + printStack(level,detailed) + } + console.groupEnd('--Result') +} + +/** + * Categorizes JSON elements + * @param {Object} obj Object element + */ +function categorizer(obj) { + var cats = [] + for (var key in obj) { + cats.push({ + Key : key, + Type : obj[key], + Value : typeof obj[key] + }) + } + console.table(cats) +} + +module.exports = { + quack, + check, + go, + stop, + test +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..feec419 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,58 @@ +{ + "name": "duckerdbg", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, + "error-stack-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.4.tgz", + "integrity": "sha512-fZ0KkoxSjLFmhW5lHbUT3tLwy3nX1qEzMYo8koY1vrsAco53CMT1djnBSeC/wUjTEZRhZl9iRw7PaMaxfJ4wzQ==", + "requires": { + "stackframe": "^1.1.0" + } + }, + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=" + }, + "stack-generator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.4.tgz", + "integrity": "sha512-ha1gosTNcgxwzo9uKTQ8zZ49aUp5FIUW58YHFxCqaAHtE0XqBg0chGFYA1MfmW//x1KWq3F4G7Ug7bJh4RiRtg==", + "requires": { + "stackframe": "^1.1.0" + } + }, + "stackframe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.1.0.tgz", + "integrity": "sha512-Vx6W1Yvy+AM1R/ckVwcHQHV147pTPBKWCRLrXMuPrFVfvBUc3os7PR1QLIWCMhPpRg5eX9ojzbQIMLGBwyLjqg==" + }, + "stacktrace-gps": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.0.3.tgz", + "integrity": "sha512-51Rr7dXkyFUKNmhY/vqZWK+EvdsfFSRiQVtgHTFlAdNIYaDD7bVh21yBHXaNWAvTD+w+QSjxHg7/v6Tz4veExA==", + "requires": { + "source-map": "0.5.6", + "stackframe": "^1.1.0" + } + }, + "stacktrace-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.1.tgz", + "integrity": "sha512-13oDNgBSeWtdGa4/2BycNyKqe+VktCoJ8VLx4pDoJkwGGJVtiHdfMOAj3aW9xTi8oR2v34z9IcvfCvT6XNdNAw==", + "requires": { + "error-stack-parser": "^2.0.4", + "stack-generator": "^2.0.4", + "stacktrace-gps": "^3.0.3" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..bf05ea7 --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "duckerdbg", + "version": "0.0.1", + "description": "Simple console debugger for simple applications", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/a01334390/ducker.git" + }, + "keywords": [ + "debug", + "testing", + "duck" + ], + "author": "Fernando Martin Garcia Del Angel", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/a01334390/ducker/issues" + }, + "homepage": "https://github.com/a01334390/ducker#readme", + "dependencies": { + "clone": "^2.1.2", + "stacktrace-js": "^2.0.1" + } +} diff --git a/test.js b/test.js new file mode 100644 index 0000000..5cb7803 --- /dev/null +++ b/test.js @@ -0,0 +1,27 @@ +const ducker = require('./index') + +function sum (a,b) { + return a + b +} + +async function mult (a,b) { + return await a * b +} + +ducker.go() + ducker.quack([{ 'a': 1 }, { 'a': 2 }]) + ducker.quack('wow', true) + ducker.check(2) + ducker.check({ 'a': 2, 'b': 4 }) + ducker.check([{ 'a': 2, 'b': 4 }, { 'a': 2, 'b': 4 }]) + ducker.check([]) + ducker.check(false) + ducker.check(null) + ducker.quack() + ducker.quack() + ducker.quack() + ducker.quack() + ducker.test(sum,[1,2],3) + ducker.test(mult,[2,5],3,true) +ducker.stop() + diff --git a/utilities/utils.js b/utilities/utils.js new file mode 100644 index 0000000..38902f7 --- /dev/null +++ b/utilities/utils.js @@ -0,0 +1,50 @@ +var clone = require('clone') + +function renameKeys(object, changes) { + if (!changes || typeof changes !== 'object') { + return object + } + + if (Array.isArray(object)) { + const newArray = [] + for (var i = 0; i< object.length; i++) { + newArray.push(renameKeys(object[i], changes)) + } + return newArray + } else { + if (typeof object !== 'object') { + return object + } + var copy = clone(object) + + for (var key in changes) { + if (typeof changes[key] === 'object') { + if (copy.hasOwnProperty(key)) { + copy[key] = renameKeys(copy[key], changes[key]) + continue + } + } + + if (copy.hasOwnProperty(key)) { + var temp = copy[key] + + copy[changes[key]] = temp + delete copy[key] + } + } + return copy + } + } + + function isEmpty(obj) { + for(var key in obj) { + if(obj.hasOwnProperty(key)) + return false; + } + return true; +} + + module.exports = { + renameKeys, + isEmpty + } \ No newline at end of file