axe 8.1.2 → 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/README.md +723 -206
  2. package/dist/axe.js +1298 -7130
  3. package/dist/axe.min.js +1 -1
  4. package/lib/index.js +357 -276
  5. package/package.json +45 -88
package/lib/index.js CHANGED
@@ -1,64 +1,80 @@
1
1
  "use strict";
2
2
 
3
- function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
3
+ // eslint-disable-next-line import/no-unassigned-import
4
+ require('console-polyfill');
4
5
 
5
- function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
6
+ const combine = require('maybe-combine-errors');
6
7
 
7
- function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
8
+ const format = require('@ladjs/format-util');
8
9
 
9
- function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
10
+ const formatSpecifiers = require('format-specifiers');
10
11
 
11
- function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
12
+ const get = require('@strikeentco/get');
12
13
 
13
- function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
14
+ const isError = require('iserror');
14
15
 
15
- function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
16
+ const mergeOptions = require('merge-options');
16
17
 
17
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
18
+ const pMapSeries = require('p-map-series');
18
19
 
19
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
20
+ const parseAppInfo = require('parse-app-info');
20
21
 
21
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
22
+ const parseErr = require('parse-err');
22
23
 
23
- function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
24
+ const pickDeep = require('pick-deep');
24
25
 
25
- // eslint-disable-next-line import/no-unassigned-import
26
- require('console-polyfill');
26
+ const set = require('@strikeentco/set');
27
27
 
28
- var cuid = require('cuid');
28
+ const unset = require('unset-value');
29
29
 
30
- var format = require('@ladjs/format-util');
30
+ const {
31
+ boolean
32
+ } = require('boolean');
31
33
 
32
- var formatSpecifiers = require('format-specifiers');
34
+ const pkg = require('../package.json');
33
35
 
34
- var isError = require('iserror');
36
+ const omittedLoggerKeys = new Set(['config', 'log']);
37
+ const levels = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];
38
+ const aliases = {
39
+ warning: 'warn',
40
+ err: 'error'
41
+ };
42
+ const levelError = `\`level\` invalid, must be: ${levels.join(', ')}`; // <https://github.com/sindresorhus/is-plain-obj/blob/main/index.js>
35
43
 
36
- var omit = require('lodash.omit');
44
+ function isPlainObject(value) {
45
+ if (typeof value !== 'object' || value === null) {
46
+ return false;
47
+ }
37
48
 
38
- var parseAppInfo = require('parse-app-info');
49
+ const prototype = Object.getPrototypeOf(value);
50
+ return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value);
51
+ } // <https://github.com/GeenenTijd/dotify/blob/master/dotify.js>
39
52
 
40
- var parseErr = require('parse-err');
41
53
 
42
- var safeStringify = require('fast-safe-stringify');
54
+ function dotifyToArray(obj) {
55
+ const res = [];
43
56
 
44
- var superagent = require('superagent');
57
+ function recurse(obj, current) {
58
+ for (const key of Object.keys(obj)) {
59
+ const value = obj[key];
60
+ const newKey = current ? current + '.' + key : key; // joined key with dot
61
+ // if (value && typeof value === 'object' && !(value instanceof Date) && !ObjectID.isValid(value)) {
45
62
 
46
- var _require = require('boolean'),
47
- boolean = _require.boolean;
63
+ if (isPlainObject(value)) {
64
+ recurse(value, newKey); // it's a nested object, so do it again
65
+ } else {
66
+ res.push(newKey);
67
+ }
68
+ }
69
+ }
48
70
 
49
- var pkg = require('../package.json');
71
+ recurse(obj);
72
+ return res;
73
+ } // <https://stackoverflow.com/a/43233163>
50
74
 
51
- var omittedLoggerKeys = new Set(['config', 'log']);
52
- var levels = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];
53
- var aliases = {
54
- warning: 'warn',
55
- err: 'error'
56
- };
57
- var endpoint = 'https://api.cabinjs.com';
58
- var levelError = "`level` invalid, must be: ".concat(levels.join(', ')); // <https://stackoverflow.com/a/43233163>
59
75
 
