@openreplay/tracker 3.6.2 → 4.0.1

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 (128) hide show
  1. package/.eslintignore +8 -0
  2. package/.prettierignore +1 -0
  3. package/LICENSE +1 -1
  4. package/cjs/app/guards.d.ts +2 -1
  5. package/cjs/app/guards.js +6 -3
  6. package/cjs/app/index.d.ts +28 -23
  7. package/cjs/app/index.js +107 -86
  8. package/cjs/app/logger.js +6 -3
  9. package/cjs/app/messages.d.ts +52 -0
  10. package/cjs/app/messages.gen.d.ts +58 -0
  11. package/cjs/app/messages.gen.js +501 -0
  12. package/cjs/app/messages.js +234 -0
  13. package/cjs/app/nodes.d.ts +1 -1
  14. package/cjs/app/nodes.js +2 -0
  15. package/cjs/app/observer/iframe_observer.d.ts +1 -1
  16. package/cjs/app/observer/iframe_observer.js +3 -3
  17. package/cjs/app/observer/observer.d.ts +2 -3
  18. package/cjs/app/observer/observer.js +50 -52
  19. package/cjs/app/observer/shadow_root_observer.d.ts +1 -1
  20. package/cjs/app/observer/shadow_root_observer.js +3 -3
  21. package/cjs/app/observer/top_observer.d.ts +13 -2
  22. package/cjs/app/observer/top_observer.js +58 -23
  23. package/cjs/app/sanitizer.d.ts +1 -1
  24. package/cjs/app/sanitizer.js +5 -5
  25. package/cjs/app/session.d.ts +20 -2
  26. package/cjs/app/session.js +65 -6
  27. package/cjs/app/ticker.d.ts +1 -1
  28. package/cjs/common/{webworker.d.ts → interaction.d.ts} +5 -5
  29. package/cjs/common/{types.js → interaction.js} +0 -0
  30. package/cjs/common/messages.gen.d.ts +388 -0
  31. package/cjs/common/{webworker.js → messages.gen.js} +1 -0
  32. package/cjs/index.d.ts +10 -9
  33. package/cjs/index.js +47 -36
  34. package/cjs/modules/adoptedStyleSheets.d.ts +2 -0
  35. package/cjs/modules/adoptedStyleSheets.js +127 -0
  36. package/cjs/modules/connection.d.ts +1 -1
  37. package/cjs/modules/connection.js +2 -2
  38. package/cjs/modules/console.d.ts +1 -1
  39. package/cjs/modules/console.js +7 -21
  40. package/cjs/modules/cssrules.d.ts +1 -1
  41. package/cjs/modules/cssrules.js +18 -14
  42. package/cjs/modules/exception.d.ts +3 -3
  43. package/cjs/modules/exception.js +23 -18
  44. package/cjs/modules/img.d.ts +1 -1
  45. package/cjs/modules/img.js +39 -26
  46. package/cjs/modules/input.d.ts +1 -1
  47. package/cjs/modules/input.js +21 -21
  48. package/cjs/modules/mouse.d.ts +1 -1
  49. package/cjs/modules/mouse.js +50 -43
  50. package/cjs/modules/performance.d.ts +1 -1
  51. package/cjs/modules/performance.js +2 -2
  52. package/cjs/modules/scroll.d.ts +1 -1
  53. package/cjs/modules/scroll.js +16 -7
  54. package/cjs/modules/timing.d.ts +1 -1
  55. package/cjs/modules/timing.js +14 -26
  56. package/cjs/modules/viewport.d.ts +1 -1
  57. package/cjs/modules/viewport.js +4 -4
  58. package/cjs/utils.js +7 -7
  59. package/cjs/vendors/finder/finder.js +53 -48
  60. package/lib/app/guards.d.ts +2 -1
  61. package/lib/app/guards.js +4 -2
  62. package/lib/app/index.d.ts +28 -23
  63. package/lib/app/index.js +115 -94
  64. package/lib/app/logger.js +6 -3
  65. package/lib/app/messages.d.ts +52 -0
  66. package/lib/app/messages.gen.d.ts +58 -0
  67. package/lib/app/messages.gen.js +441 -0
  68. package/lib/app/messages.js +181 -0
  69. package/lib/app/nodes.d.ts +1 -1
  70. package/lib/app/nodes.js +2 -0
  71. package/lib/app/observer/iframe_observer.d.ts +1 -1
  72. package/lib/app/observer/iframe_observer.js +3 -3
  73. package/lib/app/observer/observer.d.ts +2 -3
  74. package/lib/app/observer/observer.js +51 -53
  75. package/lib/app/observer/shadow_root_observer.d.ts +1 -1
  76. package/lib/app/observer/shadow_root_observer.js +3 -3
  77. package/lib/app/observer/top_observer.d.ts +13 -2
  78. package/lib/app/observer/top_observer.js +62 -27
  79. package/lib/app/sanitizer.d.ts +1 -1
  80. package/lib/app/sanitizer.js +7 -7
  81. package/lib/app/session.d.ts +20 -2
  82. package/lib/app/session.js +65 -6
  83. package/lib/app/ticker.d.ts +1 -1
  84. package/lib/common/{webworker.d.ts → interaction.d.ts} +5 -5
  85. package/lib/common/{types.js → interaction.js} +0 -0
  86. package/lib/common/messages.gen.d.ts +388 -0
  87. package/lib/common/messages.gen.js +2 -0
  88. package/lib/common/tsconfig.tsbuildinfo +1 -1
  89. package/lib/index.d.ts +10 -9
  90. package/lib/index.js +60 -49
  91. package/lib/modules/adoptedStyleSheets.d.ts +2 -0
  92. package/lib/modules/adoptedStyleSheets.js +124 -0
  93. package/lib/modules/connection.d.ts +1 -1
  94. package/lib/modules/connection.js +2 -2
  95. package/lib/modules/console.d.ts +1 -1
  96. package/lib/modules/console.js +8 -22
  97. package/lib/modules/cssrules.d.ts +1 -1
  98. package/lib/modules/cssrules.js +19 -15
  99. package/lib/modules/exception.d.ts +3 -3
  100. package/lib/modules/exception.js +23 -18
  101. package/lib/modules/img.d.ts +1 -1
  102. package/lib/modules/img.js +41 -28
  103. package/lib/modules/input.d.ts +1 -1
  104. package/lib/modules/input.js +23 -23
  105. package/lib/modules/mouse.d.ts +1 -1
  106. package/lib/modules/mouse.js +53 -46
  107. package/lib/modules/performance.d.ts +1 -1
  108. package/lib/modules/performance.js +3 -3
  109. package/lib/modules/scroll.d.ts +1 -1
  110. package/lib/modules/scroll.js +17 -8
  111. package/lib/modules/timing.d.ts +1 -1
  112. package/lib/modules/timing.js +16 -28
  113. package/lib/modules/viewport.d.ts +1 -1
  114. package/lib/modules/viewport.js +4 -4
  115. package/lib/utils.js +7 -7
  116. package/lib/vendors/finder/finder.js +53 -48
  117. package/package.json +27 -10
  118. package/cjs/common/messages.d.ts +0 -444
  119. package/cjs/common/messages.js +0 -794
  120. package/cjs/common/types.d.ts +0 -9
  121. package/cjs/modules/longtasks.d.ts +0 -2
  122. package/cjs/modules/longtasks.js +0 -26
  123. package/lib/common/messages.d.ts +0 -444
  124. package/lib/common/messages.js +0 -790
  125. package/lib/common/types.d.ts +0 -9
  126. package/lib/common/webworker.js +0 -1
  127. package/lib/modules/longtasks.d.ts +0 -2
  128. package/lib/modules/longtasks.js +0 -23
