core.mjs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. const LogLevels = {
  2. silent: Number.NEGATIVE_INFINITY,
  3. fatal: 0,
  4. error: 0,
  5. warn: 1,
  6. log: 2,
  7. info: 3,
  8. success: 3,
  9. fail: 3,
  10. ready: 3,
  11. start: 3,
  12. box: 3,
  13. debug: 4,
  14. trace: 5,
  15. verbose: Number.POSITIVE_INFINITY
  16. };
  17. const LogTypes = {
  18. // Silent
  19. silent: {
  20. level: -1
  21. },
  22. // Level 0
  23. fatal: {
  24. level: LogLevels.fatal
  25. },
  26. error: {
  27. level: LogLevels.error
  28. },
  29. // Level 1
  30. warn: {
  31. level: LogLevels.warn
  32. },
  33. // Level 2
  34. log: {
  35. level: LogLevels.log
  36. },
  37. // Level 3
  38. info: {
  39. level: LogLevels.info
  40. },
  41. success: {
  42. level: LogLevels.success
  43. },
  44. fail: {
  45. level: LogLevels.fail
  46. },
  47. ready: {
  48. level: LogLevels.info
  49. },
  50. start: {
  51. level: LogLevels.info
  52. },
  53. box: {
  54. level: LogLevels.info
  55. },
  56. // Level 4
  57. debug: {
  58. level: LogLevels.debug
  59. },
  60. // Level 5
  61. trace: {
  62. level: LogLevels.trace
  63. },
  64. // Verbose
  65. verbose: {
  66. level: LogLevels.verbose
  67. }
  68. };
  69. function isObject(value) {
  70. return value !== null && typeof value === "object";
  71. }
  72. function _defu(baseObject, defaults, namespace = ".", merger) {
  73. if (!isObject(defaults)) {
  74. return _defu(baseObject, {}, namespace, merger);
  75. }
  76. const object = Object.assign({}, defaults);
  77. for (const key in baseObject) {
  78. if (key === "__proto__" || key === "constructor") {
  79. continue;
  80. }
  81. const value = baseObject[key];
  82. if (value === null || value === void 0) {
  83. continue;
  84. }
  85. if (merger && merger(object, key, value, namespace)) {
  86. continue;
  87. }
  88. if (Array.isArray(value) && Array.isArray(object[key])) {
  89. object[key] = [...value, ...object[key]];
  90. } else if (isObject(value) && isObject(object[key])) {
  91. object[key] = _defu(
  92. value,
  93. object[key],
  94. (namespace ? `${namespace}.` : "") + key.toString(),
  95. merger
  96. );
  97. } else {
  98. object[key] = value;
  99. }
  100. }
  101. return object;
  102. }
  103. function createDefu(merger) {
  104. return (...arguments_) => (
  105. // eslint-disable-next-line unicorn/no-array-reduce
  106. arguments_.reduce((p, c) => _defu(p, c, "", merger), {})
  107. );
  108. }
  109. const defu = createDefu();
  110. function isPlainObject(obj) {
  111. return Object.prototype.toString.call(obj) === "[object Object]";
  112. }
  113. function isLogObj(arg) {
  114. if (!isPlainObject(arg)) {
  115. return false;
  116. }
  117. if (!arg.message && !arg.args) {
  118. return false;
  119. }
  120. if (arg.stack) {
  121. return false;
  122. }
  123. return true;
  124. }
  125. let paused = false;
  126. const queue = [];
  127. class Consola {
  128. constructor(options = {}) {
  129. const types = options.types || LogTypes;
  130. this.options = defu(
  131. {
  132. ...options,
  133. defaults: { ...options.defaults },
  134. level: _normalizeLogLevel(options.level, types),
  135. reporters: [...options.reporters || []]
  136. },
  137. {
  138. types: LogTypes,
  139. throttle: 1e3,
  140. throttleMin: 5,
  141. formatOptions: {
  142. date: true,
  143. colors: false,
  144. compact: true
  145. }
  146. }
  147. );
  148. for (const type in types) {
  149. const defaults = {
  150. type,
  151. ...this.options.defaults,
  152. ...types[type]
  153. };
  154. this[type] = this._wrapLogFn(defaults);
  155. this[type].raw = this._wrapLogFn(
  156. defaults,
  157. true
  158. );
  159. }
  160. if (this.options.mockFn) {
  161. this.mockTypes();
  162. }
  163. this._lastLog = {};
  164. }
  165. get level() {
  166. return this.options.level;
  167. }
  168. set level(level) {
  169. this.options.level = _normalizeLogLevel(
  170. level,
  171. this.options.types,
  172. this.options.level
  173. );
  174. }
  175. prompt(message, opts) {
  176. if (!this.options.prompt) {
  177. throw new Error("prompt is not supported!");
  178. }
  179. return this.options.prompt(message, opts);
  180. }
  181. create(options) {
  182. const instance = new Consola({
  183. ...this.options,
  184. ...options
  185. });
  186. if (this._mockFn) {
  187. instance.mockTypes(this._mockFn);
  188. }
  189. return instance;
  190. }
  191. withDefaults(defaults) {
  192. return this.create({
  193. ...this.options,
  194. defaults: {
  195. ...this.options.defaults,
  196. ...defaults
  197. }
  198. });
  199. }
  200. withTag(tag) {
  201. return this.withDefaults({
  202. tag: this.options.defaults.tag ? this.options.defaults.tag + ":" + tag : tag
  203. });
  204. }
  205. addReporter(reporter) {
  206. this.options.reporters.push(reporter);
  207. return this;
  208. }
  209. removeReporter(reporter) {
  210. if (reporter) {
  211. const i = this.options.reporters.indexOf(reporter);
  212. if (i >= 0) {
  213. return this.options.reporters.splice(i, 1);
  214. }
  215. } else {
  216. this.options.reporters.splice(0);
  217. }
  218. return this;
  219. }
  220. setReporters(reporters) {
  221. this.options.reporters = Array.isArray(reporters) ? reporters : [reporters];
  222. return this;
  223. }
  224. wrapAll() {
  225. this.wrapConsole();
  226. this.wrapStd();
  227. }
  228. restoreAll() {
  229. this.restoreConsole();
  230. this.restoreStd();
  231. }
  232. wrapConsole() {
  233. for (const type in this.options.types) {
  234. if (!console["__" + type]) {
  235. console["__" + type] = console[type];
  236. }
  237. console[type] = this[type].raw;
  238. }
  239. }
  240. restoreConsole() {
  241. for (const type in this.options.types) {
  242. if (console["__" + type]) {
  243. console[type] = console["__" + type];
  244. delete console["__" + type];
  245. }
  246. }
  247. }
  248. wrapStd() {
  249. this._wrapStream(this.options.stdout, "log");
  250. this._wrapStream(this.options.stderr, "log");
  251. }
  252. _wrapStream(stream, type) {
  253. if (!stream) {
  254. return;
  255. }
  256. if (!stream.__write) {
  257. stream.__write = stream.write;
  258. }
  259. stream.write = (data) => {
  260. this[type].raw(String(data).trim());
  261. };
  262. }
  263. restoreStd() {
  264. this._restoreStream(this.options.stdout);
  265. this._restoreStream(this.options.stderr);
  266. }
  267. _restoreStream(stream) {
  268. if (!stream) {
  269. return;
  270. }
  271. if (stream.__write) {
  272. stream.write = stream.__write;
  273. delete stream.__write;
  274. }
  275. }
  276. pauseLogs() {
  277. paused = true;
  278. }
  279. resumeLogs() {
  280. paused = false;
  281. const _queue = queue.splice(0);
  282. for (const item of _queue) {
  283. item[0]._logFn(item[1], item[2]);
  284. }
  285. }
  286. mockTypes(mockFn) {
  287. const _mockFn = mockFn || this.options.mockFn;
  288. this._mockFn = _mockFn;
  289. if (typeof _mockFn !== "function") {
  290. return;
  291. }
  292. for (const type in this.options.types) {
  293. this[type] = _mockFn(type, this.options.types[type]) || this[type];
  294. this[type].raw = this[type];
  295. }
  296. }
  297. _wrapLogFn(defaults, isRaw) {
  298. return (...args) => {
  299. if (paused) {
  300. queue.push([this, defaults, args, isRaw]);
  301. return;
  302. }
  303. return this._logFn(defaults, args, isRaw);
  304. };
  305. }
  306. _logFn(defaults, args, isRaw) {
  307. if ((defaults.level || 0) > this.level) {
  308. return false;
  309. }
  310. const logObj = {
  311. date: /* @__PURE__ */ new Date(),
  312. args: [],
  313. ...defaults,
  314. level: _normalizeLogLevel(defaults.level, this.options.types)
  315. };
  316. if (!isRaw && args.length === 1 && isLogObj(args[0])) {
  317. Object.assign(logObj, args[0]);
  318. } else {
  319. logObj.args = [...args];
  320. }
  321. if (logObj.message) {
  322. logObj.args.unshift(logObj.message);
  323. delete logObj.message;
  324. }
  325. if (logObj.additional) {
  326. if (!Array.isArray(logObj.additional)) {
  327. logObj.additional = logObj.additional.split("\n");
  328. }
  329. logObj.args.push("\n" + logObj.additional.join("\n"));
  330. delete logObj.additional;
  331. }
  332. logObj.type = typeof logObj.type === "string" ? logObj.type.toLowerCase() : "log";
  333. logObj.tag = typeof logObj.tag === "string" ? logObj.tag : "";
  334. const resolveLog = (newLog = false) => {
  335. const repeated = (this._lastLog.count || 0) - this.options.throttleMin;
  336. if (this._lastLog.object && repeated > 0) {
  337. const args2 = [...this._lastLog.object.args];
  338. if (repeated > 1) {
  339. args2.push(`(repeated ${repeated} times)`);
  340. }
  341. this._log({ ...this._lastLog.object, args: args2 });
  342. this._lastLog.count = 1;
  343. }
  344. if (newLog) {
  345. this._lastLog.object = logObj;
  346. this._log(logObj);
  347. }
  348. };
  349. clearTimeout(this._lastLog.timeout);
  350. const diffTime = this._lastLog.time && logObj.date ? logObj.date.getTime() - this._lastLog.time.getTime() : 0;
  351. this._lastLog.time = logObj.date;
  352. if (diffTime < this.options.throttle) {
  353. try {
  354. const serializedLog = JSON.stringify([
  355. logObj.type,
  356. logObj.tag,
  357. logObj.args
  358. ]);
  359. const isSameLog = this._lastLog.serialized === serializedLog;
  360. this._lastLog.serialized = serializedLog;
  361. if (isSameLog) {
  362. this._lastLog.count = (this._lastLog.count || 0) + 1;
  363. if (this._lastLog.count > this.options.throttleMin) {
  364. this._lastLog.timeout = setTimeout(
  365. resolveLog,
  366. this.options.throttle
  367. );
  368. return;
  369. }
  370. }
  371. } catch {
  372. }
  373. }
  374. resolveLog(true);
  375. }
  376. _log(logObj) {
  377. for (const reporter of this.options.reporters) {
  378. reporter.log(logObj, {
  379. options: this.options
  380. });
  381. }
  382. }
  383. }
  384. function _normalizeLogLevel(input, types = {}, defaultLevel = 3) {
  385. if (input === void 0) {
  386. return defaultLevel;
  387. }
  388. if (typeof input === "number") {
  389. return input;
  390. }
  391. if (types[input] && types[input].level !== void 0) {
  392. return types[input].level;
  393. }
  394. return defaultLevel;
  395. }
  396. Consola.prototype.add = Consola.prototype.addReporter;
  397. Consola.prototype.remove = Consola.prototype.removeReporter;
  398. Consola.prototype.clear = Consola.prototype.removeReporter;
  399. Consola.prototype.withScope = Consola.prototype.withTag;
  400. Consola.prototype.mock = Consola.prototype.mockTypes;
  401. Consola.prototype.pause = Consola.prototype.pauseLogs;
  402. Consola.prototype.resume = Consola.prototype.resumeLogs;
  403. function createConsola(options = {}) {
  404. return new Consola(options);
  405. }
  406. export { Consola, LogLevels, LogTypes, createConsola };