From 530f8c612da6c51261905c2f6861a23517ea18e4 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Fri, 8 Oct 2021 16:54:27 +0300 Subject: [PATCH 1/5] feat: add patched Console transport for winston to make it work in the browser --- src/logger/console.js | 123 +++++++++++++++++++++++++++++ src/{logger.js => logger/index.js} | 9 ++- 2 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 src/logger/console.js rename src/{logger.js => logger/index.js} (80%) diff --git a/src/logger/console.js b/src/logger/console.js new file mode 100644 index 000000000..91c926b5f --- /dev/null +++ b/src/logger/console.js @@ -0,0 +1,123 @@ +/* eslint-disable */ +/* + * console.js: Transport for outputting to the console. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +const os = require('os'); +// eslint-disable-next-line import/no-extraneous-dependencies +const { LEVEL, MESSAGE } = require('triple-beam'); +// eslint-disable-next-line import/no-extraneous-dependencies +const TransportStream = require('winston-transport'); + +/** + * Transport for outputting to the console. + * @type {Console} + * @extends {TransportStream} + */ +module.exports = class Console extends TransportStream { + /** + * Constructor function for the Console transport object responsible for + * persisting log messages and metadata to a terminal or TTY. + * @param {!Object} [options={}] - Options for this instance. + */ + constructor(options = {}) { + super(options); + + // Expose the name of this Transport on the prototype + this.name = options.name || 'console'; + this.stderrLevels = this._stringArrayToSet(options.stderrLevels); + this.consoleWarnLevels = this._stringArrayToSet(options.consoleWarnLevels); + this.eol = options.eol || os.EOL; + + this.setMaxListeners(30); + } + + /** + * Core logging method exposed to Winston. + * @param {Object} info - TODO: add param description. + * @param {Function} callback - TODO: add param description. + * @returns {undefined} + */ + log(info, callback) { + setTimeout(() => this.emit('logged', info), 1); + + // Remark: what if there is no raw...? + if (this.stderrLevels[info[LEVEL]]) { + if (console._stderr) { + // Node.js maps `process.stderr` to `console._stderr`. + // eslint-disable-next-line no-underscore-dangle + console._stderr.write(`${info[MESSAGE]}${this.eol}`); + } else { + // console.error adds a newline + console.error(info[MESSAGE]); + } + + if (callback) { + callback(); // eslint-disable-line callback-return + } + return; + } if (this.consoleWarnLevels[info[LEVEL]]) { + // eslint-disable-next-line no-underscore-dangle + if (console._stderr) { + // Node.js maps `process.stderr` to `console._stderr`. + // in Node.js console.warn is an alias for console.error + console._stderr.write(`${info[MESSAGE]}${this.eol}`); + } else { + // console.warn adds a newline + console.warn(info[MESSAGE]); + } + + if (callback) { + callback(); // eslint-disable-line callback-return + } + return; + } + + // eslint-disable-next-line no-underscore-dangle + if (console._stdout) { + // Node.js maps `process.stdout` to `console._stdout`. + // eslint-disable-next-line no-underscore-dangle + console._stdout.write(`${info[MESSAGE]}${this.eol}`); + } else { + // console.log adds a newline. + console.log(info[MESSAGE]); + } + + if (callback) { + callback(); // eslint-disable-line callback-return + } + } + + /** + * Returns a Set-like object with strArray's elements as keys (each with the + * value true). + * @param {Array} strArray - Array of Set-elements as strings. + * @param {?string} [errMsg] - Custom error message thrown on invalid input. + * @returns {Object} - TODO: add return description. + * @private + */ + // eslint-disable-next-line no-underscore-dangle + _stringArrayToSet(strArray, errMsg) { + if (!strArray) return {}; + + // eslint-disable-next-line no-param-reassign + errMsg = errMsg || 'Cannot make set from type other than Array of string elements'; + + if (!Array.isArray(strArray)) { + throw new Error(errMsg); + } + + return strArray.reduce((set, el) => { + if (typeof el !== 'string') { + throw new Error(errMsg); + } + // eslint-disable-next-line no-param-reassign + set[el] = true; + + return set; + }, {}); + } +}; diff --git a/src/logger.js b/src/logger/index.js similarity index 80% rename from src/logger.js rename to src/logger/index.js index c6e4970b7..3f0193fcc 100644 --- a/src/logger.js +++ b/src/logger/index.js @@ -1,5 +1,6 @@ const util = require('util'); const winston = require('winston'); +const Console = require('./console'); const LOG_LEVEL = process.env.LOG_LEVEL || 'info'; @@ -11,10 +12,10 @@ const LOG_LEVEL = process.env.LOG_LEVEL || 'info'; // debug 4 // silly 5 -const logger = winston.createLogger({ +const index = winston.createLogger({ level: LOG_LEVEL, transports: [ - new winston.transports.Console({ + new Console({ format: winston.format.combine( { transform: (info) => { @@ -35,6 +36,6 @@ const logger = winston.createLogger({ ], }); -logger.verbose(`Logger uses "${LOG_LEVEL}" level`, { level: LOG_LEVEL }); +index.verbose(`Logger uses "${LOG_LEVEL}" level`, { level: LOG_LEVEL }); -module.exports = logger; +module.exports = index; From fb8656f580d0823beb9c154ccaac4ce9baa2bf43 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Fri, 8 Oct 2021 16:57:21 +0300 Subject: [PATCH 2/5] rename index back to logger --- src/logger/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/logger/index.js b/src/logger/index.js index 3f0193fcc..86f2fde46 100644 --- a/src/logger/index.js +++ b/src/logger/index.js @@ -12,7 +12,7 @@ const LOG_LEVEL = process.env.LOG_LEVEL || 'info'; // debug 4 // silly 5 -const index = winston.createLogger({ +const logger = winston.createLogger({ level: LOG_LEVEL, transports: [ new Console({ @@ -36,6 +36,6 @@ const index = winston.createLogger({ ], }); -index.verbose(`Logger uses "${LOG_LEVEL}" level`, { level: LOG_LEVEL }); +logger.verbose(`Logger uses "${LOG_LEVEL}" level`, { level: LOG_LEVEL }); -module.exports = index; +module.exports = logger; From cec479a0812ff7fba606c37cf055f6e4eebe0b8a Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Fri, 8 Oct 2021 17:11:09 +0300 Subject: [PATCH 3/5] add setImmeadiate polyfill --- package-lock.json | 7 ++- package.json | 3 +- src/logger/console.js | 123 ------------------------------------------ src/logger/index.js | 7 ++- 4 files changed, 10 insertions(+), 130 deletions(-) delete mode 100644 src/logger/console.js diff --git a/package-lock.json b/package-lock.json index 2ce3282c3..ac25e8160 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "crypto-js": "^4.0.0", "lodash": "^4.17.19", "pbkdf2": "^3.1.1", + "setimmediate": "^1.0.5", "winston": "^3.2.1" }, "devDependencies": { @@ -8149,8 +8150,7 @@ "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" }, "node_modules/setprototypeof": { "version": "1.1.1", @@ -17441,8 +17441,7 @@ "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" }, "setprototypeof": { "version": "1.1.1", diff --git a/package.json b/package.json index 56aece36a..21491af0c 100644 --- a/package.json +++ b/package.json @@ -45,10 +45,10 @@ "crypto-js": "^4.0.0", "lodash": "^4.17.19", "pbkdf2": "^3.1.1", + "setimmediate": "^1.0.5", "winston": "^3.2.1" }, "devDependencies": { - "node-inspect-extracted": "1.0.7", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "dotenv-safe": "^8.2.0", @@ -64,6 +64,7 @@ "karma-webpack": "^4.0.2", "localforage": "^1.7.3", "mocha": "^7.2.0", + "node-inspect-extracted": "1.0.7", "nyc": "^15.0.0", "sinon": "^9.0.3", "webpack": "^4.43.0", diff --git a/src/logger/console.js b/src/logger/console.js deleted file mode 100644 index 91c926b5f..000000000 --- a/src/logger/console.js +++ /dev/null @@ -1,123 +0,0 @@ -/* eslint-disable */ -/* - * console.js: Transport for outputting to the console. - * - * (C) 2010 Charlie Robbins - * MIT LICENCE - */ - -const os = require('os'); -// eslint-disable-next-line import/no-extraneous-dependencies -const { LEVEL, MESSAGE } = require('triple-beam'); -// eslint-disable-next-line import/no-extraneous-dependencies -const TransportStream = require('winston-transport'); - -/** - * Transport for outputting to the console. - * @type {Console} - * @extends {TransportStream} - */ -module.exports = class Console extends TransportStream { - /** - * Constructor function for the Console transport object responsible for - * persisting log messages and metadata to a terminal or TTY. - * @param {!Object} [options={}] - Options for this instance. - */ - constructor(options = {}) { - super(options); - - // Expose the name of this Transport on the prototype - this.name = options.name || 'console'; - this.stderrLevels = this._stringArrayToSet(options.stderrLevels); - this.consoleWarnLevels = this._stringArrayToSet(options.consoleWarnLevels); - this.eol = options.eol || os.EOL; - - this.setMaxListeners(30); - } - - /** - * Core logging method exposed to Winston. - * @param {Object} info - TODO: add param description. - * @param {Function} callback - TODO: add param description. - * @returns {undefined} - */ - log(info, callback) { - setTimeout(() => this.emit('logged', info), 1); - - // Remark: what if there is no raw...? - if (this.stderrLevels[info[LEVEL]]) { - if (console._stderr) { - // Node.js maps `process.stderr` to `console._stderr`. - // eslint-disable-next-line no-underscore-dangle - console._stderr.write(`${info[MESSAGE]}${this.eol}`); - } else { - // console.error adds a newline - console.error(info[MESSAGE]); - } - - if (callback) { - callback(); // eslint-disable-line callback-return - } - return; - } if (this.consoleWarnLevels[info[LEVEL]]) { - // eslint-disable-next-line no-underscore-dangle - if (console._stderr) { - // Node.js maps `process.stderr` to `console._stderr`. - // in Node.js console.warn is an alias for console.error - console._stderr.write(`${info[MESSAGE]}${this.eol}`); - } else { - // console.warn adds a newline - console.warn(info[MESSAGE]); - } - - if (callback) { - callback(); // eslint-disable-line callback-return - } - return; - } - - // eslint-disable-next-line no-underscore-dangle - if (console._stdout) { - // Node.js maps `process.stdout` to `console._stdout`. - // eslint-disable-next-line no-underscore-dangle - console._stdout.write(`${info[MESSAGE]}${this.eol}`); - } else { - // console.log adds a newline. - console.log(info[MESSAGE]); - } - - if (callback) { - callback(); // eslint-disable-line callback-return - } - } - - /** - * Returns a Set-like object with strArray's elements as keys (each with the - * value true). - * @param {Array} strArray - Array of Set-elements as strings. - * @param {?string} [errMsg] - Custom error message thrown on invalid input. - * @returns {Object} - TODO: add return description. - * @private - */ - // eslint-disable-next-line no-underscore-dangle - _stringArrayToSet(strArray, errMsg) { - if (!strArray) return {}; - - // eslint-disable-next-line no-param-reassign - errMsg = errMsg || 'Cannot make set from type other than Array of string elements'; - - if (!Array.isArray(strArray)) { - throw new Error(errMsg); - } - - return strArray.reduce((set, el) => { - if (typeof el !== 'string') { - throw new Error(errMsg); - } - // eslint-disable-next-line no-param-reassign - set[el] = true; - - return set; - }, {}); - } -}; diff --git a/src/logger/index.js b/src/logger/index.js index 86f2fde46..e813a7b10 100644 --- a/src/logger/index.js +++ b/src/logger/index.js @@ -1,6 +1,9 @@ const util = require('util'); const winston = require('winston'); -const Console = require('./console'); +// Default winston transport requires setImmediate to work, so +// polyfill included here. Making it work with webpack is rather tricky, so it is used as per +// documentation: https://github.com/YuzuJS/setImmediate#usage +require('setimmediate'); const LOG_LEVEL = process.env.LOG_LEVEL || 'info'; @@ -15,7 +18,7 @@ const LOG_LEVEL = process.env.LOG_LEVEL || 'info'; const logger = winston.createLogger({ level: LOG_LEVEL, transports: [ - new Console({ + new winston.transports.Console({ format: winston.format.combine( { transform: (info) => { From 5b9c9d23d2d5c3b26b0d367ba05afbfd5fb1e5a9 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Fri, 8 Oct 2021 17:15:01 +0300 Subject: [PATCH 4/5] moved polyfill to the top of the file --- src/logger/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/logger/index.js b/src/logger/index.js index e813a7b10..64dc8ac05 100644 --- a/src/logger/index.js +++ b/src/logger/index.js @@ -1,9 +1,9 @@ -const util = require('util'); -const winston = require('winston'); // Default winston transport requires setImmediate to work, so // polyfill included here. Making it work with webpack is rather tricky, so it is used as per // documentation: https://github.com/YuzuJS/setImmediate#usage require('setimmediate'); +const util = require('util'); +const winston = require('winston'); const LOG_LEVEL = process.env.LOG_LEVEL || 'info'; From 130db5d958781654c4ecebfaf53b0e1c92ee75ff Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Fri, 8 Oct 2021 17:16:08 +0300 Subject: [PATCH 5/5] moved polyfill even further --- src/index.js | 4 ++++ src/logger/index.js | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/index.js b/src/index.js index 784e1caba..2fa9d8a9e 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,7 @@ +// Default winston transport requires setImmediate to work, so +// polyfill included here. Making it work with webpack is rather tricky, so it is used as per +// documentation: https://github.com/YuzuJS/setImmediate#usage +require('setimmediate'); const Wallet = require('./types/Wallet/Wallet'); const Account = require('./types/Account/Account'); const Identities = require('./types/Identities/Identities'); diff --git a/src/logger/index.js b/src/logger/index.js index 64dc8ac05..c6e4970b7 100644 --- a/src/logger/index.js +++ b/src/logger/index.js @@ -1,7 +1,3 @@ -// Default winston transport requires setImmediate to work, so -// polyfill included here. Making it work with webpack is rather tricky, so it is used as per -// documentation: https://github.com/YuzuJS/setImmediate#usage -require('setimmediate'); const util = require('util'); const winston = require('winston');