60
76
  function isEmpty(value) {
61
- return value === undefined || value === null || _typeof(value) === 'object' && Object.keys(value).length === 0 || typeof value === 'string' && value.trim().length === 0;
77
+ return value === undefined || value === null || typeof value === 'object' && Object.keys(value).length === 0 || typeof value === 'string' && value.trim().length === 0;
62
78
  }
63
79
 
64
80
  function isNull(value) {
@@ -70,7 +86,7 @@ function isUndefined(value) {
70
86
  }
71
87
 
72
88
  function isObject(value) {
73
- return _typeof(value) === 'object' && value !== null && !Array.isArray(value);
89
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
74
90
  }
75
91
 
76
92
  function isString(value) {
@@ -81,308 +97,373 @@ function isFunction(value) {
81
97
  return typeof value === 'function';
82
98
  }
83
99
 
84
- function isBoolean(value) {
85
- return typeof value === 'boolean';
86
- }
87
-
88
- var Axe = /*#__PURE__*/function () {
89
- function Axe() {
100
+ class Axe {
101
+ constructor() {
90
102
  var _this = this;
91
103
 
92
- var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
93
-
94
- _classCallCheck(this, Axe);
95
-
96
- this.config = Object.assign({
97
- key: '',
98
- endpoint: endpoint,
99
- headers: {},
100
- timeout: 5000,
101
- retry: 3,
102
- showStack: process.env.SHOW_STACK ? boolean(process.env.SHOW_STACK) : true,
103
- meta: {
104
- show: process.env.SHOW_META ? boolean(process.env.SHOW_META) : true,
105
- showApp: process.env.SHOW_META_APP ? boolean(process.env.SHOW_META_APP) : false,
106
- omittedFields: process.env.OMIT_META_FIELDS ? process.env.OMIT_META_FIELDS.split(',').map(function (s) {
107
- return s.trim();
108
- }) : []
109
- },
104
+ let config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
105
+ const remappedFields = {};
106
+
107
+ if (process.env.AXE_REMAPPED_META_FIELDS) {
108
+ const arr = process.env.AXE_REMAPPED_META_FIELDS.split(',').map(v => v.split(':'));
109
+
110
+ for (const [prop, value] of arr) {
111
+ remappedFields[prop] = value;
112
+ }
113
+ }
114
+
115
+ this.config = mergeOptions({
116
+ showStack: process.env.AXE_SHOW_STACK ? boolean(process.env.AXE_SHOW_STACK) : true,
117
+ meta: Object.assign({
118
+ show: process.env.AXE_SHOW_META ? boolean(process.env.AXE_SHOW_META) : true,
119
+ remappedFields,
120
+ omittedFields: process.env.AXE_OMIT_META_FIELDS ? process.env.AXE_OMIT_META_FIELDS.split(',').map(s => s.trim()) : ['level', 'err', 'app', 'args'],
121
+ pickedFields: process.env.AXE_PICK_META_FIELDS ? process.env.AXE_PICK_META_FIELDS.split(',').map(s => s.trim()) : [],
122
+ cleanupRemapping: true
123
+ }, typeof config.meta === 'object' ? config.meta : {}),
124
+ version: pkg.version,
110
125
  silent: false,
111
126
  logger: console,
112
127
  name: false,
113
128
  level: 'info',
114
129
  levels: ['info', 'warn', 'error', 'fatal'],
115
- // TODO: if user specifies `key` and it is `process.platform === 'browser' || process.browser || env === 'production'` then set `capture` to `true`
116
- capture: false,
117
- callback: false,
118
- appInfo: process.env.APP_INFO ? boolean(process.env.APP_INFO) : true
119
- }, config); // For backwards compatability
120
-
121
- if (this.config.showMeta) {
122
- this.config.meta.show = this.config.showMeta;
123
- delete this.config.showMeta;
124
- }
125
-
130
+ appInfo: process.env.AXE_APP_INFO ? boolean(process.env.AXE_APP_INFO) : true,
131
+ hooks: Object.assign({
132
+ pre: [],
133
+ post: []
134
+ }, typeof config.hooks === 'object' ? config.hooks : {})
135
+ }, config);
126
136
  this.appInfo = this.config.appInfo ? isFunction(parseAppInfo) ? parseAppInfo() : false : false;
127
137
  this.log = this.log.bind(this); // Inherit methods from parent logger
128
138
 
129
- var methods = Object.keys(this.config.logger).filter(function (key) {
130
- return !omittedLoggerKeys.has(key);
131
- });
132
-
133
- var _iterator = _createForOfIteratorHelper(methods),
134
- _step;
139
+ const methods = Object.keys(this.config.logger).filter(key => !omittedLoggerKeys.has(key));
135
140
 
136
- try {
137
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
138
- var element = _step.value;
139
- this[element] = this.config.logger[element];
140
- } // Bind helper functions for each log level
141
+ for (const element of methods) {
142
+ this[element] = this.config.logger[element];
143
+ } // Bind helper functions for each log level
141
144
 
142
- } catch (err) {
143
- _iterator.e(err);
144
- } finally {
145
- _iterator.f();
146
- }
147
145
 
148
- var _iterator2 = _createForOfIteratorHelper(levels),
149
- _step2;
146
+ for (const element of levels) {
147
+ // Ensure function exists in logger passed
148
+ if (typeof this.config.logger[element] !== 'function') {
149
+ if (element === 'fatal') {
150
+ this.config.logger.fatal = this.config.logger.error || this.config.logger.info || this.config.logger.log;
151
+ } else {
152
+ this.config.logger[element] = this.config.logger.info || this.config.logger.log;
153
+ }
154
+ } // Bind log handler which normalizes args and populates meta
150
155
 
151
- try {
152
- var _loop = function _loop() {
153
- var element = _step2.value;
154
156
 
155
- _this[element] = function () {
156
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
157
- args[_key] = arguments[_key];
158
- }
157
+ this[element] = function () {
158
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
159
+ args[_key] = arguments[_key];
160
+ }
159
161
 
160
- return _this.log.apply(_this, _toConsumableArray([element].concat(Array.prototype.slice.call(args))));
161
- };
162
+ return _this.log(element, ...Array.prototype.slice.call(args));
162
163
  };
163
-
164
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
165
- _loop();
166
- } // We could have used `auto-bind` but it's not compiled for browser
167
-
168
- } catch (err) {
169
- _iterator2.e(err);
170
- } finally {
171
- _iterator2.f();
172
164
  }
173
165
 
174
166
  this.setLevel = this.setLevel.bind(this);
175
167
  this.getNormalizedLevel = this.getNormalizedLevel.bind(this);
176
- this.setName = this.setName.bind(this);
177
- this.setCallback = this.setCallback.bind(this); // Set the logger name
168
+ this.setName = this.setName.bind(this); // Set the logger name
178
169
 
179
170
  if (this.config.name) this.setName(this.config.name); // Set the logger level
180
171
 
181
172
  this.setLevel(this.config.level); // Aliases
182
173
 
183
174
  this.err = this.error;
184
- this.warning = this.warn;
175
+ this.warning = this.warn; // Pre and Post Hooks
176
+
177
+ this.pre = function (level, fn) {
178
+ this.config.hooks.pre.push(function (_level) {
179
+ for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
180
+ args[_key2 - 1] = arguments[_key2];
181
+ }
182
+
183
+ if (level !== _level) return [...args];
184
+ return fn(...args);
185
+ });
186
+ };
187
+
188
+ this.post = function (level, fn) {
189
+ this.config.hooks.post.push(function (_level) {
190
+ for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
191
+ args[_key3 - 1] = arguments[_key3];
192
+ }
193
+
194
+ if (level !== _level) return [...args];
195
+ return fn(...args);
196
+ });
197
+ };
185
198
  }
186
199
 
187
- _createClass(Axe, [{
188
- key: "setCallback",
189
- value: function setCallback(callback) {
190
- this.config.callback = callback;
191
- }
192
- }, {
193
- key: "setLevel",
194
- value: function setLevel(level) {
195
- if (!isString(level) || !levels.includes(level)) throw new Error(levelError); // Support signale logger and other loggers that use `logLevel`
200
+ setLevel(level) {
201
+ if (!isString(level) || levels.indexOf(level) === -1) throw new Error(levelError); // Support signale logger and other loggers that use `logLevel`
196
202
 
197
- if (isString(this.config.logger.logLevel)) this.config.logger.logLevel = level;else this.config.logger.level = level; // Adjusts `this.config.levels` array
198
- // so that it has all proceeding (inclusive)
203
+ if (isString(this.config.logger.logLevel)) this.config.logger.logLevel = level;else this.config.logger.level = level; // Adjusts `this.config.levels` array
204
+ // so that it has all proceeding (inclusive)
199
205
 
200
- this.config.levels = levels.slice(levels.indexOf(level));
206
+ this.config.levels = levels.slice(levels.indexOf(level));
207
+ }
208
+
209
+ getNormalizedLevel(level) {
210
+ if (!isString(level)) return 'info';
211
+ if (isString(aliases[level])) return aliases[level];
212
+ if (levels.indexOf(level) === -1) return 'info';
213
+ return level;
214
+ }
215
+
216
+ setName(name) {
217
+ if (!isString(name)) throw new Error('`name` must be a String'); // Support signale logger and other loggers that use `scope`
218
+
219
+ if (isString(this.config.logger.scope)) this.config.logger.scope = name;else this.config.logger.name = name;
220
+ } // eslint-disable-next-line complexity
221
+
222
+
223
+ log(level, message, meta) {
224
+ const originalArgs = [];
225
+ const errors = [];
226
+ if (!isUndefined(level)) originalArgs.push(level);
227
+ if (!isUndefined(message)) originalArgs.push(message);
228
+ if (!isUndefined(meta)) originalArgs.push(meta);
229
+
230
+ for (var _len4 = arguments.length, args = new Array(_len4 > 3 ? _len4 - 3 : 0), _key4 = 3; _key4 < _len4; _key4++) {
231
+ args[_key4 - 3] = arguments[_key4];
201
232
  }
202
- }, {
203
- key: "getNormalizedLevel",
204
- value: function getNormalizedLevel(level) {
205
- if (!isString(level)) return 'info';
206
- if (isString(aliases[level])) return aliases[level];
207
- if (!levels.includes(level)) return 'info';
208
- return level;
233
+
234
+ for (const arg of Array.prototype.slice.call(args)) {
235
+ originalArgs.push(arg);
209
236
  }
210
- }, {
211
- key: "setName",
212
- value: function setName(name) {
213
- if (!isString(name)) throw new Error('`name` must be a String'); // Support signale logger and other loggers that use `scope`
214
-
215
- if (isString(this.config.logger.scope)) this.config.logger.scope = name;else this.config.logger.name = name;
216
- } // eslint-disable-next-line complexity
217
-
218
- }, {
219
- key: "log",
220
- value: function log(level, message, meta) {
221
- var _this2 = this;
222
-
223
- var originalArgs = [];
224
- if (!isUndefined(level)) originalArgs.push(level);
225
- if (!isUndefined(message)) originalArgs.push(message);
226
- if (!isUndefined(meta)) originalArgs.push(meta);
227
-
228
- for (var _len2 = arguments.length, args = new Array(_len2 > 3 ? _len2 - 3 : 0), _key2 = 3; _key2 < _len2; _key2++) {
229
- args[_key2 - 3] = arguments[_key2];
237
+
238
+ const {
239
+ config
240
+ } = this;
241
+ let modifier = 0;
242
+
243
+ if (isString(level) && isString(aliases[level])) {
244
+ level = aliases[level];
245
+ } else if (isError(level)) {
246
+ meta = message;
247
+ message = level;
248
+ level = 'error';
249
+ } else if (!isString(level) || levels.indexOf(level) === -1) {
250
+ meta = message;
251
+ message = level;
252
+ level = this.getNormalizedLevel(level);
253
+ modifier = -1;
254
+ } // Return early if it is not a valid logging level
255
+
256
+
257
+ if (config.levels.indexOf(level) === -1) return; // Bunyan support (meta, message, ...args)
258
+
259
+ let isBunyan = false;
260
+
261
+ if ((isObject(message) || Array.isArray(message)) && isString(meta)) {
262
+ isBunyan = true;
263
+ const _meta = meta;
264
+ meta = message;
265
+ message = isString(_meta) && originalArgs.length >= 3 + modifier ? format(...originalArgs.slice(2 + modifier)) : _meta;
266
+ } // If message was undefined then set it to level
267
+
268
+
269
+ if (isUndefined(message)) message = level; // If only `message` was passed then if it was an Object
270
+ // preserve it as an Object by setting it as meta
271
+
272
+ if (originalArgs.slice(1 + modifier).length === 1 && !isString(message) && !isError(message)) {
273
+ meta = {
274
+ message
275
+ };
276
+ message = level;
277
+ } else if (!isBunyan && originalArgs.length >= 4 + modifier) {
278
+ message = undefined;
279
+ meta = {};
280
+ const messages = [];
281
+
282
+ for (const arg of originalArgs) {
283
+ if (isError(arg)) errors.push(arg);else if (isString(arg)) messages.push(arg);
230
284
  }
231
285
 
232
- originalArgs = originalArgs.concat(Array.prototype.slice.call(args));
233
- var config = this.config;
234
- var modifier = 0;
235
-
236
- if (isString(level) && isString(aliases[level])) {
237
- level = aliases[level];
238
- } else if (isError(level)) {
239
- meta = message;
240
- message = level;
241
- level = 'error';
242
- } else if (!isString(level) || !levels.includes(level)) {
243
- meta = message;
244
- message = level;
245
- level = this.getNormalizedLevel(level);
246
- modifier = -1;
247
- } // Bunyan support (meta, message, ...args)
248
-
249
-
250
- var isBunyan = false;
251
-
252
- if ((isObject(message) || Array.isArray(message)) && isString(meta)) {
253
- isBunyan = true;
254
- var _meta = meta;
255
- meta = message;
256
- message = isString(_meta) && originalArgs.length >= 3 + modifier ? format.apply(void 0, _toConsumableArray(originalArgs.slice(2 + modifier))) : _meta;
257
- } // If message was undefined then set it to level
258
-
259
-
260
- if (isUndefined(message)) message = level; // If only `message` was passed then if it was an Object
261
- // preserve it as an Object by setting it as meta
262
-
263
- if (originalArgs.slice(1 + modifier).length === 1 && !isString(message) && !isError(message)) {
264
- meta = {
265
- message: message
266
- };
267
- message = level;
268
- } else if (!isBunyan && originalArgs.length >= 4 + modifier) {
269
- // If there are four or more args
270
- // then infer to use util.format on everything
271
- message = format.apply(void 0, _toConsumableArray(originalArgs.slice(1 + modifier)));
286
+ if (errors.length === 0 && messages.length > 0) message = format(...messages);else if (errors.length > 0 && level === 'log') level = 'error';
287
+ } else if (!isBunyan && originalArgs.length === 3 + modifier && isString(message) && formatSpecifiers.some(t => message.indexOf(t) !== -1)) {
288
+ // Otherwise if there are three args and if the `message` contains
289
+ // a placeholder token (e.g. '%s' or '%d' - see above `formatSpecifiers` variable)
290
+ // then we can infer that the `meta` arg passed is used for formatting
291
+ message = format(message, meta);
292
+ meta = {};
293
+ } else if (!isError(message)) {
294
+ if (isError(meta)) {
295
+ errors.push(meta);
272
296
  meta = {};
273
- } else if (!isBunyan && originalArgs.length === 3 + modifier && isString(message) && formatSpecifiers.some(function (t) {
274
- return message.includes(t);
275
- })) {
276
- // Otherwise if there are three args and if the `message` contains
277
- // a placeholder token (e.g. '%s' or '%d' - see above `formatSpecifiers` variable)
278
- // then we can infer that the `meta` arg passed is used for formatting
297
+ } else if (!isObject(meta) && !isUndefined(meta) && !isNull(meta)) {
298
+ // If the `meta` variable passed was not an Object then convert it
279
299
  message = format(message, meta);
280
300
  meta = {};
281
- } else if (!isError(message)) {
282
- if (isError(meta)) {
283
- meta = {
284
- err: parseErr(meta)
285
- }; // } else if (!isPlainObject(meta) && !isUndefined(meta) && !isNull(meta)) {
286
- } else if (!isObject(meta) && !isUndefined(meta) && !isNull(meta)) {
287
- // If the `meta` variable passed was not an Object then convert it
288
- message = format(message, meta);
289
- meta = {};
290
- } else if (!isString(message)) {
291
- // If the message is not a string then we should run `util.format` on it
292
- // assuming we're formatting it like it was another argument
293
- // (as opposed to using something like fast-json-stringify)
294
- message = format(message);
295
- }
296
- } // If (!isPlainObject(meta)) meta = {};
297
-
298
-
299
- if (!isUndefined(meta) && !isObject(meta)) meta = {
300
- meta: meta
301
- };else if (!isObject(meta)) meta = {};
302
- var error;
301
+ } else if (!isString(message)) {
302
+ // If the message is not a string then we should run `util.format` on it
303
+ // assuming we're formatting it like it was another argument
304
+ // (as opposed to using something like fast-json-stringify)
305
+ message = format(message);
306
+ }
307
+ } else if (isError(meta)) {
308
+ errors.push(meta); // handle additional args
303
309
 
304
- if (isError(message)) {
305
- error = message;
306
- if (!isObject(meta.err)) meta.err = parseErr(error);
307
- var _message = message;
308
- message = _message.message;
309
- } else if (isError(meta.err)) {
310
- error = meta.err;
311
- } // Omit `callback` from `meta` if it was passed
310
+ for (const arg of originalArgs.slice(2 + modifier)) {
311
+ // should skip this better with slice and modifier adjustment
312
+ if (meta === arg) continue;
313
+ if (isError(arg)) errors.push(arg);
314
+ }
312
315
 
316
+ meta = {};
317
+ }
313
318
 
314
- var callback = isFunction(config.callback) && (!isBoolean(meta.callback) || meta.callback);
315
- meta = omit(meta, ['callback']); // Set default level on meta
319
+ if (!isUndefined(meta) && !isObject(meta)) meta = {
320
+ original_meta: meta
321
+ };else if (!isObject(meta)) meta = {};
316
322
 
317
- meta.level = level; // Add `app` object to metadata
323
+ if (isError(message)) {
324
+ errors.unshift(message);
325
+ message = undefined;
326
+ } //
327
+ // rewrite `meta.err` to `meta.original_err` for consistency
328
+ // (in case someone has an object with `.err` property on it with an error)
329
+ //
318
330
 
319
- if (this.appInfo) meta.app = this.appInfo; // Set the body used for returning with and sending logs
320
- // (and also remove circular references)
321
331
 
322
- var body = safeStringify({
323
- message: message,
324
- meta: meta
325
- }); // Send to Cabin or other logging service here the `message` and `meta`
332
+ if (isObject(meta.err)) {
333
+ if (isError(meta.err)) errors.push(meta.err);
334
+ meta.original_err = isError(meta.err) ? parseErr(meta.err) : meta.err;
335
+ }
326
336
 
327
- if (config.capture && config.levels.includes(level) && (!isError(error) || !error._captureFailed)) {
328
- // If the user didn't specify a key
329
- // and they are using the default endpoint
330
- // then we should throw an error to them
331
- if (config.endpoint === endpoint && !config.key) throw new Error("Cabin API key required (e.g. `{ key: 'YOUR-CABIN-API-KEY' })`)\n<https://cabinjs.com>"); // Capture the log over HTTP
337
+ let err;
338
+
339
+ if (errors.length > 0) {
340
+ err = combine(errors);
341
+ meta.err = parseErr(err);
342
+ if (!isString(message)) message = err.message;
343
+ } // Set `args` prop with original arguments passed
344
+
345
+
346
+ meta.args = originalArgs; // Set default level on meta
347
+
348
+ meta.level = level; // Add `app` object to metadata
349
+
350
+ if (this.appInfo) meta.app = this.appInfo; //
351
+ // determine log method to use
352
+ //
353
+ // if we didn't pass a level as a method
354
+ // (e.g. console.info), then we should still
355
+ // use the logger's `log` method to output
356
+ //
357
+ // and fatal should use error (e.g. in browser)
358
+ //
359
+
360
+ const method = modifier === -1 ? 'log' : level; //
361
+ // NOTE: using lodash _.omit and _.pick would have been _very slow_
362
+ //
363
+ // const omittedAndPickedFields = {
364
+ // ..._.omit(meta, this.config.meta.omittedFields),
365
+ // ..._.pick(meta, this.config.meta.pickedFields)
366
+ // };
367
+ //
368
+ // also we don't want to mutate anything in `meta`
369
+ // and ideally we only want to pick exactly what we need
370
+ // (and not have two operations, one for omit, and one for pick)
371
+ //
372
+
373
+ if (!isEmpty(this.config.meta.remappedFields)) {
374
+ for (const key of Object.keys(this.config.meta.remappedFields)) {
375
+ set(meta, this.config.meta.remappedFields[key], get(meta, key));
376
+ unset(meta, key); // cleanup empty objects after remapping
377
+
378
+ if (this.config.meta.cleanupRemapping) {
379
+ const index = key.lastIndexOf('.');
380
+ if (index === -1) continue;
381
+ const parentKey = key.slice(0, index);
382
+ if (isEmpty(get(meta, parentKey))) unset(meta, parentKey);
383
+ }
384
+ }
385
+ }
332
386
 
333
- var request = superagent.post(config.endpoint).set('X-Request-Id', cuid()).timeout(config.timeout);
334
- if (!process.browser) request.set('User-Agent', "axe/".concat(pkg.version)); // Basic auth (e.g. Cabin API key)
387
+ if (!isEmpty(this.config.meta.omittedFields) || !isEmpty(this.config.meta.pickedFields)) {
388
+ const dotified = dotifyToArray(meta); // dotified = [
389
+ // 'err.name',
390
+ // 'err.message',
391
+ // 'err.stack',
392
+ // 'level',
393
+ // 'app.name',
394
+ // 'app.version',
395
+ // 'app.node',
396
+ // 'app.hash',
397
+ // // ...
398
+ // ]
399
+
400
+ if (!isEmpty(this.config.meta.omittedFields)) {
401
+ for (const prop of this.config.meta.omittedFields) {
402
+ // <https://stackoverflow.com/a/9882349>
403
+ let i = dotified.length;
404
+
405
+ while (i--) {
406
+ if (dotified[i] === prop || dotified[i].indexOf(`${prop}.`) === 0) dotified.splice(i, 1);
407
+ }
408
+ }
409
+ }
335
410
 
336
- if (config.key) request.auth(config.key); // Set headers if any
411
+ if (!isEmpty(this.config.meta.pickedFields)) {
412
+ for (const prop of this.config.meta.pickedFields) {
413
+ // response.headers.boop
414
+ // response.headers.beep
415
+ // response.body
416
+ // response.text
417
+ // response
418
+ //
419
+ // so we need to split by the first period and omit any keys from dotified starting with it
420
+ const index = prop.indexOf('.');
421
+ const key = prop.slice(0, index + 1);
337
422
 
338
- if (!isEmpty(config.headers)) request.set(config.headers);
339
- request.type('application/json').send(body).retry(config.retry).end(function (error_) {
340
- if (error_) {
341
- error_._captureFailed = true;
423
+ if (index !== -1) {
424
+ let i = dotified.length;
342
425
 
343
- _this2.config.logger.error(error_);
344
- }
345
- });
346
- } // Custom callback function (e.g. Slack message)
426
+ while (i--) {
427
+ if (dotified[i].indexOf(key) === 0) dotified.splice(i, 1);
428
+ }
429
+ } // finally add it if it did not already exist
347
430
 
348
431
 
349
- if (callback) config.callback(level, message, meta); // Suppress logs if it was silent
432
+ if (dotified.indexOf(prop) === -1) dotified.push(prop);
433
+ }
434
+ } // now we call pick-deep using the final array
350
435
 
351
- if (config.silent) return body; // Return early if it is not a valid logging level
352
436
 
353
- if (!config.levels.includes(level)) return body; //
354
- // determine log method to use
355
- //
356
- // if we didn't pass a level as a method
357
- // (e.g. console.info), then we should still
358
- // use the logger's `log` method to output
359
- //
360
- // and fatal should use error (e.g. in browser)
361
- //
437
+ meta = pickDeep(meta, dotified);
438
+ } // pre-hooks
362
439
 
363
- var method = level;
364
- if (modifier === -1) method = 'log';else if (level === 'fatal') method = 'error'; // If there was meta information then output it
365
- // setup ommitted fields
366
440
 
367
- var omittedFields = ['level', 'err'].concat(this.config.meta.omittedFields); // Omit app is configured
441
+ for (const hook of this.config.hooks.pre) {
442
+ [err, message, meta] = hook(method, err, message, meta);
443
+ } // only invoke logger methods if it was not silent
368
444
 
369
- if (!this.config.meta.showApp) omittedFields.push('app');
370
- var omitted = omit(meta, omittedFields); // Show stack trace if necessary (along with any metadata)
371
445
 
372
- if (method === 'error' && isError(error) && config.showStack) {
373
- if (!config.meta.show || isEmpty(omitted)) this.config.logger.error(error);else this.config.logger.error(error, omitted);
374
- } else if (!config.meta.show || isEmpty(omitted)) {
446
+ if (!config.silent) {
447
+ // Show stack trace if necessary (along with any metadata)
448
+ if (isError(err) && config.showStack) {
449
+ if (!config.meta.show || isEmpty(meta)) {
450
+ this.config.logger[method](err);
451
+ } else {
452
+ this.config.logger[method](err, meta);
453
+ }
454
+ } else if (!config.meta.show || isEmpty(meta)) {
375
455
  this.config.logger[method](message);
376
456
  } else {
377
- this.config.logger[method](message, omitted);
378
- } // Return the parsed body in case we need it
457
+ this.config.logger[method](message, meta);
458
+ }
459
+ } // post-hooks
379
460
 
380
461
 
381
- return body;
382
- }
383
- }]);
462
+ pMapSeries(this.config.hooks.post, hook => hook(method, err, message, meta)).then().catch(err => {
463
+ this.config.logger.error(err);
464
+ });
465
+ }
384
466
 
385
- return Axe;
386
- }();
467
+ }
387
468
 
388
469
  module.exports = Axe;