package/lib/utils.js CHANGED
@@ -11,25 +11,25 @@ export function normSpaces(str) {
11
11
  export function isURL(s) {
12
12
  return s.startsWith('https://') || s.startsWith('http://');
13
13
  }
14
- export const IN_BROWSER = !(typeof window === "undefined");
14
+ export const IN_BROWSER = !(typeof window === 'undefined');
15
15
  // TODO: JOIN IT WITH LOGGER somehow (use logging decorators?); Don't forget about index.js loggin when there is no logger instance.
16
16
  export const DOCS_HOST = 'https://docs.openreplay.com';
17
17
  const warnedFeatures = {};
18
- export function deprecationWarn(nameOfFeature, useInstead, docsPath = "/") {
18
+ export function deprecationWarn(nameOfFeature, useInstead, docsPath = '/') {
19
19
  if (warnedFeatures[nameOfFeature]) {
20
20
  return;
21
21
  }
22
- console.warn(`OpenReplay: ${nameOfFeature} is deprecated. ${useInstead ? `Please, use ${useInstead} instead.` : ""} Visit ${DOCS_HOST}${docsPath} for more information.`);
22
+ console.warn(`OpenReplay: ${nameOfFeature} is deprecated. ${useInstead ? `Please, use ${useInstead} instead.` : ''} Visit ${DOCS_HOST}${docsPath} for more information.`);
23
23
  warnedFeatures[nameOfFeature] = true;
24
24
  }
25
25
  export function getLabelAttribute(e) {
26
- let value = e.getAttribute("data-openreplay-label");
26
+ let value = e.getAttribute('data-openreplay-label');
27
27
  if (value !== null) {
28
28
  return value;
29
29
  }
30
- value = e.getAttribute("data-asayer-label");
30
+ value = e.getAttribute('data-asayer-label');
31
31
  if (value !== null) {
32
- deprecationWarn(`"data-asayer-label" attribute`, `"data-openreplay-label" attribute`, "/");
32
+ deprecationWarn('"data-asayer-label" attribute', '"data-openreplay-label" attribute', '/');
33
33
  }
34
34
  return value;
35
35
  }
@@ -40,7 +40,7 @@ export function hasOpenreplayAttribute(e, name) {
40
40
  }
41
41
  const oldName = `data-asayer-${name}`;
42
42
  if (e.hasAttribute(oldName)) {
43
- deprecationWarn(`"${oldName}" attribute`, `"${newName}" attribute`, "/installation/sanitize-data");
43
+ deprecationWarn(`"${oldName}" attribute`, `"${newName}" attribute`, '/installation/sanitize-data');
44
44
  return true;
45
45
  }
46
46
  return false;
@@ -8,10 +8,10 @@ let config;
8
8
  let rootDocument;
9
9
  export function finder(input, options) {
10
10
  if (input.nodeType !== Node.ELEMENT_NODE) {
11
- throw new Error(`Can't generate CSS selector for non-element node type.`);
11
+ throw new Error("Can't generate CSS selector for non-element node type.");
12
12
  }
13
- if ("html" === input.tagName.toLowerCase()) {
14
- return "html";
13
+ if ('html' === input.tagName.toLowerCase()) {
14
+ return 'html';
15
15
  }
16
16
  const defaults = {
17
17
  root: document.body,
@@ -35,7 +35,7 @@ export function finder(input, options) {
35
35
  return selector(path);
36
36
  }
37
37
  else {
38
- throw new Error(`Selector was not found.`);
38
+ throw new Error('Selector was not found.');
39
39
  }
40
40
  }
41
41
  function findRootDocument(rootNode, defaults) {
@@ -49,30 +49,33 @@ function findRootDocument(rootNode, defaults) {
49
49
  }
50
50
  function bottomUpSearch(input, limit, fallback) {
51
51
  let path = null;
52
- let stack = [];
52
+ const stack = [];
53
53
  let current = input;
54
54
  let i = 0;
55
55
  while (current && current !== config.root.parentElement) {
56
- let level = maybe(id(current)) || maybe(...attr(current)) || maybe(...classNames(current)) || maybe(tagName(current)) || [any()];
56
+ let level = maybe(id(current)) ||
57
+ maybe(...attr(current)) ||
58
+ maybe(...classNames(current)) ||
59
+ maybe(tagName(current)) || [any()];
57
60
  const nth = index(current);
58
61
  if (limit === Limit.All) {
59
62
  if (nth) {
60
- level = level.concat(level.filter(dispensableNth).map(node => nthChild(node, nth)));
63
+ level = level.concat(level.filter(dispensableNth).map((node) => nthChild(node, nth)));
61
64
  }
62
65
  }
63
66
  else if (limit === Limit.Two) {
64
67
  level = level.slice(0, 1);
65
68
  if (nth) {
66
- level = level.concat(level.filter(dispensableNth).map(node => nthChild(node, nth)));
69
+ level = level.concat(level.filter(dispensableNth).map((node) => nthChild(node, nth)));
67
70
  }
68
71
  }
69
72
  else if (limit === Limit.One) {
70
- const [node] = level = level.slice(0, 1);
73
+ const [node] = (level = level.slice(0, 1));
71
74
  if (nth && dispensableNth(node)) {
72
75
  level = [nthChild(node, nth)];
73
76
  }
74
77
  }
75
- for (let node of level) {
78
+ for (const node of level) {
76
79
  node.level = i;
77
80
  }
78
81
  stack.push(level);
@@ -95,7 +98,7 @@ function findUniquePath(stack, fallback) {
95
98
  if (paths.length > config.threshold) {
96
99
  return fallback ? fallback() : null;
97
100
  }
98
- for (let candidate of paths) {
101
+ for (const candidate of paths) {
99
102
  if (unique(candidate)) {
100
103
  return candidate;
101
104
  }
@@ -118,7 +121,7 @@ function selector(path) {
118
121
  return query;
119
122
  }
120
123
  function penalty(path) {
121
- return path.map(node => node.penalty).reduce((acc, i) => acc + i, 0);
124
+ return path.map((node) => node.penalty).reduce((acc, i) => acc + i, 0);
122
125
  }
123
126
  function unique(path) {
124
127
  switch (rootDocument.querySelectorAll(selector(path)).length) {
@@ -131,10 +134,10 @@ function unique(path) {
131
134
  }
132
135
  }
133
136
  function id(input) {
134
- const elementId = input.getAttribute("id");
137
+ const elementId = input.getAttribute('id');
135
138
  if (elementId && config.idName(elementId)) {
136
139
  return {
137
- name: "#" + cssesc(elementId, { isIdentifier: true }),
140
+ name: '#' + cssesc(elementId, { isIdentifier: true }),
138
141
  penalty: 0,
139
142
  };
140
143
  }
@@ -143,16 +146,15 @@ function id(input) {
143
146
  function attr(input) {
144
147
  const attrs = Array.from(input.attributes).filter((attr) => config.attr(attr.name, attr.value));
145
148
  return attrs.map((attr) => ({
146
- name: "[" + cssesc(attr.name, { isIdentifier: true }) + "=\"" + cssesc(attr.value) + "\"]",
147
- penalty: 0.5
149
+ name: '[' + cssesc(attr.name, { isIdentifier: true }) + '="' + cssesc(attr.value) + '"]',
150
+ penalty: 0.5,
148
151
  }));
149
152
  }
150
153
  function classNames(input) {
151
- const names = Array.from(input.classList)
152
- .filter(config.className);
154
+ const names = Array.from(input.classList).filter(config.className);
153
155
  return names.map((name) => ({
154
- name: "." + cssesc(name, { isIdentifier: true }),
155
- penalty: 1
156
+ name: '.' + cssesc(name, { isIdentifier: true }),
157
+ penalty: 1,
156
158
  }));
157
159
  }
158
160
  function tagName(input) {
@@ -160,15 +162,15 @@ function tagName(input) {
160
162
  if (config.tagName(name)) {
161
163
  return {
162
164
  name,
163
- penalty: 2
165
+ penalty: 2,
164
166
  };
165
167
  }
166
168
  return null;
167
169
  }
168
170
  function any() {
169
171
  return {
170
- name: "*",
171
- penalty: 3
172
+ name: '*',
173
+ penalty: 3,
172
174
  };
173
175
  }
174
176
  function index(input) {
@@ -195,11 +197,11 @@ function index(input) {
195
197
  function nthChild(node, i) {
196
198
  return {
197
199
  name: node.name + `:nth-child(${i})`,
198
- penalty: node.penalty + 1
200
+ penalty: node.penalty + 1,
199
201
  };
200
202
  }
201
203
  function dispensableNth(node) {
202
- return node.name !== "html" && !node.name.startsWith("#");
204
+ return node.name !== 'html' && !node.name.startsWith('#');
203
205
  }
204
206
  function maybe(...level) {
205
207
  const list = level.filter(notEmpty);
@@ -214,7 +216,7 @@ function notEmpty(value) {
214
216
  function combinations(stack, path = []) {
215
217
  const paths = [];
216
218
  if (stack.length > 0) {
217
- for (let node of stack[0]) {
219
+ for (const node of stack[0]) {
218
220
  paths.push(...combinations(stack.slice(1, stack.length), path.concat(node)));
219
221
  }
220
222
  }
@@ -228,7 +230,7 @@ function sort(paths) {
228
230
  }
229
231
  function optimize(path, input, scope = {
230
232
  counter: 0,
231
- visited: new Map()
233
+ visited: new Map(),
232
234
  }) {
233
235
  const paths = [];
234
236
  if (path.length > 2 && path.length > config.optimizedMinLength) {
@@ -259,20 +261,20 @@ const regexAnySingleEscape = /[ -,\.\/:-@\[-\^`\{-~]/;
259
261
  const regexSingleEscape = /[ -,\.\/:-@\[\]\^`\{-~]/;
260
262
  const regexExcessiveSpaces = /(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g;
261
263
  const defaultOptions = {
262
- "escapeEverything": false,
263
- "isIdentifier": false,
264
- "quotes": "single",
265
- "wrap": false
264
+ escapeEverything: false,
265
+ isIdentifier: false,
266
+ quotes: 'single',
267
+ wrap: false,
266
268
  };
267
269
  function cssesc(string, opt = {}) {
268
270
  const options = Object.assign(Object.assign({}, defaultOptions), opt);
269
- if (options.quotes != "single" && options.quotes != "double") {
270
- options.quotes = "single";
271
+ if (options.quotes != 'single' && options.quotes != 'double') {
272
+ options.quotes = 'single';
271
273
  }
272
- const quote = options.quotes == "double" ? "\"" : "'";
274
+ const quote = options.quotes == 'double' ? '"' : "'";
273
275
  const isIdentifier = options.isIdentifier;
274
276
  const firstChar = string.charAt(0);
275
- let output = "";
277
+ let output = '';
276
278
  let counter = 0;
277
279
  const length = string.length;
278
280
  while (counter < length) {
@@ -280,13 +282,13 @@ function cssesc(string, opt = {}) {
280
282
  let codePoint = character.charCodeAt(0);
281
283
  let value = void 0;
282
284
  // If it’s not a printable ASCII character…
283
- if (codePoint < 0x20 || codePoint > 0x7E) {
284
- if (codePoint >= 0xD800 && codePoint <= 0xDBFF && counter < length) {
285
+ if (codePoint < 0x20 || codePoint > 0x7e) {
286
+ if (codePoint >= 0xd800 && codePoint <= 0xdbff && counter < length) {
285
287
  // It’s a high surrogate, and there is a next character.
286
288
  const extra = string.charCodeAt(counter++);
287
- if ((extra & 0xFC00) == 0xDC00) {
289
+ if ((extra & 0xfc00) == 0xdc00) {
288
290
  // next character is low surrogate
289
- codePoint = ((codePoint & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000;
291
+ codePoint = ((codePoint & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000;
290
292
  }
291
293
  else {
292
294
  // It’s an unmatched surrogate; only append this code unit, in case
@@ -294,22 +296,25 @@ function cssesc(string, opt = {}) {
294
296
  counter--;
295
297
  }
296
298
  }
297
- value = "\\" + codePoint.toString(16).toUpperCase() + " ";
299
+ value = '\\' + codePoint.toString(16).toUpperCase() + ' ';
298
300
  }
299
301
  else {
300
302
  if (options.escapeEverything) {
301
303
  if (regexAnySingleEscape.test(character)) {
302
- value = "\\" + character;
304
+ value = '\\' + character;
303
305
  }
304
306
  else {
305
- value = "\\" + codePoint.toString(16).toUpperCase() + " ";
307
+ value = '\\' + codePoint.toString(16).toUpperCase() + ' ';
306
308
  }
307
309
  }
308
310
  else if (/[\t\n\f\r\x0B]/.test(character)) {
309
- value = "\\" + codePoint.toString(16).toUpperCase() + " ";
311
+ value = '\\' + codePoint.toString(16).toUpperCase() + ' ';
310
312
  }
311
- else if (character == "\\" || !isIdentifier && (character == "\"" && quote == character || character == "'" && quote == character) || isIdentifier && regexSingleEscape.test(character)) {
312
- value = "\\" + character;
313
+ else if (character == '\\' ||
314
+ (!isIdentifier &&
315
+ ((character == '"' && quote == character) || (character == "'" && quote == character))) ||
316
+ (isIdentifier && regexSingleEscape.test(character))) {
317
+ value = '\\' + character;
313
318
  }
314
319
  else {
315
320
  value = character;
@@ -319,10 +324,10 @@ function cssesc(string, opt = {}) {
319
324
  }
320
325
  if (isIdentifier) {
321
326
  if (/^-[-\d]/.test(output)) {
322
- output = "\\-" + output.slice(1);
327
+ output = '\\-' + output.slice(1);
323
328
  }
324
329
  else if (/\d/.test(firstChar)) {
325
- output = "\\3" + firstChar + " " + output.slice(1);
330
+ output = '\\3' + firstChar + ' ' + output.slice(1);
326
331
  }
327
332
  }
328
333
  // Remove spaces after `\HEX` escapes that are not followed by a hex digit,
@@ -334,7 +339,7 @@ function cssesc(string, opt = {}) {
334
339
  return $0;
335
340
  }
336
341
  // Strip the space.
337
- return ($1 || "") + $2;
342
+ return ($1 || '') + $2;
338
343
  });
339
344
  if (!isIdentifier && options.wrap) {
340
345
  return quote + output + quote;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@openreplay/tracker",
3
3
  "description": "The OpenReplay tracker main package",
4
- "version": "3.6.2",
4
+ "version": "4.0.1",
5
5
  "keywords": [
6
6
  "logging",
7
7
  "replay"
@@ -14,33 +14,50 @@
14
14
  "type": "module",
15
15
  "main": "./lib/index.js",
16
16
  "scripts": {
17
- "lint": "eslint src --ext .ts,.js --fix && tsc --noEmit",
17
+ "lint": "eslint src --ext .ts,.js --fix --quiet",
18
18
  "clean": "rm -Rf build && rm -Rf lib && rm -Rf cjs",
19
- "tsc": "tsc -b src/main && tsc -b src/webworker && tsc --project src/main/tsconfig-cjs.json",
19
+ "tscRun": "tsc -b src/main && tsc -b src/webworker && tsc --project src/main/tsconfig-cjs.json",
20
20
  "rollup": "rollup --config rollup.config.js",
21
21
  "compile": "node --experimental-modules --experimental-json-modules scripts/compile.cjs",
22
- "build": "npm run clean && npm run tsc && npm run rollup && npm run compile",
23
- "prepare": "node scripts/checkver.cjs && npm run build"
22
+ "build": "npm run clean && npm run tscRun && npm run rollup && npm run compile",
23
+ "prepare": "cd ../../ && husky install tracker/.husky/",
24
+ "lint-front": "lint-staged"
24
25
  },
25
26
  "devDependencies": {
26
27
  "@babel/core": "^7.10.2",
27
28
  "@rollup/plugin-babel": "^5.0.3",
28
29
  "@rollup/plugin-node-resolve": "^10.0.0",
29
- "@typescript-eslint/eslint-plugin": "^4.33.0",
30
- "@typescript-eslint/parser": "^4.33.0",
30
+ "@typescript-eslint/eslint-plugin": "^5.30.0",
31
+ "@typescript-eslint/parser": "^5.30.0",
31
32
  "eslint": "^7.8.0",
32
- "eslint-plugin-prettier": "^4.1.4",
33
- "prettier": "^2.0.0",
33
+ "eslint-config-prettier": "^8.5.0",
34
+ "eslint-plugin-prettier": "^4.2.1",
35
+ "husky": "^8.0.1",
36
+ "lint-staged": "^13.0.3",
37
+ "prettier": "^2.7.1",
34
38
  "replace-in-files": "^2.0.3",
35
39
  "rollup": "^2.17.0",
36
40
  "rollup-plugin-terser": "^6.1.0",
37
41
  "semver": "^6.3.0",
38
- "typescript": "^4.6.0-dev.20211126"
42
+ "typescript": "4.6.0-dev.20211126"
39
43
  },
40
44
  "dependencies": {
41
45
  "error-stack-parser": "^2.0.6"
42
46
  },
43
47
  "engines": {
44
48
  "node": ">=14.0"
49
+ },
50
+ "husky": {
51
+ "hooks": {
52
+ "pre-commit": "sh lint.sh"
53
+ }
54
+ },
55
+ "lint-staged": {
56
+ "*.{js,mjs,jsx,ts,tsx}": [
57
+ "eslint --fix --quiet"
58
+ ],
59
+ "*.{json,md,html,js,jsx,ts,tsx}": [
60
+ "prettier --write"
61
+ ]
45
62
  }
46
63
  }