diff --git a/src/utils/log.ts b/src/utils/log.ts index 0a3ff50..a236eaf 100644 --- a/src/utils/log.ts +++ b/src/utils/log.ts @@ -1,4 +1,5 @@ import chalk from "chalk"; +import { decycle } from "./stringify"; class Logger { info(message: any) { @@ -10,10 +11,12 @@ class Logger { return; } console.log( - JSON.stringify({ - action: action, - data: message, - }) + JSON.stringify( + decycle({ + action: action, + data: message, + }) + ) ); } diff --git a/src/utils/stringify.ts b/src/utils/stringify.ts new file mode 100644 index 0000000..f7cdd46 --- /dev/null +++ b/src/utils/stringify.ts @@ -0,0 +1,45 @@ +const isArray = (value: any) => Array.isArray(value); + +const isObject = (value: any) => + Object.prototype.toString.call(value).slice(8, -1) === "Object"; + +const validate = (value: any) => { + if (typeof value === "undefined") { + throw new Error("This method requires one parameter"); + } + + if (!isArray(value) && !isObject(value)) { + throw new TypeError("This method only accepts arrays and objects"); + } +}; + +const findRef = (ref: any, visitedRefs: any) => + Object.keys(visitedRefs).find((key) => visitedRefs[key] === ref); + +export const decycle = (arg: any) => { + validate(arg); + + const visitedRefs: any = {}; + + const recurs = (value: any, path = "$") => { + const ref = findRef(value, visitedRefs); + if (ref) { + return { $ref: ref }; + } + if (isArray(value) || isObject(value)) { + visitedRefs[path] = value; + + if (isArray(value)) { + return value.map((elem: any, i: any) => recurs(elem, `${path}[${i}]`)); + } + + return Object.keys(value).reduce((accum: any, key: any) => { + accum[key] = recurs(value[key], `${path}.${key}`); + + return accum; + }, {}); + } + return value; + }; + return recurs(arg); +}; \ No newline at end of file