lighthouse-reporting 1.3.1 → 1.5.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.
package/README.md CHANGED
@@ -92,12 +92,16 @@ import {
92
92
  LighthouseResult,
93
93
  StorybookIndexStory,
94
94
  storybookPlaywright,
95
+ writeScoresToJson
95
96
  } from 'lighthouse-reporting'
96
97
 
97
98
  playwrightLighthouseTest.setTimeout(60000)
98
- const reportDir = path.join(process.cwd(), process.env.LH_REPORT_DIR as string)
99
+ const lhScoresDir = path.join(process.cwd(), process.env.LH_SCORES_DIR || 'lh-scores')
100
+ const reportDir = path.join(process.cwd(), process.env.LH_REPORT_DIR || 'lighthouse')
99
101
  const htmlFilePath = path.join(reportDir, 'index.html')
100
102
 
103
+ // use stories.json instead of index.json for storybook v6
104
+ // make sure to set buildStoriesJson to true in storybook main.js feature section
101
105
  const stories = storybookPlaywright.getStories('./storybook-static/index.json', (story) => {
102
106
  // skip docs, etc
103
107
  if (story.type !== 'story') {
@@ -147,6 +151,8 @@ const runLighthouse = async (story: StorybookIndexStory, context: BrowserContext
147
151
  const scores = getScores(result)
148
152
  await writeCsvResult(reportDir, name, scores, thresholds)
149
153
  await writeHtmlListEntryWithRetry(htmlFilePath, name, scores, thresholds, result.comparisonError)
154
+ // write score results in JSON, allows generating the Average csv report
155
+ await writeScoresToJson(lhScoresDir, name, scores, result)
150
156
  }
151
157
  ```
152
158
 
@@ -162,6 +168,8 @@ import { PlaywrightTestConfig } from '@playwright/test'
162
168
 
163
169
  const baseURL = 'http://127.0.0.1:6009'
164
170
  // process.env.LH_REPORT_DIR = 'lighthouse-storybook' // adjust lighthouse output folder if required
171
+ // process.env.LH_SCORES_DIR = 'lh-scores' // to write and store scores in json format or write average report
172
+
165
173
 
166
174
  const config: PlaywrightTestConfig = {
167
175
  use: {
@@ -209,49 +217,13 @@ export default config
209
217
  <summary>global-setup.ts</summary>
210
218
 
211
219
  ```ts
212
- import { PlaywrightTestConfig } from '@playwright/test'
213
-
214
- const baseURL = 'http://127.0.0.1:6009'
215
- // process.env.LH_REPORT_DIR = 'lighthouse-storybook' // adjust lighthouse output folder if required
220
+ import { lighthouseSetup } from 'lighthouse-reporting'
216
221
 
217
- const config: PlaywrightTestConfig = {
218
- use: {
219
- viewport: { width: 1280, height: 820 },
220
- ignoreHTTPSErrors: true,
221
- acceptDownloads: false,
222
- trace: 'off',
223
- baseURL,
224
- screenshot: { mode: 'off' },
225
- },
226
- projects: [
227
- {
228
- name: 'chromium',
229
- use: {
230
- browserName: 'chromium',
231
- launchOptions: { args: ['--disable-gpu'] },
232
- },
233
- retries: 0,
234
- },
235
- ],
236
- expect: { toMatchSnapshot: { threshold: 0.2 } },
237
- reporter: 'line',
238
- testDir: 'test/storybook',
239
- testMatch: '*.spec.ts',
240
- fullyParallel: true,
241
- globalSetup: './src/global-setup.ts',
242
- globalTeardown: './src/global-teardown.ts',
243
- forbidOnly: true,
244
- webServer: [
245
- {
246
- command: 'npx http-server ./storybook-static --port 6009 --silent',
247
- url: `${baseURL}/index.json`,
248
- timeout: 15 * 1000,
249
- reuseExistingServer: false,
250
- ignoreHTTPSErrors: true,
251
- },
252
- ],
222
+ async function globalSetup() {
223
+ await lighthouseSetup()
253
224
  }
254
- export default config
225
+
226
+ export default globalSetup
255
227
  ```
256
228
 
257
229
  </details>
@@ -260,10 +232,14 @@ export default config
260
232
  <summary>global-teardown.ts</summary>
261
233
 
262
234
  ```ts
263
- import { lighthousePlaywrightTeardown } from 'lighthouse-reporting'
235
+ import { lighthousePlaywrightTeardown, buildAverageCsv } from 'lighthouse-reporting'
236
+
237
+ const lhScoresDir = path.join(process.cwd(), process.env.LH_SCORES_DIR || 'lh-scores')
238
+ const reportDir = path.join(process.cwd(), 'lighthouse')
264
239
 
265
240
  async function globalTeardown() {
266
241
  await lighthousePlaywrightTeardown()
242
+ await buildAverageCsv(lhScoresDir, reportDir)
267
243
  }
268
244
 
269
245
  export default globalTeardown
package/dist/index.cjs CHANGED
@@ -13,8 +13,10 @@ require("get-port");
13
13
  require("@playwright/test");
14
14
  exports.lighthousePlaywrightTeardown = hooks.lighthousePlaywrightTeardown;
15
15
  exports.lighthouseSetup = hooks.lighthouseSetup;
16
+ exports.buildAverageCsv = lighthouseReports.buildAverageCsv;
16
17
  exports.getScores = lighthouseReports.getScores;
17
18
  exports.writeCsvResult = lighthouseReports.writeCsvResult;
18
19
  exports.writeHtmlListEntryWithRetry = lighthouseReports.writeHtmlListEntryWithRetry;
20
+ exports.writeScoresToJson = lighthouseReports.writeScoresToJson;
19
21
  exports.playwrightLighthouseTest = playwrightLighthouseTest.playwrightLighthouseTest;
20
22
  exports.storybookPlaywright = storybookPlaywright.storybookPlaywright;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { lighthousePlaywrightTeardown, lighthouseSetup } from "./hooks.js";
2
- import { getScores, writeCsvResult, writeHtmlListEntryWithRetry } from "./lighthouseReports.js";
2
+ import { buildAverageCsv, getScores, writeCsvResult, writeHtmlListEntryWithRetry, writeScoresToJson } from "./lighthouseReports.js";
3
3
  import { playwrightLighthouseTest } from "./playwrightLighthouseTest.js";
4
4
  import { storybookPlaywright } from "./storybookPlaywright.js";
5
5
  import "os";
@@ -10,11 +10,13 @@ import "./constants-226e9774.js";
10
10
  import "get-port";
11
11
  import "@playwright/test";
12
12
  export {
13
+ buildAverageCsv,
13
14
  getScores,
14
15
  lighthousePlaywrightTeardown,
15
16
  lighthouseSetup,
16
17
  playwrightLighthouseTest,
17
18
  storybookPlaywright,
18
19
  writeCsvResult,
19
- writeHtmlListEntryWithRetry
20
+ writeHtmlListEntryWithRetry,
21
+ writeScoresToJson
20
22
  };
@@ -21,14 +21,14 @@
21
21
  async function lighthousePlaywrightTeardown() {
22
22
  await fse.remove(path.join(os.tmpdir(), PW_TMP_DIR));
23
23
  }
24
- const writeCsvResult = async (reportDir2, name, scores, thresholds, swimlanes = []) => {
24
+ const writeCsvResult = async (reportDir2, name, scores, thresholds = {}, swimlanes = []) => {
25
25
  let csvData = Object.keys(scores).join(",");
26
26
  if (swimlanes.length > 0) {
27
27
  csvData += "," + swimlanes.map((swimlane) => `${swimlane}_threshold`);
28
28
  }
29
29
  csvData += "\n";
30
30
  csvData += Object.values(scores).join(",");
31
- if (swimlanes.length > 0) {
31
+ if (swimlanes.length > 0 && Object.keys(thresholds).length > 0) {
32
32
  csvData += "," + swimlanes.map((swimlane) => thresholds[swimlane]);
33
33
  }
34
34
  await fse.writeFile(path.join(reportDir2, `${name}.csv`), csvData);
@@ -61,6 +61,45 @@
61
61
  prev[key] = Math.floor(c.score * 100);
62
62
  return prev;
63
63
  }, {});
64
+ const writeScoresToJson = async (lhScoresDir, name, scores, result) => {
65
+ const json = Object.entries(scores).reduce((prev, [k, score]) => {
66
+ prev[k] = { score };
67
+ return prev;
68
+ }, {});
69
+ const accessibilityViolations = result.artifacts.Accessibility.violations.map((v) => {
70
+ return {
71
+ title: result.lhr.audits[v.id].title,
72
+ nodes: v.nodes.length
73
+ };
74
+ });
75
+ if (accessibilityViolations.length > 0) {
76
+ json.accessibility.issues = accessibilityViolations;
77
+ }
78
+ await fse.writeFile(path.join(lhScoresDir, `${name}.json`), JSON.stringify(json, null, 2));
79
+ };
80
+ const buildAverageCsv = async (lhScoresDir, reportDir2) => {
81
+ const files = await fse.readdir(lhScoresDir);
82
+ const jsonFiles = files.filter((f) => f.endsWith(".json"));
83
+ if (jsonFiles.length === 0) {
84
+ return;
85
+ }
86
+ const scores = {};
87
+ for (const fileName of jsonFiles) {
88
+ const score = await fse.readJson(
89
+ path.join(lhScoresDir, fileName)
90
+ );
91
+ Object.entries(score).forEach(([k, v]) => {
92
+ if (!scores[k]) {
93
+ scores[k] = 0;
94
+ }
95
+ scores[k] += v.score;
96
+ });
97
+ }
98
+ Object.entries(scores).forEach(([k, v]) => {
99
+ scores[k] = v / jsonFiles.length;
100
+ });
101
+ await writeCsvResult(reportDir2, "_AVERAGE_", scores);
102
+ };
64
103
  class Locked extends Error {
65
104
  constructor(port) {
66
105
  super(`${port} is locked`);
@@ -71,7 +110,7 @@
71
110
  young: /* @__PURE__ */ new Set()
72
111
  };
73
112
  const releaseOldLockedPortsIntervalMs = 1e3 * 15;
74
- let interval;
113
+ let timeout;
75
114
  const getLocalHosts = () => {
76
115
  const interfaces = os.networkInterfaces();
77
116
  const results = /* @__PURE__ */ new Set([void 0, "0.0.0.0"]);
@@ -137,13 +176,14 @@
137
176
  exclude = new Set(excludeIterable);
138
177
  }
139
178
  }
140
- if (interval === void 0) {
141
- interval = setInterval(() => {
179
+ if (timeout === void 0) {
180
+ timeout = setTimeout(() => {
181
+ timeout = void 0;
142
182
  lockedPorts.old = lockedPorts.young;
143
183
  lockedPorts.young = /* @__PURE__ */ new Set();
144
184
  }, releaseOldLockedPortsIntervalMs);
145
- if (interval.unref) {
146
- interval.unref();
185
+ if (timeout.unref) {
186
+ timeout.unref();
147
187
  }
148
188
  }
149
189
  const hosts = getLocalHosts();
@@ -199,7 +239,8 @@
199
239
  throw new Error("Please build storybook before running tests!");
200
240
  }
201
241
  const storybookIndexJson = fse.readJsonSync(pathToStorybookIndexJson);
202
- const stories = Object.values(storybookIndexJson.entries).filter(storyFilterFn);
242
+ const storyObject = storybookIndexJson.entries || storybookIndexJson.stories;
243
+ const stories = Object.values(storyObject).filter(storyFilterFn);
203
244
  return stories;
204
245
  },
205
246
  captureScreenshot: async (story, context, screenshotOptions, actionBeforeScreenshot) => {
@@ -214,6 +255,7 @@
214
255
  await test.expect(page).toHaveScreenshot(`${story.id}.png`, screenshotOptions);
215
256
  }
216
257
  };
258
+ exports2.buildAverageCsv = buildAverageCsv;
217
259
  exports2.getScores = getScores;
218
260
  exports2.lighthousePlaywrightTeardown = lighthousePlaywrightTeardown;
219
261
  exports2.lighthouseSetup = lighthouseSetup;
@@ -221,5 +263,6 @@
221
263
  exports2.storybookPlaywright = storybookPlaywright;
222
264
  exports2.writeCsvResult = writeCsvResult;
223
265
  exports2.writeHtmlListEntryWithRetry = writeHtmlListEntryWithRetry;
266
+ exports2.writeScoresToJson = writeScoresToJson;
224
267
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
225
268
  });
@@ -2,14 +2,14 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const path = require("path");
4
4
  const fse = require("fs-extra");
5
- const writeCsvResult = async (reportDir, name, scores, thresholds, swimlanes = []) => {
5
+ const writeCsvResult = async (reportDir, name, scores, thresholds = {}, swimlanes = []) => {
6
6
  let csvData = Object.keys(scores).join(",");
7
7
  if (swimlanes.length > 0) {
8
8
  csvData += "," + swimlanes.map((swimlane) => `${swimlane}_threshold`);
9
9
  }
10
10
  csvData += "\n";
11
11
  csvData += Object.values(scores).join(",");
12
- if (swimlanes.length > 0) {
12
+ if (swimlanes.length > 0 && Object.keys(thresholds).length > 0) {
13
13
  csvData += "," + swimlanes.map((swimlane) => thresholds[swimlane]);
14
14
  }
15
15
  await fse.writeFile(path.join(reportDir, `${name}.csv`), csvData);
@@ -42,6 +42,47 @@ const getScores = (result) => Object.entries(result.lhr.categories).reduce((prev
42
42
  prev[key] = Math.floor(c.score * 100);
43
43
  return prev;
44
44
  }, {});
45
+ const writeScoresToJson = async (lhScoresDir, name, scores, result) => {
46
+ const json = Object.entries(scores).reduce((prev, [k, score]) => {
47
+ prev[k] = { score };
48
+ return prev;
49
+ }, {});
50
+ const accessibilityViolations = result.artifacts.Accessibility.violations.map((v) => {
51
+ return {
52
+ title: result.lhr.audits[v.id].title,
53
+ nodes: v.nodes.length
54
+ };
55
+ });
56
+ if (accessibilityViolations.length > 0) {
57
+ json.accessibility.issues = accessibilityViolations;
58
+ }
59
+ await fse.writeFile(path.join(lhScoresDir, `${name}.json`), JSON.stringify(json, null, 2));
60
+ };
61
+ const buildAverageCsv = async (lhScoresDir, reportDir) => {
62
+ const files = await fse.readdir(lhScoresDir);
63
+ const jsonFiles = files.filter((f) => f.endsWith(".json"));
64
+ if (jsonFiles.length === 0) {
65
+ return;
66
+ }
67
+ const scores = {};
68
+ for (const fileName of jsonFiles) {
69
+ const score = await fse.readJson(
70
+ path.join(lhScoresDir, fileName)
71
+ );
72
+ Object.entries(score).forEach(([k, v]) => {
73
+ if (!scores[k]) {
74
+ scores[k] = 0;
75
+ }
76
+ scores[k] += v.score;
77
+ });
78
+ }
79
+ Object.entries(scores).forEach(([k, v]) => {
80
+ scores[k] = v / jsonFiles.length;
81
+ });
82
+ await writeCsvResult(reportDir, "_AVERAGE_", scores);
83
+ };
84
+ exports.buildAverageCsv = buildAverageCsv;
45
85
  exports.getScores = getScores;
46
86
  exports.writeCsvResult = writeCsvResult;
47
87
  exports.writeHtmlListEntryWithRetry = writeHtmlListEntryWithRetry;
88
+ exports.writeScoresToJson = writeScoresToJson;
@@ -1,3 +1,29 @@
1
+ interface NodeDetails {
2
+ lhId: string;
3
+ devtoolsNodePath: string;
4
+ selector: string;
5
+ boudingRect: {
6
+ [k: string]: number;
7
+ };
8
+ snippet: string;
9
+ nodeLabel: string;
10
+ }
11
+ interface RuleExecutionError {
12
+ name: string;
13
+ message: string;
14
+ }
15
+ interface AxeRuleResult {
16
+ id: string;
17
+ impact?: string;
18
+ tags: Array<string>;
19
+ nodes: Array<{
20
+ target: Array<string>;
21
+ failureSummary?: string;
22
+ node: NodeDetails;
23
+ relatedNodes: NodeDetails[];
24
+ }>;
25
+ error?: RuleExecutionError;
26
+ }
1
27
  export interface LighthouseResult {
2
28
  lhr: {
3
29
  categories: {
@@ -5,12 +31,30 @@ export interface LighthouseResult {
5
31
  score: number;
6
32
  };
7
33
  };
34
+ audits: {
35
+ [k: string]: {
36
+ title: string;
37
+ };
38
+ };
39
+ };
40
+ artifacts: {
41
+ Accessibility: {
42
+ violations: Array<AxeRuleResult>;
43
+ };
8
44
  };
9
45
  comparisonError?: string;
10
46
  }
11
- export declare const writeCsvResult: (reportDir: string, name: string, scores: Record<string, number>, thresholds: Record<string, number>, swimlanes?: Array<string>) => Promise<void>;
47
+ export declare const writeCsvResult: (reportDir: string, name: string, scores: Record<string, number>, thresholds?: Record<string, number>, swimlanes?: Array<string>) => Promise<void>;
12
48
  /**
13
49
  * workaround conflicts when multiple threads write the same file
14
50
  */
15
51
  export declare const writeHtmlListEntryWithRetry: (htmlFilePath: string, name: string, scores: Record<string, number>, thresholds: Record<string, number>, comparisonError?: string, addReportLink?: boolean) => Promise<void>;
16
52
  export declare const getScores: (result: LighthouseResult) => Record<string, number>;
53
+ export declare const writeScoresToJson: (lhScoresDir: string, name: string, scores: Record<string, number>, result: LighthouseResult) => Promise<void>;
54
+ /**
55
+ * Generate average csv file. Make sure to use `writeScoresToJson` in your test!
56
+ * @param lhScoresDir path to folder with lighthouse json files. See `writeScoresToJson`.
57
+ * @param reportDir folder where `_AVERAGE_.json` will be generated
58
+ */
59
+ export declare const buildAverageCsv: (lhScoresDir: string, reportDir: string) => Promise<void>;
60
+ export {};
@@ -1,13 +1,13 @@
1
1
  import path from "path";
2
2
  import fse from "fs-extra";
3
- const writeCsvResult = async (reportDir, name, scores, thresholds, swimlanes = []) => {
3
+ const writeCsvResult = async (reportDir, name, scores, thresholds = {}, swimlanes = []) => {
4
4
  let csvData = Object.keys(scores).join(",");
5
5
  if (swimlanes.length > 0) {
6
6
  csvData += "," + swimlanes.map((swimlane) => `${swimlane}_threshold`);
7
7
  }
8
8
  csvData += "\n";
9
9
  csvData += Object.values(scores).join(",");
10
- if (swimlanes.length > 0) {
10
+ if (swimlanes.length > 0 && Object.keys(thresholds).length > 0) {
11
11
  csvData += "," + swimlanes.map((swimlane) => thresholds[swimlane]);
12
12
  }
13
13
  await fse.writeFile(path.join(reportDir, `${name}.csv`), csvData);
@@ -40,8 +40,49 @@ const getScores = (result) => Object.entries(result.lhr.categories).reduce((prev
40
40
  prev[key] = Math.floor(c.score * 100);
41
41
  return prev;
42
42
  }, {});
43
+ const writeScoresToJson = async (lhScoresDir, name, scores, result) => {
44
+ const json = Object.entries(scores).reduce((prev, [k, score]) => {
45
+ prev[k] = { score };
46
+ return prev;
47
+ }, {});
48
+ const accessibilityViolations = result.artifacts.Accessibility.violations.map((v) => {
49
+ return {
50
+ title: result.lhr.audits[v.id].title,
51
+ nodes: v.nodes.length
52
+ };
53
+ });
54
+ if (accessibilityViolations.length > 0) {
55
+ json.accessibility.issues = accessibilityViolations;
56
+ }
57
+ await fse.writeFile(path.join(lhScoresDir, `${name}.json`), JSON.stringify(json, null, 2));
58
+ };
59
+ const buildAverageCsv = async (lhScoresDir, reportDir) => {
60
+ const files = await fse.readdir(lhScoresDir);
61
+ const jsonFiles = files.filter((f) => f.endsWith(".json"));
62
+ if (jsonFiles.length === 0) {
63
+ return;
64
+ }
65
+ const scores = {};
66
+ for (const fileName of jsonFiles) {
67
+ const score = await fse.readJson(
68
+ path.join(lhScoresDir, fileName)
69
+ );
70
+ Object.entries(score).forEach(([k, v]) => {
71
+ if (!scores[k]) {
72
+ scores[k] = 0;
73
+ }
74
+ scores[k] += v.score;
75
+ });
76
+ }
77
+ Object.entries(scores).forEach(([k, v]) => {
78
+ scores[k] = v / jsonFiles.length;
79
+ });
80
+ await writeCsvResult(reportDir, "_AVERAGE_", scores);
81
+ };
43
82
  export {
83
+ buildAverageCsv,
44
84
  getScores,
45
85
  writeCsvResult,
46
- writeHtmlListEntryWithRetry
86
+ writeHtmlListEntryWithRetry,
87
+ writeScoresToJson
47
88
  };
@@ -9,7 +9,8 @@ const storybookPlaywright = {
9
9
  throw new Error("Please build storybook before running tests!");
10
10
  }
11
11
  const storybookIndexJson = fse.readJsonSync(pathToStorybookIndexJson);
12
- const stories = Object.values(storybookIndexJson.entries).filter(storyFilterFn);
12
+ const storyObject = storybookIndexJson.entries || storybookIndexJson.stories;
13
+ const stories = Object.values(storyObject).filter(storyFilterFn);
13
14
  return stories;
14
15
  },
15
16
  captureScreenshot: async (story, context, screenshotOptions, actionBeforeScreenshot) => {
@@ -1,4 +1,7 @@
1
1
  import { BrowserContext, Locator, Page } from '@playwright/test';
2
+ /**
3
+ * Storybook v7
4
+ */
2
5
  export interface StorybookIndexStory {
3
6
  id: string;
4
7
  title: string;
@@ -7,7 +10,23 @@ export interface StorybookIndexStory {
7
10
  tags: Array<string>;
8
11
  type: 'story' | 'docs';
9
12
  }
10
- type StoriesFilterFn = (story: StorybookIndexStory) => boolean;
13
+ /**
14
+ * Storybook v6
15
+ */
16
+ export interface StorybookStoriesStory {
17
+ id: string;
18
+ title: string;
19
+ name: string;
20
+ importPath: string;
21
+ kind: string;
22
+ story: string;
23
+ parameters: {
24
+ __id: string;
25
+ docsOnly: boolean;
26
+ fileName: string;
27
+ };
28
+ }
29
+ type StoriesFilterFn = <V7 = true>(story: V7 extends true ? StorybookIndexStory : StorybookStoriesStory) => boolean;
11
30
  export declare const storybookPlaywright: {
12
31
  getStories: (pathToStorybookIndexJson: string, storyFilterFn: StoriesFilterFn) => StorybookIndexStory[];
13
32
  captureScreenshot: (story: StorybookIndexStory, context: BrowserContext, screenshotOptions?: {
@@ -7,7 +7,8 @@ const storybookPlaywright = {
7
7
  throw new Error("Please build storybook before running tests!");
8
8
  }
9
9
  const storybookIndexJson = fse.readJsonSync(pathToStorybookIndexJson);
10
- const stories = Object.values(storybookIndexJson.entries).filter(storyFilterFn);
10
+ const storyObject = storybookIndexJson.entries || storybookIndexJson.stories;
11
+ const stories = Object.values(storyObject).filter(storyFilterFn);
11
12
  return stories;
12
13
  },
13
14
  captureScreenshot: async (story, context, screenshotOptions, actionBeforeScreenshot) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lighthouse-reporting",
3
- "version": "1.3.1",
3
+ "version": "1.5.0",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "vite build && vite build -c vite.umd.config.ts && tsc -p ./tsconfig.build.json",
@@ -24,25 +24,25 @@
24
24
  },
25
25
  "optionalDependencies": {
26
26
  "@playwright/test": "^1",
27
- "get-port": "^6"
27
+ "get-port": ">=7"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@playwright/test": "^1.34.3",
31
31
  "@types/fs-extra": "^11.0.1",
32
- "@types/node": "^20.2.4",
33
- "@typescript-eslint/eslint-plugin": "^5.59.7",
34
- "@typescript-eslint/parser": "^5.59.7",
35
- "eslint": "^8.41.0",
32
+ "@types/node": "^20.3.1",
33
+ "@typescript-eslint/eslint-plugin": "^5.60.0",
34
+ "@typescript-eslint/parser": "^5.60.0",
35
+ "eslint": "^8.43.0",
36
36
  "eslint-config-prettier": "^8.8.0",
37
37
  "eslint-plugin-prettier": "^4.2.1",
38
- "get-port": "^6.1.2",
38
+ "get-port": "^7.0.0",
39
39
  "husky": "^8.0.3",
40
40
  "npm-run-all": "^4.1.5",
41
41
  "prettier": "^2.8.8",
42
- "semantic-release": "^21.0.2",
43
- "typescript": "^5.0.4",
42
+ "semantic-release": "^21.0.5",
43
+ "typescript": "^5.1.3",
44
44
  "vite": "^4.3.9",
45
- "vite-plugin-static-copy": "^0.15.0"
45
+ "vite-plugin-static-copy": "^0.16.0"
46
46
  },
47
47
  "dependencies": {
48
48
  "fs-extra": "^11.1.1"