kayvee 3.16.0 → 3.18.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.
@@ -11,11 +11,10 @@ var _ = require("underscore");
11
11
  /**
12
12
  * all relative files path in a directory
13
13
  */
14
- function walkDirSync(dir, files) {
15
- if (files === void 0) { files = []; }
16
- var list = fs.readdirSync(dir);
17
- list.forEach(function (file) {
18
- var f = path.join(dir, file);
14
+ function walkDirSync(dir, files = []) {
15
+ const list = fs.readdirSync(dir);
16
+ list.forEach((file) => {
17
+ const f = path.join(dir, file);
19
18
  if (fs.statSync(path.join(dir, file)).isDirectory()) {
20
19
  walkDirSync(f, files);
21
20
  }
@@ -23,7 +22,7 @@ function walkDirSync(dir, files) {
23
22
  files.push(f);
24
23
  }
25
24
  });
26
- return files.map(function (f) { return path.relative(dir, f); });
25
+ return files.map((f) => path.relative(dir, f));
27
26
  }
28
27
  /**
29
28
  * returns a middleware function that checks if path exists in dir.
@@ -31,12 +30,11 @@ function walkDirSync(dir, files) {
31
30
  * Files in the directory are prefixed by base_path and compared to
32
31
  * req.path
33
32
  */
34
- function skip_path(dir, base_path) {
35
- if (base_path === void 0) { base_path = "/"; }
36
- var files = walkDirSync(dir);
37
- files = files.map(function (file) { return path.join(base_path, file); });
38
- console.error("KayveeMiddleware: Skipping successful requests for files in " + dir + " at " + base_path);
39
- return function (req, res) { return _(files).contains(req.path) && res.statusCode < 400; };
33
+ function skip_path(dir, base_path = "/") {
34
+ let files = walkDirSync(dir);
35
+ files = files.map((file) => path.join(base_path, file));
36
+ console.error(`KayveeMiddleware: Skipping successful requests for files in ${dir} at ${base_path}`);
37
+ return (req, res) => _(files).contains(req.path) && res.statusCode < 400;
40
38
  }
41
39
  /**
42
40
  * request path
@@ -52,8 +50,11 @@ function getBaseUrl(req) {
52
50
  function getQueryParams(req) {
53
51
  var url = req.originalUrl || req.url;
54
52
  var parsed = require("url").parse(url, true);
55
- var parsedQueryString = require("qs").parse(parsed.search, { allowPrototypes: false, ignoreQueryPrefix: true });
56
- return "?" + require("qs").stringify(parsedQueryString);
53
+ var parsedQueryString = require("qs").parse(parsed.search, {
54
+ allowPrototypes: false,
55
+ ignoreQueryPrefix: true,
56
+ });
57
+ return `?${require("qs").stringify(parsedQueryString)}`;
57
58
  }
58
59
  /**
59
60
  * response size
@@ -78,8 +79,7 @@ function getResponseTimeNs(req, res) {
78
79
  return undefined;
79
80
  }
80
81
  // calculate diff
81
- var ns = (res._startAt[0] - req._startAt[0]) * 1e9
82
- + (res._startAt[1] - req._startAt[1]);
82
+ var ns = (res._startAt[0] - req._startAt[0]) * 1e9 + (res._startAt[1] - req._startAt[1]);
83
83
  return ns;
84
84
  }
85
85
  /**
@@ -95,8 +95,8 @@ function getIp(req) {
95
95
  * Log level
96
96
  */
97
97
  function getLogLevel(req, res) {
98
- var statusCode = res.statusCode;
99
- var result;
98
+ const statusCode = res.statusCode;
99
+ let result;
100
100
  if (statusCode >= 499) {
101
101
  result = KayveeLogger.Error;
102
102
  }
@@ -105,66 +105,50 @@ function getLogLevel(req, res) {
105
105
  }
106
106
  return result;
107
107
  }
108
- /**
109
- * Get canary status
110
- */
111
- function isCanary() {
112
- return (process.env._CANARY === "1") || ("_POD_SHORTNAME" in process.env && process.env._POD_SHORTNAME.includes("-canary"));
113
- }
114
108
  /*
115
109
  * Default handlers
116
110
  */
117
111
  var defaultHandlers = [
118
112
  // Request method
119
- function (req) { return ({ method: req.method }); },
113
+ (req) => ({ method: req.method }),
120
114
  // Path (URL without query params)
121
- function (req) { return ({ path: getBaseUrl(req) }); },
115
+ (req) => ({ path: getBaseUrl(req) }),
122
116
  // Query params
123
- function (req) { return ({ params: getQueryParams(req) }); },
117
+ (req) => ({ params: getQueryParams(req) }),
124
118
  // Response size
125
- function (req, res) { return ({ "response-size": getResponseSize(res) }); },
119
+ (req, res) => ({ "response-size": getResponseSize(res) }),
126
120
  // Response time (ns)
127
- function (req, res) { return ({ "response-time": getResponseTimeNs(req, res) }); },
121
+ (req, res) => ({ "response-time": getResponseTimeNs(req, res) }),
128
122
  // Status code
129
- function (req, res) { return ({ "status-code": res.statusCode }); },
123
+ (req, res) => ({ "status-code": res.statusCode }),
130
124
  // Ip address
131
- function (req) { return ({ ip: getIp(req) }); },
125
+ (req) => ({ ip: getIp(req) }),
132
126
  // Via -- what library/code produced this log?
133
- function () { return ({ via: "kayvee-middleware" }); },
127
+ () => ({ via: "kayvee-middleware" }),
134
128
  // Kayvee's reserved fields
135
129
  // Log level
136
- function (req, res) { return ({ level: getLogLevel(req, res) }); },
130
+ (req, res) => ({ level: getLogLevel(req, res) }),
137
131
  // Source -- which app emitted this log?
138
132
  // -> Gets passed in among `options` during library initialization
139
133
  // Title
140
- function () { return ({ title: "request-finished" }); },
141
- // During the transition to pods, let's keep the canary field accurate
142
- // whether it's in the canary pod or a canary container in homepod
143
- function () { return ({ canary: isCanary() }); },
134
+ () => ({ title: "request-finished" }),
144
135
  ];
145
- var defaultContextHandlers = [];
146
- function handlerData(handlers) {
147
- var args = [];
148
- for (var _i = 1; _i < arguments.length; _i++) {
149
- args[_i - 1] = arguments[_i];
150
- }
151
- var data = {};
152
- handlers.forEach(function (h) {
136
+ const defaultContextHandlers = [];
137
+ function handlerData(handlers, ...args) {
138
+ const data = {};
139
+ handlers.forEach((h) => {
153
140
  try {
154
- var handler_data = h.apply(void 0, args);
141
+ const handler_data = h(...args);
155
142
  _.extend(data, handler_data);
156
143
  }
157
144
  catch (e) {
145
+ // swallow invalid handler
158
146
  }
159
147
  });
160
148
  return data;
161
149
  }
162
- var ContextLogger = (function () {
163
- function ContextLogger(logger, handlers) {
164
- var args = [];
165
- for (var _i = 2; _i < arguments.length; _i++) {
166
- args[_i - 2] = arguments[_i];
167
- }
150
+ class ContextLogger {
151
+ constructor(logger, handlers, ...args) {
168
152
  this.logger = null;
169
153
  this.handlers = [];
170
154
  this.args = [];
@@ -172,34 +156,25 @@ var ContextLogger = (function () {
172
156
  this.handlers = handlers;
173
157
  this.args = args;
174
158
  }
175
- ContextLogger.prototype._contextualData = function (data) {
176
- return _.extend(handlerData.apply(void 0, [this.handlers].concat(this.args)), data);
177
- };
178
- return ContextLogger;
179
- }());
180
- var _loop_1 = function(func) {
159
+ _contextualData(data) {
160
+ return _.extend(handlerData(this.handlers, ...this.args), data);
161
+ }
162
+ }
163
+ for (const func of KayveeLogger.LEVELS) {
181
164
  ContextLogger.prototype[func] = function (title) {
182
- this[(func + "D")](title, {});
165
+ this[`${func}D`](title, {});
183
166
  };
184
- ContextLogger.prototype[(func + "D")] = function (title, data) {
185
- this.logger[(func + "D")](title, this._contextualData(data));
167
+ ContextLogger.prototype[`${func}D`] = function (title, data) {
168
+ this.logger[`${func}D`](title, this._contextualData(data));
186
169
  };
187
- };
188
- for (var _i = 0, _a = KayveeLogger.LEVELS; _i < _a.length; _i++) {
189
- var func = _a[_i];
190
- _loop_1(func);
191
170
  }
192
- var _loop_2 = function(func) {
171
+ for (const func of KayveeLogger.METRICS) {
193
172
  ContextLogger.prototype[func] = function (title, value) {
194
- this[(func + "D")](title, value, {});
173
+ this[`${func}D`](title, value, {});
195
174
  };
196
- ContextLogger.prototype[(func + "D")] = function (title, value, data) {
197
- this.logger[(func + "D")](title, value, this._contextualData(data));
175
+ ContextLogger.prototype[`${func}D`] = function (title, value, data) {
176
+ this.logger[`${func}D`](title, value, this._contextualData(data));
198
177
  };
199
- };
200
- for (var _b = 0, _c = KayveeLogger.METRICS; _b < _c.length; _b++) {
201
- var func = _c[_b];
202
- _loop_2(func);
203
178
  }
204
179
  /*
205
180
  * User configuration is passed via an `options` object.
@@ -224,20 +199,20 @@ for (var _b = 0, _c = KayveeLogger.METRICS; _b < _c.length; _b++) {
224
199
  * base_handlers: e.g. [function(request, response) { return {"key":"val"}]
225
200
  *
226
201
  */
227
- var formatLine = function (options_arg) {
202
+ var formatLine = (options_arg) => {
228
203
  var options = options_arg || {};
229
204
  // `source` is the one required field
230
205
  if (!options.source) {
231
- throw (Error("Missing required config for 'source' in Kayvee middleware 'options'"));
206
+ throw Error("Missing required config for 'source' in Kayvee middleware 'options'");
232
207
  }
233
- var router = KayveeLogger.getGlobalRouter();
234
- return function (tokens, req, res) {
208
+ const router = KayveeLogger.getGlobalRouter();
209
+ return (tokens, req, res) => {
235
210
  // Build a dict of data to log
236
211
  var data = { _kvmeta: undefined }; // Adding _kvmeta here to make typescript compile happy
237
212
  // Add user-configured request headers
238
213
  var custom_headers = options.headers || [];
239
214
  var header_data = {};
240
- custom_headers.forEach(function (h) {
215
+ custom_headers.forEach((h) => {
241
216
  // Header field names are case insensitive, so let's be consistent
242
217
  var lc = h.toLowerCase();
243
218
  header_data[lc] = req.headers[lc];
@@ -247,9 +222,9 @@ var formatLine = function (options_arg) {
247
222
  var custom_handlers = options.handlers || [];
248
223
  // Allow user to override `base_handlers`; provide sane default set of handlers
249
224
  var base_handlers = options.base_handlers || defaultHandlers;
250
- base_handlers = base_handlers.concat([function () { return ({ source: options.source }); }]);
225
+ base_handlers = base_handlers.concat([() => ({ source: options.source })]);
251
226
  // Execute custom-handlers THEN base-handlers
252
- var all_handlers = custom_handlers.concat(base_handlers);
227
+ const all_handlers = custom_handlers.concat(base_handlers);
253
228
  _.extend(data, handlerData(all_handlers, req, res));
254
229
  if (router) {
255
230
  data._kvmeta = router.route(data);
@@ -257,7 +232,7 @@ var formatLine = function (options_arg) {
257
232
  return kayvee.format(data);
258
233
  };
259
234
  };
260
- var defaultContextLoggerOpts = {
235
+ const defaultContextLoggerOpts = {
261
236
  enabled: true,
262
237
  handlers: defaultContextHandlers,
263
238
  };
@@ -266,8 +241,7 @@ var defaultContextLoggerOpts = {
266
241
  * @public
267
242
  */
268
243
  if (process.env.NODE_ENV === "test") {
269
- module.exports = function (clever_options, morgan_options) {
270
- if (morgan_options === void 0) { morgan_options = { skip: null }; }
244
+ module.exports = (clever_options, morgan_options = { skip: null }) => {
271
245
  if (clever_options.ignore_dir) {
272
246
  morgan_options.skip = skip_path(clever_options.ignore_dir.directory, clever_options.ignore_dir.path);
273
247
  }
@@ -276,22 +250,21 @@ if (process.env.NODE_ENV === "test") {
276
250
  module.exports.ContextLogger = ContextLogger;
277
251
  }
278
252
  else {
279
- module.exports = function (clever_options, context_logger_options) {
280
- if (context_logger_options === void 0) { context_logger_options = defaultContextLoggerOpts; }
253
+ module.exports = (clever_options, context_logger_options = defaultContextLoggerOpts) => {
281
254
  // `source` is the one required field
282
255
  if (!clever_options.source) {
283
256
  throw new Error("Missing required config for 'source' in Kayvee middleware 'options'");
284
257
  }
285
- var logger = new KayveeLogger(clever_options.source);
286
- var morgan_options = {
258
+ const logger = new KayveeLogger(clever_options.source);
259
+ const morgan_options = {
287
260
  stream: process.stderr,
288
261
  skip: null,
289
262
  };
290
263
  if (clever_options.ignore_dir) {
291
264
  morgan_options.skip = skip_path(clever_options.ignore_dir.directory, clever_options.ignore_dir.path);
292
265
  }
293
- var morgan_logger = morgan(formatLine(clever_options), morgan_options);
294
- return function (req, res, next) {
266
+ const morgan_logger = morgan(formatLine(clever_options), morgan_options);
267
+ return (req, res, next) => {
295
268
  if (context_logger_options.enabled) {
296
269
  req.log = new ContextLogger(logger, context_logger_options.handlers, req);
297
270
  }
@@ -4,20 +4,20 @@ var schema = require("./schema_definitions");
4
4
  var yaml = require("js-yaml");
5
5
  var _ = require("underscore");
6
6
  var packageJson = require("../../package.json");
7
- var kvVersion = packageJson.version;
8
- var teamName = process.env._TEAM_OWNER || "UNSET";
9
- var reEnvvarTokens = new RegExp("\\$\\{(.+?)\\}", "g");
10
- var reFieldTokens = new RegExp("%\\{(.+?)\\}", "g");
7
+ const kvVersion = packageJson.version;
8
+ const teamName = process.env._TEAM_OWNER || "UNSET";
9
+ const reEnvvarTokens = new RegExp("\\$\\{(.+?)\\}", "g");
10
+ const reFieldTokens = new RegExp("%\\{(.+?)\\}", "g");
11
11
  // For performance reason this code is intentionally redundant and not-inlined.
12
12
  // Removing redundancy and inlining this function some how makes performance worst.
13
13
  function substituteEnvVars(obj, subber) {
14
- var rtn = {};
15
- var replacer = function (s) { return s.replace(reEnvvarTokens, function (__, p1) { return subber(p1); }); };
16
- for (var key in obj) {
17
- var val = obj[key];
14
+ const rtn = {};
15
+ const replacer = (s) => s.replace(reEnvvarTokens, (__, p1) => subber(p1));
16
+ for (const key in obj) {
17
+ const val = obj[key];
18
18
  if (Array.isArray(val)) {
19
- var updatedVals = Array(val.length);
20
- for (var i = 0; i < val.length; i++) {
19
+ const updatedVals = Array(val.length);
20
+ for (let i = 0; i < val.length; i++) {
21
21
  updatedVals[i] = replacer(val[i]);
22
22
  }
23
23
  rtn[key] = updatedVals;
@@ -29,51 +29,51 @@ function substituteEnvVars(obj, subber) {
29
29
  return rtn;
30
30
  }
31
31
  function deepKey(obj, key) {
32
- var path = key.split(".");
33
- var idx = 0;
34
- var val = obj;
32
+ const path = key.split(".");
33
+ let idx = 0;
34
+ let val = obj;
35
35
  do {
36
36
  val = val[path[idx++]];
37
37
  } while (val && idx < path.length);
38
38
  return val;
39
39
  }
40
40
  function fieldMatches(obj, field, values) {
41
- var val = obj[field] || deepKey(obj, field);
41
+ const val = obj[field] || deepKey(obj, field);
42
42
  if (val == null || val === "") {
43
43
  return false;
44
44
  }
45
45
  if (values[0] === "*") {
46
46
  return true;
47
47
  }
48
- for (var i = 0; i < values.length; i++) {
48
+ for (let i = 0; i < values.length; i++) {
49
49
  if (values[i] === val) {
50
50
  return true;
51
51
  }
52
52
  }
53
53
  return false;
54
54
  }
55
- var Rule = (function () {
56
- function Rule(name, matchers, output) {
55
+ class Rule {
56
+ constructor(name, matchers, output) {
57
57
  this.name = null;
58
58
  this.matchers = null;
59
59
  this.output = null;
60
60
  this.name = name;
61
61
  this.matchers = matchers;
62
- var envMissing = [];
63
- this.output = substituteEnvVars(output, function (k) {
64
- var val = process.env[k];
62
+ const envMissing = [];
63
+ this.output = substituteEnvVars(output, (k) => {
64
+ const val = process.env[k];
65
65
  if (val == null) {
66
66
  envMissing.push(k);
67
67
  }
68
68
  return val;
69
69
  });
70
70
  if (envMissing.length > 0) {
71
- throw new Error("Missing env var(s): " + envMissing.join(", "));
71
+ throw new Error(`Missing env var(s): ${envMissing.join(", ")}`);
72
72
  }
73
- Object.keys(matchers).forEach(function (field) {
74
- var fieldVals = matchers[field];
73
+ Object.keys(matchers).forEach((field) => {
74
+ const fieldVals = matchers[field];
75
75
  if (fieldVals.indexOf("*") !== -1 && fieldVals.length > 1) {
76
- throw new Error(("Invalid matcher values in " + name + "." + field + ".\n") +
76
+ throw new Error(`Invalid matcher values in ${name}.${field}.\n` +
77
77
  "Wildcard matcher can't co-exist with other matchers.");
78
78
  }
79
79
  });
@@ -83,24 +83,24 @@ var Rule = (function () {
83
83
  this.output.rule = this.name;
84
84
  }
85
85
  // matches returns true if `msg` matches against this rule
86
- Rule.prototype.matches = function (msg) {
87
- for (var field in this.matchers) {
86
+ matches(msg) {
87
+ for (const field in this.matchers) {
88
88
  if (!fieldMatches(msg, field, this.matchers[field])) {
89
89
  return false;
90
90
  }
91
91
  }
92
92
  return true;
93
- };
93
+ }
94
94
  // returns the output with kv substitutions performed
95
- Rule.prototype.outputFor = function (msg) {
96
- var rtn = {};
97
- var subst = function (__, k) { return msg[k] || deepKey(msg, k) || "KEY_NOT_FOUND"; };
98
- var replacer = function (s) { return s.replace(reFieldTokens, subst); };
99
- for (var key in this.output) {
100
- var val = this.output[key];
95
+ outputFor(msg) {
96
+ const rtn = {};
97
+ const subst = (__, k) => msg[k] || deepKey(msg, k) || "KEY_NOT_FOUND";
98
+ const replacer = (s) => s.replace(reFieldTokens, subst);
99
+ for (const key in this.output) {
100
+ const val = this.output[key];
101
101
  if (Array.isArray(val)) {
102
- var updatedVals = Array(val.length);
103
- for (var i = 0; i < val.length; i++) {
102
+ const updatedVals = Array(val.length);
103
+ for (let i = 0; i < val.length; i++) {
104
104
  updatedVals[i] = replacer(val[i]);
105
105
  }
106
106
  rtn[key] = updatedVals;
@@ -110,9 +110,8 @@ var Rule = (function () {
110
110
  }
111
111
  }
112
112
  return rtn;
113
- };
114
- return Rule;
115
- }());
113
+ }
114
+ }
116
115
  // validateKVConfig ensures that `routes` matches the config schema. We have this
117
116
  // function instead of just doing a plain jsonschema.validate in order to get
118
117
  // better error messages for the "output" object (by default jsonschema would
@@ -120,11 +119,11 @@ var Rule = (function () {
120
119
  // formats, but won't tell you what's wrong because it doesn't let you
121
120
  // condition on the output.type property).
122
121
  function validateKVConfig(config) {
123
- var validator = new jsonschema.Validator();
124
- var results = validator.validate(config, schema);
122
+ const validator = new jsonschema.Validator();
123
+ const results = validator.validate(config, schema);
125
124
  return {
126
125
  valid: results.valid,
127
- errors: results.errors.map(function (err) { return err.stack; }),
126
+ errors: results.errors.map((err) => err.stack),
128
127
  };
129
128
  }
130
129
  // parseConfig parses and validates the configuration passed as a string. It
@@ -132,53 +131,53 @@ function validateKVConfig(config) {
132
131
  // it was successfully parsed, rules is an array of rules, and errors is an
133
132
  // array of errors.
134
133
  function parseConfig(fileString) {
135
- var config;
134
+ let config;
136
135
  try {
137
136
  config = yaml.safeLoad(fileString);
138
137
  }
139
138
  catch (e) {
140
139
  return { valid: false, rules: [], errors: [e] };
141
140
  }
142
- var validateRes = validateKVConfig(config);
141
+ const validateRes = validateKVConfig(config);
143
142
  if (!validateRes.valid) {
144
143
  return _.assign(validateRes, { rules: [] });
145
144
  }
146
145
  try {
147
- var rulesObj = _.mapObject(config.routes, function (elem, name) { return new Rule(name, elem.matchers, elem.output); });
148
- var rules = _.values(rulesObj);
149
- return { valid: true, rules: rules, errors: [] };
146
+ const rulesObj = _.mapObject(config.routes, (elem, name) => new Rule(name, elem.matchers, elem.output));
147
+ const rules = _.values(rulesObj);
148
+ return { valid: true, rules, errors: [] };
150
149
  }
151
150
  catch (e) {
152
151
  return { valid: false, rules: [], errors: [e] };
153
152
  }
154
153
  }
155
- var Router = (function () {
156
- function Router(rules) {
154
+ class Router {
155
+ constructor(rules) {
157
156
  this.rules = null;
158
157
  this.rules = rules || [];
159
158
  }
160
159
  // loadConfig reads in the config located at `filename` and sets the routing
161
160
  // rules to what it finds there. It should be a YAML-formatted file with
162
161
  // routing rules placed under the `routes` key on the root object.
163
- Router.prototype.loadConfig = function (filename) {
164
- var data = fs.readFileSync(filename, "utf8");
162
+ loadConfig(filename) {
163
+ const data = fs.readFileSync(filename, "utf8");
165
164
  this._loadConfigString(data);
166
- };
167
- Router.prototype._loadConfigString = function (configStr) {
168
- var parsedRules = parseConfig(configStr);
165
+ }
166
+ _loadConfigString(configStr) {
167
+ const parsedRules = parseConfig(configStr);
169
168
  if (!parsedRules.valid) {
170
169
  throw new Error(parsedRules.errors);
171
170
  }
172
171
  this.rules = parsedRules.rules;
173
- };
172
+ }
174
173
  // route matches the log line `msg` against all loaded rules and returns a
175
174
  // metadata object describing the outputs it should be sent to based on that
176
175
  // matching. logger.ts will attach this to log lines under the `_kvmeta`
177
176
  // property.
178
- Router.prototype.route = function (msg) {
179
- var outputs = [];
180
- for (var i = 0; i < this.rules.length; i++) {
181
- var rule = this.rules[i];
177
+ route(msg) {
178
+ const outputs = [];
179
+ for (let i = 0; i < this.rules.length; i++) {
180
+ const rule = this.rules[i];
182
181
  if (rule.matches(msg)) {
183
182
  outputs.push(rule.outputFor(msg));
184
183
  }
@@ -189,10 +188,9 @@ var Router = (function () {
189
188
  kv_language: "js",
190
189
  routes: outputs,
191
190
  };
192
- };
193
- return Router;
194
- }());
191
+ }
192
+ }
195
193
  module.exports = {
196
- Router: Router,
197
- Rule: Rule,
194
+ Router,
195
+ Rule,
198
196
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kayvee",
3
3
  "description": "Write data to key=val pairs, for human and machine readability",
4
- "version": "3.16.0",
4
+ "version": "3.18.0",
5
5
  "main": "index.js",
6
6
  "repository": {
7
7
  "type": "git",
@@ -16,19 +16,27 @@
16
16
  "underscore": "^1.8.3"
17
17
  },
18
18
  "devDependencies": {
19
+ "@clever/prettier-config": "1.0.0",
20
+ "@types/mocha": "^8.0.3",
21
+ "@types/node": "^12.12.68",
22
+ "@typescript-eslint/eslint-plugin": "^5.2.0",
23
+ "@typescript-eslint/parser": "^5.2.0",
19
24
  "babel-eslint": "^6.0.2",
20
25
  "benchmark": "^2.1.1",
21
- "eslint": "^2.7.0",
26
+ "eslint": "^7.11.0",
22
27
  "eslint-config-airbnb": "^7.0.0",
23
- "eslint-plugin-jsx-a11y": "^0.6.2",
24
- "eslint-plugin-react": "^4.3.0",
28
+ "eslint-config-prettier": "^6.12.0",
29
+ "eslint-formatter-summary": "^1.1.0",
30
+ "eslint-plugin-jsx-a11y": "^6.3.1",
31
+ "eslint-plugin-react": "^7.21.5",
32
+ "eslint-plugin-react-hooks": "^4.1.2",
25
33
  "express": "^4.13.4",
26
- "mocha": "^2.5.3",
34
+ "mocha": "^3.5.3",
35
+ "prettier": "2.1.2",
27
36
  "sinon": "^1.17.4",
28
37
  "supertest": "^1.2.0",
29
- "ts-node": "^0.7.1",
30
- "tslint": "^3.7.4",
31
- "typescript": "^1.8.9"
38
+ "ts-node": "^9.0.0",
39
+ "typescript": "^3.9.10"
32
40
  },
33
41
  "scripts": {
34
42
  "test": "make -Br test",