From 84e309ee10956821abec27aef8c31b82694e9385 Mon Sep 17 00:00:00 2001 From: Pellya Roman Date: Wed, 11 Mar 2026 11:27:25 +0300 Subject: [PATCH 1/6] Add module testing for analyze articles for Polytech subject --- .../article-analyzer/__tests__/graph.test.ts | 43 ++++++++ .../article-analyzer/__tests__/loader.test.ts | 98 +++++++++++++++++++ .../__tests__/pagerank.test.ts | 43 ++++++++ .../__tests__/validator.test.ts | 21 ++++ json-server/article-analyzer/graph.ts | 72 ++++++++++++++ json-server/article-analyzer/loader.ts | 58 +++++++++++ json-server/article-analyzer/pagerank.ts | 86 ++++++++++++++++ json-server/article-analyzer/types.ts | 16 +++ json-server/article-analyzer/validator.ts | 21 ++++ 9 files changed, 458 insertions(+) create mode 100644 json-server/article-analyzer/__tests__/graph.test.ts create mode 100644 json-server/article-analyzer/__tests__/loader.test.ts create mode 100644 json-server/article-analyzer/__tests__/pagerank.test.ts create mode 100644 json-server/article-analyzer/__tests__/validator.test.ts create mode 100644 json-server/article-analyzer/graph.ts create mode 100644 json-server/article-analyzer/loader.ts create mode 100644 json-server/article-analyzer/pagerank.ts create mode 100644 json-server/article-analyzer/types.ts create mode 100644 json-server/article-analyzer/validator.ts diff --git a/json-server/article-analyzer/__tests__/graph.test.ts b/json-server/article-analyzer/__tests__/graph.test.ts new file mode 100644 index 00000000..b63763f0 --- /dev/null +++ b/json-server/article-analyzer/__tests__/graph.test.ts @@ -0,0 +1,43 @@ +import { buildGraphSparse, buildGraphDense } from '../graph'; + +describe('Построение графа', () => { + const articles = [ + { id: '1', title: 'A', authors: [], year: 2020, citations: ['2'] }, + { id: '2', title: 'B', authors: [], year: 2020, citations: ['1', '3'] }, + { id: '3', title: 'C', authors: [], year: 2020, citations: ['1'] }, + ]; + + test('Разреженное представление – проверка ветвей outDegree > 0 и =0', () => { + const graph = buildGraphSparse(articles); + expect(graph.outDegree).toEqual([1, 2, 1]); + expect(graph.outLinks[0]).toEqual([1]); + expect(graph.outLinks[1]).toEqual([0, 2]); + expect(graph.outLinks[2]).toEqual([0]); + }); + + test('Плотное представление', () => { + const graph = buildGraphDense(articles); + expect(graph.matrix[0][1]).toBe(1); + expect(graph.matrix[1][0]).toBe(1); + expect(graph.matrix[1][2]).toBe(1); + expect(graph.matrix[2][0]).toBe(1); + expect(graph.matrix[0][2]).toBe(0); + }); + + test('Игнорирование отсутствующих ссылок', () => { + const articlesMissing = [ + { + id: '1', + title: 'A', + authors: [], + year: 2020, + citations: ['2', '4'], + }, + { id: '2', title: 'B', authors: [], year: 2020, citations: [] }, + ]; + const graph = buildGraphSparse(articlesMissing, { + ignoreMissing: true, + }); + expect(graph.outLinks[0]).toEqual([1]); // только ссылка на '2' + }); +}); diff --git a/json-server/article-analyzer/__tests__/loader.test.ts b/json-server/article-analyzer/__tests__/loader.test.ts new file mode 100644 index 00000000..85f91075 --- /dev/null +++ b/json-server/article-analyzer/__tests__/loader.test.ts @@ -0,0 +1,98 @@ +import fs from 'fs'; +import { Readable } from 'stream'; +import { loadArticlesFromFile } from '../loader'; + +jest.mock('fs'); + +describe('Модуль загрузки JSON', () => { + beforeEach(() => { + jest.resetAllMocks(); + }); + + test('Загрузка корректного файла', async () => { + const mockData = JSON.stringify([ + { + id: '1', + title: 'Article 1', + authors: ['A'], + year: 2020, + citations: [], + }, + ]); + const mockStream = Readable.from([mockData]); + (fs.createReadStream as jest.Mock).mockReturnValue(mockStream); + + const articles = await loadArticlesFromFile('valid.json'); + expect(articles).toHaveLength(1); + expect(articles[0]).toMatchObject({ id: '1', title: 'Article 1' }); + }); + + test('Загрузка несуществующего файла', async () => { + // Создаём поток, который сразу генерирует ошибку + const errorStream = new Readable(); + errorStream._read = () => {}; + process.nextTick(() => errorStream.emit('error', new Error('ENOENT'))); + (fs.createReadStream as jest.Mock).mockReturnValue(errorStream); + + await expect(loadArticlesFromFile('missing.json')).rejects.toThrow( + 'File not found', + ); + }); + + test('Загрузка файла с отсутствующим id', async () => { + const mockData = JSON.stringify([ + { title: 'No ID', authors: ['A'], year: 2020, citations: [] }, + ]); + const mockStream = Readable.from([mockData]); + (fs.createReadStream as jest.Mock).mockReturnValue(mockStream); + + await expect(loadArticlesFromFile('no-id.json')).rejects.toThrow( + 'Missing required field: id', + ); + }); + + test('Загрузка файла с некорректным JSON (синтаксис)', async () => { + const mockData = '{ "id": 1, "title": "Broken" '; // невалидный JSON + const mockStream = Readable.from([mockData]); + (fs.createReadStream as jest.Mock).mockReturnValue(mockStream); + + await expect( + loadArticlesFromFile('invalid-syntax.json'), + ).rejects.toThrow('Invalid JSON format'); + }); + + test('Граничные значения года: 1900 (допустимо)', async () => { + const mockData = JSON.stringify([ + { + id: '1', + title: 'Old', + authors: ['A'], + year: 1900, + citations: [], + }, + ]); + const mockStream = Readable.from([mockData]); + (fs.createReadStream as jest.Mock).mockReturnValue(mockStream); + + const articles = await loadArticlesFromFile('min-year.json'); + expect(articles[0].year).toBe(1900); + }); + + test('Граничные значения года: 1899 (недопустимо)', async () => { + const mockData = JSON.stringify([ + { + id: '1', + title: 'Too Old', + authors: ['A'], + year: 1899, + citations: [], + }, + ]); + const mockStream = Readable.from([mockData]); + (fs.createReadStream as jest.Mock).mockReturnValue(mockStream); + + await expect(loadArticlesFromFile('invalid-year.json')).rejects.toThrow( + 'Invalid year', + ); + }); +}); diff --git a/json-server/article-analyzer/__tests__/pagerank.test.ts b/json-server/article-analyzer/__tests__/pagerank.test.ts new file mode 100644 index 00000000..53ae8d4b --- /dev/null +++ b/json-server/article-analyzer/__tests__/pagerank.test.ts @@ -0,0 +1,43 @@ +/* eslint-disable no-plusplus */ +import { pagerankSparse, pagerankDense } from '../pagerank'; +import { buildGraphSparse, buildGraphDense } from '../graph'; + +describe('PageRank', () => { + const articles = [ + { id: '1', title: 'A', authors: [], year: 2020, citations: ['2'] }, + { id: '2', title: 'B', authors: [], year: 2020, citations: ['1', '3'] }, + { id: '3', title: 'C', authors: [], year: 2020, citations: ['1'] }, + ]; + const graphSparse = buildGraphSparse(articles); + const graphDense = buildGraphDense(articles); + const n = 3; + + test('Сравнение двух реализаций (результаты должны совпадать)', () => { + const prSparse = pagerankSparse(graphSparse, 0.85, 20, n); + const prDense = pagerankDense(graphDense, 0.85, 20, n); + for (let i = 0; i < n; i++) { + expect(prSparse[i]).toBeCloseTo(prDense[i], 6); + } + }); + + test('iterations = 1 (минимальное допустимое)', () => { + expect(() => pagerankSparse(graphSparse, 0.85, 1, n)).not.toThrow(); + }); + + test('iterations = 0 (недопустимо)', () => { + expect(() => pagerankSparse(graphSparse, 0.85, 0, n)).toThrow( + 'Iterations must be >= 1', + ); + }); + + test('damping = 0.5 (допустимо)', () => { + const pr = pagerankSparse(graphSparse, 0.5, 20, n); + expect(pr).toBeDefined(); + }); + + test('damping = 1 (недопустимо)', () => { + expect(() => pagerankSparse(graphSparse, 1, 20, n)).toThrow( + 'Damping must be in (0,1)', + ); + }); +}); diff --git a/json-server/article-analyzer/__tests__/validator.test.ts b/json-server/article-analyzer/__tests__/validator.test.ts new file mode 100644 index 00000000..87412234 --- /dev/null +++ b/json-server/article-analyzer/__tests__/validator.test.ts @@ -0,0 +1,21 @@ +import { validateArticle } from '../validator'; + +describe('Валидация статей', () => { + test.each([ + [{ id: null, title: 'A' }, false], // нет id + [{ id: 1, title: 'A' }, false], // id не строка + [{ id: '1' }, false], // нет title + [{ id: '1', title: null }, false], // нет title + [{ id: '1', title: 123 }, false], + [{ id: '1', title: 'A', year: 2020 }, true], + [{ id: '1', title: 'A', year: '2020' }, false], + [{ id: '1', title: 'A', year: 1899 }, false], + [{ id: '1', title: 'A' }, true], + [{ id: '1', title: 'A', authors: ['John'] }, true], + [{ id: '1', title: 'A', authors: 'John' }, false], + [{ id: '1', title: 'A', citations: ['2'] }, true], + [{ id: '1', title: 'A', citations: '2' }, false], + ])('validateArticle(%p) = %p', (input, expected) => { + expect(validateArticle(input)).toBe(expected); + }); +}); diff --git a/json-server/article-analyzer/graph.ts b/json-server/article-analyzer/graph.ts new file mode 100644 index 00000000..d69b08c8 --- /dev/null +++ b/json-server/article-analyzer/graph.ts @@ -0,0 +1,72 @@ +import { Article } from './types'; + +export interface GraphSparse { + outLinks: number[][]; // для каждой вершины список индексов исходящих соседей + inLinks: number[][]; // входящие соседи + outDegree: number[]; + n: number; +} + +export interface GraphDense { + matrix: number[][]; // плотная матрица смежности + n: number; +} + +/** + * Строит разреженное представление графа. + */ +export function buildGraphSparse( + articles: Article[], + options = { ignoreMissing: false }, +): GraphSparse { + const idToIndex = new Map(); + articles.forEach((a, idx) => idToIndex.set(a.id, idx)); + + const outLinks: number[][] = Array(articles.length) + .fill(0) + .map(() => []); + const inLinks: number[][] = Array(articles.length) + .fill(0) + .map(() => []); + const outDegree = Array(articles.length).fill(0); + + articles.forEach((article, idx) => { + const targets = article.citations + .map((ref) => idToIndex.get(ref)) + .filter((t) => t !== undefined) as number[]; + if ( + !options.ignoreMissing && + targets.length !== article.citations.length + ) { + throw new Error('Some citations refer to missing articles'); + } + outLinks[idx] = targets; + outDegree[idx] = targets.length; + targets.forEach((t) => inLinks[t].push(idx)); + }); + + return { outLinks, inLinks, outDegree, n: articles.length }; +} + +/** + * Строит плотную матрицу смежности. + */ +export function buildGraphDense(articles: Article[]): GraphDense { + const n = articles.length; + const idToIndex = new Map(); + articles.forEach((a, idx) => idToIndex.set(a.id, idx)); + + const matrix = Array(n) + .fill(0) + .map(() => Array(n).fill(0)); + articles.forEach((article, i) => { + article.citations.forEach((ref) => { + const j = idToIndex.get(ref); + if (j !== undefined) { + matrix[i][j] = 1; + } + }); + }); + + return { matrix, n }; +} diff --git a/json-server/article-analyzer/loader.ts b/json-server/article-analyzer/loader.ts new file mode 100644 index 00000000..b7e9556d --- /dev/null +++ b/json-server/article-analyzer/loader.ts @@ -0,0 +1,58 @@ +/* eslint-disable no-restricted-syntax */ +/* eslint-disable no-use-before-define */ +import { createReadStream } from 'fs'; +import { createInterface } from 'readline'; +import { Article, RawArticle } from './types'; + +/** + * Загружает статьи из JSON-файла с поддержкой потоковой обработки. + * @param filePath - путь к файлу + * @returns массив статей в нормализованном формате + */ +export async function loadArticlesFromFile( + filePath: string, +): Promise { + const stream = createReadStream(filePath, { encoding: 'utf8' }); + const rl = createInterface({ input: stream, crlfDelay: Infinity }); + + let buffer = ''; + try { + for await (const line of rl) { + buffer += line; + } + } catch (err) { + // Ошибка при чтении файла (например, файл не найден) + throw new Error('File not found'); + } + + let data; + try { + data = JSON.parse(buffer); + } catch (err) { + throw new Error('Invalid JSON format'); + } + + const articles = Array.isArray(data) ? data : data.articles; + // normalizeArticles выбросит собственную ошибку, если данные некорректны + return normalizeArticles(articles); +} + +/** + * Нормализует сырые данные статей к единому формату. + */ +export function normalizeArticles(rawArticles: RawArticle[]): Article[] { + return rawArticles.map((raw) => { + if (!raw.id) throw new Error('Missing required field: id'); + if (!raw.title) throw new Error('Missing required field: title'); + if (raw.year && (typeof raw.year !== 'number' || raw.year < 1900)) { + throw new Error('Invalid year'); + } + return { + id: String(raw.id), + title: raw.title, + authors: raw.authors || [], + year: raw.year || new Date().getFullYear(), + citations: raw.citations || raw.references || [], + }; + }); +} diff --git a/json-server/article-analyzer/pagerank.ts b/json-server/article-analyzer/pagerank.ts new file mode 100644 index 00000000..6624170e --- /dev/null +++ b/json-server/article-analyzer/pagerank.ts @@ -0,0 +1,86 @@ +/* eslint-disable no-restricted-syntax */ +/* eslint-disable no-plusplus */ +import { GraphSparse, GraphDense } from './graph'; + +/** + * Разреженная версия PageRank. + */ +export function pagerankSparse( + graph: GraphSparse, + damping: number, + iterations: number, + n: number, +): number[] { + if (iterations < 1) throw new Error('Iterations must be >= 1'); + if (damping <= 0 || damping >= 1) + throw new Error('Damping must be in (0,1)'); + + let pr = new Array(n).fill(1 / n); + const base = (1 - damping) / n; + + for (let iter = 0; iter < iterations; iter++) { + const newPr = new Array(n).fill(base); + for (let i = 0; i < n; i++) { + if (graph.outDegree[i] === 0) { + // висячая вершина: размазываем равномерно + const contribution = (damping * pr[i]) / n; + for (let j = 0; j < n; j++) { + newPr[j] += contribution; + } + } else { + const contribution = (damping * pr[i]) / graph.outDegree[i]; + for (const j of graph.outLinks[i]) { + newPr[j] += contribution; + } + } + } + pr = newPr; + } + return pr; +} + +/** + * Плотная версия PageRank. + */ +export function pagerankDense( + graph: GraphDense, + damping: number, + iterations: number, + n: number, +): number[] { + if (iterations < 1) throw new Error('Iterations must be >= 1'); + if (damping <= 0 || damping >= 1) + throw new Error('Damping must be in (0,1)'); + + // Вычисляем исходящие степени + const outDegree = Array(n).fill(0); + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + outDegree[i] += graph.matrix[i][j]; + } + } + + let pr = new Array(n).fill(1 / n); + const base = (1 - damping) / n; + + for (let iter = 0; iter < iterations; iter++) { + const newPr = new Array(n).fill(base); + for (let i = 0; i < n; i++) { + if (outDegree[i] === 0) { + const contribution = (damping * pr[i]) / n; + for (let j = 0; j < n; j++) { + newPr[j] += contribution; + } + } else { + const contribution = (damping * pr[i]) / outDegree[i]; + for (let j = 0; j < n; j++) { + if (graph.matrix[i][j] > 0) { + newPr[j] += contribution; + } + } + } + } + pr = newPr; + } + return pr; +} diff --git a/json-server/article-analyzer/types.ts b/json-server/article-analyzer/types.ts new file mode 100644 index 00000000..fb1818f2 --- /dev/null +++ b/json-server/article-analyzer/types.ts @@ -0,0 +1,16 @@ +export interface Article { + id: string; + title: string; + authors: string[]; + year: number; + citations: string[]; +} + +export interface RawArticle { + id: string | number; + title: string; + authors?: string[]; + year?: number; + citations?: string[]; + references?: string[]; +} diff --git a/json-server/article-analyzer/validator.ts b/json-server/article-analyzer/validator.ts new file mode 100644 index 00000000..5d6bca10 --- /dev/null +++ b/json-server/article-analyzer/validator.ts @@ -0,0 +1,21 @@ +export interface ArticleInput { + id?: any; + title?: any; + authors?: any; + year?: any; + citations?: any; +} + +export function validateArticle(article: ArticleInput): boolean { + if (!article.id || typeof article.id !== 'string') return false; + if (!article.title || typeof article.title !== 'string') return false; + if (article.authors !== undefined && !Array.isArray(article.authors)) + return false; + if (article.year !== undefined) { + if (typeof article.year !== 'number' || article.year < 1900) + return false; + } + if (article.citations !== undefined && !Array.isArray(article.citations)) + return false; + return true; +} From 4fea9b07ca11a4948fa3f38cf1504ba0c4a9b1d4 Mon Sep 17 00:00:00 2001 From: Pellya Date: Mon, 23 Mar 2026 21:35:25 +0300 Subject: [PATCH 2/6] Add console app for MTPO --- .../app/algorithm/algorithms.ts | 120 +++++++++++ .../app/commands/buildGraph.ts | 74 +++++++ .../article-analyzer/app/commands/cmdLoad.ts | 28 +++ .../article-analyzer/app/commands/compare.ts | 108 ++++++++++ .../article-analyzer/app/commands/export.ts | 40 ++++ .../app/commands/launchTest.ts | 77 +++++++ .../article-analyzer/app/commands/rageRank.ts | 101 +++++++++ .../article-analyzer/app/commands/report.ts | 60 ++++++ .../article-analyzer/app/ensureData.ts | 33 +++ .../article-analyzer/app/print/help.ts | 75 +++++++ .../article-analyzer/app/print/menu.ts | 58 ++++++ json-server/article-analyzer/app/state.ts | 7 + json-server/article-analyzer/app/tools.ts | 16 ++ json-server/article-analyzer/main.ts | 191 ++++++++++++++++++ .../article-analyzer/mock/articles.json | 51 +++++ 15 files changed, 1039 insertions(+) create mode 100644 json-server/article-analyzer/app/algorithm/algorithms.ts create mode 100644 json-server/article-analyzer/app/commands/buildGraph.ts create mode 100644 json-server/article-analyzer/app/commands/cmdLoad.ts create mode 100644 json-server/article-analyzer/app/commands/compare.ts create mode 100644 json-server/article-analyzer/app/commands/export.ts create mode 100644 json-server/article-analyzer/app/commands/launchTest.ts create mode 100644 json-server/article-analyzer/app/commands/rageRank.ts create mode 100644 json-server/article-analyzer/app/commands/report.ts create mode 100644 json-server/article-analyzer/app/ensureData.ts create mode 100644 json-server/article-analyzer/app/print/help.ts create mode 100644 json-server/article-analyzer/app/print/menu.ts create mode 100644 json-server/article-analyzer/app/state.ts create mode 100644 json-server/article-analyzer/app/tools.ts create mode 100644 json-server/article-analyzer/main.ts create mode 100644 json-server/article-analyzer/mock/articles.json diff --git a/json-server/article-analyzer/app/algorithm/algorithms.ts b/json-server/article-analyzer/app/algorithm/algorithms.ts new file mode 100644 index 00000000..c622cba9 --- /dev/null +++ b/json-server/article-analyzer/app/algorithm/algorithms.ts @@ -0,0 +1,120 @@ +// АЛГОРИТМЫ (встроены в CLI — не требуют сборки TypeScript) + +import path from 'path'; +import fs from 'fs'; + +export function normalizeArticles(raw: any[]) { + return raw.map((a) => { + if (!a.id) throw new Error('[103] Missing required field: id'); + if (!a.title) throw new Error('[103] Missing required field: title'); + const year = + a.year !== undefined && a.year !== null + ? a.year + : new Date().getFullYear(); + if (typeof year !== 'number' || year < 1900) + throw new Error(`[104] Invalid year: ${year}`); + if (a.citations !== undefined && !Array.isArray(a.citations)) + throw new Error('[104] citations must be an array'); + return { + id: String(a.id), + title: String(a.title), + year, + authors: Array.isArray(a.authors) ? a.authors : [], + citations: Array.isArray(a.citations) ? a.citations : [], + }; + }); +} + +export function loadArticles(filePath: string) { + const abs = path.resolve(filePath); + if (!fs.existsSync(abs)) + throw new Error(`[101] File not found: ${filePath}`); + let raw; + try { + raw = JSON.parse(fs.readFileSync(abs, 'utf8')); + } catch { + throw new Error(`[102] Invalid JSON: ${filePath}`); + } + if (!Array.isArray(raw)) throw new Error('[102] JSON must be an array'); + return normalizeArticles(raw); +} +export function pagerankSparse( + graph: any, + damping: number, + iterations: number, +) { + if (iterations < 1) throw new Error('Iterations must be >= 1'); + if (damping <= 0 || damping >= 1) + throw new Error('Damping must be in (0,1)'); + const { n, outDegree, outLinks } = graph; + let pr = Array(n).fill(1 / n); + for (let k = 0; k < iterations; k += 1) { + const np = Array(n).fill((1 - damping) / n); + for (let v = 0; v < n; v += 1) { + if (outDegree[v] > 0) { + // ветка true + const c = (damping * pr[v]) / outDegree[v]; + // eslint-disable-next-line no-restricted-syntax + for (const j of outLinks[v]) np[j] += c; + } else { + // висячая вершина + const c = (damping * pr[v]) / n; + for (let j = 0; j < n; j += 1) np[j] += c; + } + } + pr = np; + } + return pr; +} + +export function pagerankDense(graph: any, damping: number, iterations: number) { + if (iterations < 1) throw new Error('Iterations must be >= 1'); + if (damping <= 0 || damping >= 1) + throw new Error('Damping must be in (0,1)'); + const { n, matrix } = graph; + const M = Array.from({ length: n }, (_, i) => { + const deg = matrix[i].reduce((s: any, v: any) => s + v, 0); + return Array.from({ length: n }, (_, j) => + deg > 0 ? matrix[i][j] / deg : 1 / n, + ); + }); + let pr = Array(n).fill(1 / n); + for (let k = 0; k < iterations; k += 1) { + const np = Array(n).fill((1 - damping) / n); + for (let j = 0; j < n; j += 1) + for (let i = 0; i < n; i += 1) np[j] += damping * M[i][j] * pr[i]; + pr = np; + } + return pr; +} + +export function buildSparse(articles: any[]) { + const n = articles.length; + const idx = new Map(articles.map((a, i) => [a.id, i])); + const outLinks = Array.from({ length: n }, () => []); + const inLinks = Array.from({ length: n }, () => []); + const outDegree = Array(n).fill(0); + articles.forEach((a, i) => { + (a.citations || []).forEach((cid: any) => { + const j = idx.get(cid); + if (j === undefined) return; // ignoreMissing + outLinks[i].push(j); + inLinks[j].push(i); + outDegree[i] += 1; + }); + }); + return { outLinks, inLinks, outDegree, n }; +} + +export function buildDense(articles: any[]) { + const n = articles.length; + const idx = new Map(articles.map((a, i) => [a.id, i])); + const matrix = Array.from({ length: n }, () => Array(n).fill(0)); + articles.forEach((a, i) => + (a.citations || []).forEach((cid: any) => { + const j = idx.get(cid); + if (j !== undefined) matrix[i][j] = 1; + }), + ); + return { matrix, n }; +} diff --git a/json-server/article-analyzer/app/commands/buildGraph.ts b/json-server/article-analyzer/app/commands/buildGraph.ts new file mode 100644 index 00000000..fb958001 --- /dev/null +++ b/json-server/article-analyzer/app/commands/buildGraph.ts @@ -0,0 +1,74 @@ +import { state } from '../state'; +import { ensureData } from '../ensureData'; +import { BOLD, CYAN, GRAY, GREEN, HR, NL, YELLOW } from '../tools'; + +export function cmdBuildGraph() { + if (!ensureData()) return; + const edges = state.sparse.outLinks.reduce((s, l) => s + l.length, 0); + const dangling = state.sparse.outDegree.filter((d) => d === 0).length; + const avgDeg = (edges / state.sparse.n).toFixed(2); + + NL(); + console.log(HR()); + console.log(BOLD(' Граф цитирования')); + console.log(HR()); + NL(); + + console.log( + GRAY(' Представление 1: ') + + CYAN(BOLD('Плотная матрица')) + + GRAY(' [Способ 1, O(N²)]'), + ); + console.log( + GRAY(' Представление 2: ') + + GREEN(BOLD('Разреженные списки')) + + GRAY(' [Способ 2, O(N+E)]'), + ); + NL(); + console.log(GRAY(' Вершин: ') + BOLD(state.sparse.n)); + console.log(GRAY(' Рёбер: ') + BOLD(edges)); + console.log(GRAY(' Средняя степень: ') + BOLD(avgDeg)); + console.log( + GRAY(' Висячих вершин: ') + + BOLD(dangling) + + GRAY(' (outDegree = 0, равномерное распределение)'), + ); + NL(); + + // Матрица смежности (до 8×8) + const n = Math.min(state.sparse.n, 8); + const labels = state.articles + .slice(0, n) + .map((a) => a.id.slice(0, 5).padEnd(6)); + const header = GRAY(' ') + labels.map((l) => GRAY(l)).join(''); + console.log(GRAY(' Матрица смежности') + GRAY(` (первые ${n}×${n}):`)); + console.log(` ${header}`); + + for (let i = 0; i < n; i += 1) { + const row = Array.from({ length: n }, (_, j) => { + const v = state.dense.matrix[i][j]; + return v ? GREEN(' 1 ') : GRAY(' 0 '); + }).join(''); + console.log(GRAY(` ${labels[i]}`) + row); + } + NL(); + + // Списки смежности + console.log(GRAY(' Списки смежности (out[v]):')); + state.articles.slice(0, 10).forEach((a, i) => { + const neighbors = + state.sparse.outLinks[i] + .map((j) => CYAN(state.articles[j].id)) + .join(', ') || GRAY('—'); + const deg = state.sparse.outDegree[i]; + console.log( + GRAY(' ') + + BOLD(a.id.padEnd(8)) + + GRAY('→ [') + + neighbors + + GRAY(']') + + GRAY(` deg=${deg}`) + + (deg === 0 ? YELLOW(' ← висячая') : ''), + ); + }); +} diff --git a/json-server/article-analyzer/app/commands/cmdLoad.ts b/json-server/article-analyzer/app/commands/cmdLoad.ts new file mode 100644 index 00000000..ed76752c --- /dev/null +++ b/json-server/article-analyzer/app/commands/cmdLoad.ts @@ -0,0 +1,28 @@ +import { buildDense, buildSparse, loadArticles } from '../algorithm/algorithms'; +import { state } from '../state'; +import { BOLD, CYAN, GRAY, GREEN } from '../tools'; + +export function cmdLoad(filePath: string, silent = false) { + if (!silent) console.log(GRAY(' Загрузка: ') + CYAN(filePath)); + state.articles = loadArticles(filePath); + state.sparse = buildSparse(state.articles); + state.dense = buildDense(state.articles); + state.loadedFile = filePath; + const edges = state.sparse.outLinks.reduce((s, l) => s + l.length, 0); + if (!silent) { + console.log( + GREEN(' ✓ Загружено статей : ') + BOLD(state.articles.length), + ); + console.log(GREEN(' ✓ Вершин в графе : ') + BOLD(state.sparse.n)); + console.log(GREEN(' ✓ Рёбер (ссылок) : ') + BOLD(edges)); + } else { + console.log( + GREEN(' ✓ ') + + GRAY('Загружено ') + + BOLD(state.articles.length) + + GRAY(' статей, ') + + BOLD(edges) + + GRAY(' ссылок'), + ); + } +} diff --git a/json-server/article-analyzer/app/commands/compare.ts b/json-server/article-analyzer/app/commands/compare.ts new file mode 100644 index 00000000..8f712016 --- /dev/null +++ b/json-server/article-analyzer/app/commands/compare.ts @@ -0,0 +1,108 @@ +import { BOLD, CYAN, GRAY, GREEN, HR, NL, YELLOW } from '../tools'; +import { pagerankDense, pagerankSparse } from '../algorithm/algorithms'; +import { ensureData } from '../ensureData'; +import { state } from '../state'; + +export function cmdCompare(iter: number, damping: number) { + if (!ensureData()) return; + NL(); + console.log(HR('═')); + console.log(BOLD(' Сравнение производительности алгоритмов PageRank')); + console.log(HR('═')); + console.log( + GRAY(' iterations=') + BOLD(iter) + GRAY(' damping=') + BOLD(damping), + ); + NL(); + + // Прогоняем каждый метод по 3 раза, берём среднее + const runs = 3; + let sumDense = 0; + let sumSparse = 0; + let prDense: any[]; + let prSparse: any[]; + for (let r = 0; r < runs; r += 1) { + let t = Date.now(); + prDense = pagerankDense(state.dense, damping, iter); + sumDense += Date.now() - t; + t = Date.now(); + prSparse = pagerankSparse(state.sparse, damping, iter); + sumSparse += Date.now() - t; + } + const tDense = (sumDense / runs).toFixed(2); + const tSparse = (sumSparse / runs).toFixed(2); + + // Проверяем совпадение + let maxDiff = 0; + for (let i = 0; i < state.sparse.n; i += 1) + maxDiff = Math.max(maxDiff, Math.abs(prDense[i] - prSparse[i])); + + const COL = 28; + const row = (label: string, v1: string | number, v2: string | number) => + console.log( + GRAY(` ${label.padEnd(26)}`) + + CYAN(String(v1).padEnd(COL)) + + GREEN(String(v2)), + ); + + console.log( + GRAY(` ${''.padEnd(26)}`) + + CYAN(BOLD('Способ 1: Матрица'.padEnd(COL))) + + GREEN(BOLD('Способ 2: Спис. смежности')), + ); + console.log(GRAY(` ${'─'.repeat(72)}`)); + row('Структура', 'Плотная матрица N×N', 'Списки смежности'); + row('Память', 'O(N²)', 'O(N + E)'); + row('Итерация', 'O(N²)', 'O(N + E)'); + row('N (вершин)', state.sparse.n, state.sparse.n); + row( + 'E (рёбер)', + state.sparse.outLinks.reduce( + (s: any, l: string | any[]) => s + l.length, + 0, + ), + state.sparse.outLinks.reduce( + (s: any, l: string | any[]) => s + l.length, + 0, + ), + ); + row('Итераций', iter, iter); + row(`Время, мс (avg ${runs} runs)`, `${tDense} мс`, `${tSparse} мс`); + NL(); + if (maxDiff < 1e-9) { + console.log(GREEN(' ✓ Результаты идентичны (|diff| < 1e-9)')); + } else { + console.log( + YELLOW(` ≈ Максимальное отклонение: ${maxDiff.toExponential(3)}`), + ); + } + + // Топ по обоим методам рядом + NL(); + console.log(HR()); + console.log(BOLD(' Ранжирование статей (оба метода):')); + NL(); + const rD = state.articles + .map((a: any, i: string | number) => ({ ...a, rank: prDense[i] })) + .sort((a: { rank: number }, b: { rank: number }) => b.rank - a.rank); + const rS = state.articles + .map((a: any, i: string | number) => ({ ...a, rank: prSparse[i] })) + .sort((a: { rank: number }, b: { rank: number }) => b.rank - a.rank); + const topN = Math.min(7, state.articles.length); + console.log( + GRAY(' # ') + + CYAN(BOLD('Матрица ')) + + GREEN(BOLD('Разреженные списки')), + ); + console.log(GRAY(` ${'─'.repeat(72)}`)); + for (let i = 0; i < topN; i += 1) { + console.log( + GRAY(` ${String(i + 1).padEnd(4)}`) + + CYAN( + `${rD[i].title.slice(0, 30)} ${rD[i].rank.toFixed( + 6, + )}`.padEnd(40), + ) + + GREEN(`${rS[i].title.slice(0, 30)} ${rS[i].rank.toFixed(6)}`), + ); + } +} diff --git a/json-server/article-analyzer/app/commands/export.ts b/json-server/article-analyzer/app/commands/export.ts new file mode 100644 index 00000000..b0a03a95 --- /dev/null +++ b/json-server/article-analyzer/app/commands/export.ts @@ -0,0 +1,40 @@ +import fs from 'fs'; +import { pagerankSparse } from '../algorithm/algorithms.ts'; +import { ensureData } from '../ensureData'; +import { BOLD, CYAN, GRAY, GREEN } from '../tools'; +import { state } from '../state.ts'; + +export function cmdExport(outFile: string, iter: number, damping: number) { + if (!ensureData()) return; + const pr = pagerankSparse(state.sparse, damping, iter); + + if (!state.sparse || !state.articles) return; + + const edges = state.sparse.outLinks.reduce((s, l) => s + l.length, 0); + const result = { + metadata: { + timestamp: new Date().toISOString(), + source: state.loadedFile || 'demo', + articles_count: state.articles.length, + edges_count: edges, + avg_degree: parseFloat((edges / state.sparse.n).toFixed(4)), + iterations: iter, + damping, + }, + pagerank: state.articles + .map((a, i) => ({ + article_id: a.id, + title: a.title, + year: a.year, + rank: pr[i], + })) + .sort((a, b) => b.rank - a.rank), + }; + try { + fs.writeFileSync(outFile, JSON.stringify(result, null, 2), 'utf8'); + console.log(GREEN(' ✓ Результаты экспортированы: ') + CYAN(outFile)); + console.log(GRAY(' Статей в отчёте: ') + BOLD(result.pagerank.length)); + } catch (e: any) { + throw new Error(`[108] Ошибка записи в файл: ${e.message}`); + } +} diff --git a/json-server/article-analyzer/app/commands/launchTest.ts b/json-server/article-analyzer/app/commands/launchTest.ts new file mode 100644 index 00000000..0fad976b --- /dev/null +++ b/json-server/article-analyzer/app/commands/launchTest.ts @@ -0,0 +1,77 @@ +/* eslint-disable no-console */ +import fs from 'fs'; +import path from 'path'; +import { spawnSync } from 'child_process'; +import { BOLD, CYAN, GRAY, GREEN, HR, NL, RED } from '../tools'; + +const ROOT = path.join(__dirname, '../../../../'); +// const ROOT = path.join(__dirname); + +export function cmdTest(group: string, verbose: boolean) { + const jestBin = path.join(ROOT, 'node_modules', '.bin', 'jest'); + const jestOk = fs.existsSync(jestBin); + console.log('jestBin', jestBin); + console.log('jestOk', jestOk); + + NL(); + console.log(HR('═')); + console.log(BOLD(CYAN(' МОДУЛЬНОЕ ТЕСТИРОВАНИЕ · Jest + ts-jest'))); + console.log( + GRAY(' Дисциплина: Методы тестирования программного обеспечения'), + ); + console.log(HR('═')); + NL(); + + if (jestOk) { + const jestArgs = ['--colors', '--verbose']; + if (!verbose) jestArgs.push('--silent'); // убираем лишний шум + if (group !== 'all') { + // Фильтруем по файлу/группе{ + const fileMap = { + equiv: 'loader.test.ts|validator.test.ts', + boundary: 'pagerank.test.ts|loader.test.ts', + branch: 'graph.test.ts|pagerank.test.ts', + condition: 'validator.test.ts', + }; + if (fileMap[group as keyof typeof fileMap]) { + jestArgs.push( + '--testPathPattern', + fileMap[group as keyof typeof fileMap], + ); + } + } + + NL(); + + const result = spawnSync( + jestBin, + [ + '--colors', + '--verbose', + ...(group !== 'all' + ? [ + '--testPathPattern', + { + equiv: 'loader|validator', + boundary: 'pagerank|loader', + branch: 'graph|pagerank', + condition: 'validator', + }[group] || '', + ] + : ['--testPathPattern', '__tests__']), + ], + { + cwd: ROOT, + stdio: 'inherit', + shell: process.platform === 'win32', + }, + ); + + NL(); + if (result.status === 0) { + console.log(GREEN(BOLD(' ✓ All tests passed'))); + } else { + console.log(RED(BOLD(' ✗ Some tests failed'))); + } + } +} diff --git a/json-server/article-analyzer/app/commands/rageRank.ts b/json-server/article-analyzer/app/commands/rageRank.ts new file mode 100644 index 00000000..3303f31e --- /dev/null +++ b/json-server/article-analyzer/app/commands/rageRank.ts @@ -0,0 +1,101 @@ +import { BOLD, CYAN, DIM, GRAY, GREEN, HR, NL, WHITE, YELLOW } from '../tools'; +import { pagerankDense, pagerankSparse } from '../algorithm/algorithms'; +import { ensureData } from '../ensureData'; +import { state } from '../state'; + +export function cmdPageRank(method: string, iter: number, damping: number) { + if (!ensureData()) return; + const useSparse = method !== 'matrix'; + + NL(); + console.log(HR()); + console.log( + `${BOLD(' PageRank')} · Метод: ${ + useSparse + ? GREEN(BOLD('Разреженные списки [Способ 2]')) + : CYAN(BOLD('Плотная матрица [Способ 1]')) + }`, + ); + console.log(HR()); + console.log( + GRAY(' Формула: ') + + WHITE('PR = d·M·PR + (1−d)/N·1') + + GRAY(' iterations=') + + BOLD(iter) + + GRAY(' damping=') + + BOLD(damping), + ); + NL(); + + const t0 = Date.now(); + const pr = useSparse + ? pagerankSparse(state.sparse, damping, iter) + : pagerankDense(state.dense, damping, iter); + const elapsed = Date.now() - t0; + + if (!state.articles) { + console.log('Нет статей'); + return; + } + + const ranked = state.articles + .map((a: any, i: string | number) => ({ ...a, rank: pr[i] })) + .sort((a: { rank: number }, b: { rank: number }) => b.rank - a.rank); + const maxR = ranked[0].rank; + + const topN = Math.min(10, ranked.length); + console.log(BOLD(` Топ-${topN} статей по PageRank:`)); + NL(); + + ranked.slice(0, topN).forEach( + ( + a: { + rank: number; + title: string; + year: { toString: () => string }; + id: any; + }, + i: number, + ) => { + const bar = Math.round((a.rank / maxR) * 28); + const filled = (useSparse ? GREEN : CYAN)('█'.repeat(bar)); + const empty = GRAY('░'.repeat(28 - bar)); + const num = String(i + 1).padStart(2); + const medal = + // eslint-disable-next-line no-nested-ternary + i === 0 ? YELLOW(' ★') : i < 3 ? GRAY(' ·') : ' '; + console.log( + `${GRAY(` ${num}.`) + medal} ${BOLD( + a.title.slice(0, 44).padEnd(45), + )}${GRAY(' rank: ')}${GREEN(a.rank.toFixed(6))}`, + ); + console.log( + GRAY(' ') + + filled + + empty + + GRAY(' ') + + DIM(a.year.toString()) + + GRAY(' out: ') + + DIM( + String( + state.sparse.outDegree[ + state.articles.findIndex( + (x: { id: any }) => x.id === a.id, + ) + ], + ), + ), + ); + }, + ); + NL(); + console.log(GRAY(' Время: ') + YELLOW(`${elapsed} мс`)); + console.log( + GRAY(' Сложность памяти: ') + + (useSparse ? GREEN('O(N + E)') : CYAN('O(N²)')), + ); + console.log( + GRAY(' Сложность итерации: ') + + (useSparse ? GREEN('O(N + E)') : CYAN('O(N²)')), + ); +} diff --git a/json-server/article-analyzer/app/commands/report.ts b/json-server/article-analyzer/app/commands/report.ts new file mode 100644 index 00000000..8df53c00 --- /dev/null +++ b/json-server/article-analyzer/app/commands/report.ts @@ -0,0 +1,60 @@ +import { pagerankSparse } from '../algorithm/algorithms'; +import { ensureData } from '../ensureData'; +import { state } from '../state'; +import { BOLD, CYAN, GRAY, GREEN, HR, NL, YELLOW } from '../tools'; + +export function cmdReport() { + if (!ensureData()) return; + const pr = pagerankSparse(state.sparse, 0.85, 20); + + if (!state.sparse) { + console.log('Ошибка с отчетом'); + return; + } + + console.log('outLinks', state.sparse.outLinks); + + const edges = state.sparse.outLinks.reduce( + (s: any, l: string | any[]) => s + l.length, + 0, + ); + const dangling = state.sparse.outDegree.filter( + (d: number) => d === 0, + ).length; + + NL(); + console.log(HR('═')); + console.log(BOLD(CYAN(' === Анализ графа цитирования ==='))); + console.log(HR('═')); + NL(); + console.log( + GRAY(' Источник данных: ') + CYAN(state.loadedFile || 'demo'), + ); + console.log(GRAY(' Всего статей: ') + BOLD(state.articles.length)); + console.log(GRAY(' Всего цитирований: ') + BOLD(edges)); + console.log( + GRAY(' Средняя степень: ') + + BOLD((edges / state.sparse.n).toFixed(2)), + ); + console.log(GRAY(' Висячих вершин: ') + BOLD(dangling)); + NL(); + + const ranked = state.articles + .map((a: any, i: string | number) => ({ ...a, rank: pr[i] })) + .sort((a: { rank: number }, b: { rank: number }) => b.rank - a.rank); + console.log(BOLD(' Топ статей по PageRank (метод: разреженные списки):')); + NL(); + ranked.forEach((a: { title: string | any[]; rank: number }, i: number) => { + // eslint-disable-next-line no-nested-ternary + const medal = i === 0 ? YELLOW('★') : i < 3 ? GRAY('·') : GRAY(' '); + console.log( + GRAY(' ') + + medal + + GRAY(` ${i + 1}.`.padEnd(5)) + + BOLD(`"${a.title.slice(0, 52)}"`) + + GRAY(' (rank: ') + + GREEN(a.rank.toFixed(6)) + + GRAY(')'), + ); + }); +} diff --git a/json-server/article-analyzer/app/ensureData.ts b/json-server/article-analyzer/app/ensureData.ts new file mode 100644 index 00000000..0849baf3 --- /dev/null +++ b/json-server/article-analyzer/app/ensureData.ts @@ -0,0 +1,33 @@ +/* eslint-disable no-console */ +import path from 'path'; +import fs from 'fs'; +import { state } from './state'; +import { CYAN, GRAY, YELLOW } from './tools'; +import { cmdLoad } from './commands/cmdLoad'; + +// const ROOT = path.join(__dirname, '../../../'); +// const demo = path.join( +// ROOT, +// 'json-server', +// 'article-analyzer', +// 'mock', +// 'articles.json', +// ); + +export function ensureData() { + if (state.articles) return true; + const demo = path.join(__dirname, '../mock/articles.json'); + + if (fs.existsSync(demo)) { + console.log( + GRAY(' → Данные не загружены, используются demo: ') + + CYAN('../mock/articles.json'), + ); + cmdLoad(demo, true); + return true; + } + console.log( + YELLOW(' ⚠ Сначала загрузите данные: ') + CYAN('load '), + ); + return false; +} diff --git a/json-server/article-analyzer/app/print/help.ts b/json-server/article-analyzer/app/print/help.ts new file mode 100644 index 00000000..230b76c1 --- /dev/null +++ b/json-server/article-analyzer/app/print/help.ts @@ -0,0 +1,75 @@ +/* eslint-disable no-console */ +import { BOLD, CYAN, DIM, GRAY, GREEN, HR, NL, WHITE, YELLOW } from '../tools'; + +// ШАПКА / СПРАВКА + +export function printBanner() { + NL(); + console.log(HR('═')); + console.log( + ` ${BOLD(CYAN('article-analyzer'))}${GRAY(' v1.0.0')} ${WHITE( + '·', + )} ${GRAY(`Node.js ${process.version}`)}`, + ); + console.log( + ` ${GRAY( + 'Анализ графа цитирования IT-статей · ', + )}${DIM('Пелля Р.Ю.')}`, + ); + console.log(HR('═')); +} + +export function printHelp() { + printBanner(); + console.log(`${BOLD('Usage:')} article-analyzer [options] `); + NL(); + + console.log(BOLD('Commands:')); + [ + [' load ', 'Загрузить статьи из JSON-файла'], + [' build-graph', 'Построить граф цитирования'], + [ + ' pagerank [method]', + `Рассчитать PageRank ${GRAY('(method: sparse | matrix)')}`, + ], + [ + ' cluster [method]', + `Найти сообщества ${GRAY('(louvain | kmeans)')}`, + ], + [' compare-pagerank', 'Сравнить производительность двух методов'], + [' export ', 'Экспортировать результаты в JSON'], + [' report', 'Вывести итоговый отчёт в консоль'], + [ + ' test [group]', + `Запустить модульные тесты (Jest) ${GRAY( + '(group: all|equiv|boundary|branch|condition)', + )}`, + ], + ].forEach(([cmd, desc]) => console.log(CYAN(cmd.padEnd(30)) + desc)); + NL(); + + console.log(BOLD('Options:')); + [ + ['-h, --help', 'Показать справку'], + ['-v, --version', 'Показать версию'], + ['--verbose', 'Подробный вывод'], + ['--iter ', `Количество итераций ${GRAY('(по умолч. 20)')}`], + ['--damping ', `Коэффициент затухания ${GRAY('(по умолч. 0.85)')}`], + ].forEach(([opt, desc]) => + console.log(YELLOW(` ${opt}`.padEnd(30)) + desc), + ); + NL(); + + console.log(BOLD('Examples:')); + [ + 'article-analyzer load data/articles.json', + 'article-analyzer pagerank sparse --iter 30', + 'article-analyzer pagerank matrix --damping 0.9', + 'article-analyzer compare-pagerank', + 'article-analyzer test all', + 'article-analyzer test boundary', + 'article-analyzer export results.json', + 'article-analyzer report', + ].forEach((e) => console.log(GRAY(' $ ') + GREEN(e))); + NL(); +} diff --git a/json-server/article-analyzer/app/print/menu.ts b/json-server/article-analyzer/app/print/menu.ts new file mode 100644 index 00000000..68c77fd8 --- /dev/null +++ b/json-server/article-analyzer/app/print/menu.ts @@ -0,0 +1,58 @@ +/* eslint-disable no-console */ +import { BOLD, CYAN, GRAY, HR, NL, RED } from '../tools'; + +export const MENU_ITEMS = [ + { key: '1', label: 'Загрузить статьи из файла', action: 'load' }, + { + key: '2', + label: 'Построить граф цитирования', + action: 'build-graph', + }, + { + key: '3', + label: 'PageRank — разреженные списки [Способ 2]', + action: 'pr-sparse', + }, + { + key: '4', + label: 'PageRank — плотная матрица [Способ 1]', + action: 'pr-matrix', + }, + { + key: '5', + label: 'Сравнить производительность методов', + action: 'compare', + }, + { key: '6', label: 'Вывести отчёт', action: 'report' }, + { + key: '7', + label: 'Экспортировать результаты в JSON', + action: 'export', + }, + { key: '8', label: 'Тесты — все группы', action: 'test-all' }, + { + key: '9', + label: 'Тесты — классы эквивалентности', + action: 'test-equiv', + }, + { key: '0', label: 'Тесты — граничные значения', action: 'test-bnd' }, + { key: 'b', label: 'Тесты — ветвления', action: 'test-branch' }, + { key: 'c', label: 'Тесты — условия', action: 'test-cond' }, + { key: 'h', label: 'Справка (--help)', action: 'help' }, + { key: 'q', label: 'Выход', action: 'quit' }, +]; + +export function printMenu() { + NL(); + console.log(HR('─')); + console.log( + BOLD(' Интерактивное меню') + + GRAY(' · введите цифру и нажмите Enter'), + ); + console.log(HR('─')); + MENU_ITEMS.forEach((item) => { + const actions = item.action === 'quit' ? RED(item.key) : CYAN(item.key); + console.log(` ${BOLD(`[${actions}]`)} ${item.label}`); + }); + console.log(HR('─')); +} diff --git a/json-server/article-analyzer/app/state.ts b/json-server/article-analyzer/app/state.ts new file mode 100644 index 00000000..e8fcdf59 --- /dev/null +++ b/json-server/article-analyzer/app/state.ts @@ -0,0 +1,7 @@ +// СОСТОЯНИЕ СЕССИИ +export const state = { + articles: null, + sparse: null, + dense: null, + loadedFile: null, +}; diff --git a/json-server/article-analyzer/app/tools.ts b/json-server/article-analyzer/app/tools.ts new file mode 100644 index 00000000..7638ad28 --- /dev/null +++ b/json-server/article-analyzer/app/tools.ts @@ -0,0 +1,16 @@ +/* eslint-disable no-console */ +// ANSI-ЦВЕТА (без внешних зависимостей) +export const R = '\x1b[0m'; +export const BOLD = (s: string | number) => `\x1b[1m${s}${R}`; +export const DIM = (s: string) => `\x1b[2m${s}${R}`; +export const RED = (s: string) => `\x1b[31m${s}${R}`; +export const GREEN = (s: string) => `\x1b[32m${s}${R}`; +export const YELLOW = (s: string) => `\x1b[33m${s}${R}`; +export const BLUE = (s: string) => `\x1b[34m${s}${R}`; +export const MAGENTA = (s: string) => `\x1b[35m${s}${R}`; +export const CYAN = (s: string) => `\x1b[36m${s}${R}`; +export const GRAY = (s: string) => `\x1b[90m${s}${R}`; +export const WHITE = (s: string) => `\x1b[37m${s}${R}`; + +export const HR = (ch = '─', n = 74) => GRAY(ch.repeat(n)); +export const NL = () => console.log(''); diff --git a/json-server/article-analyzer/main.ts b/json-server/article-analyzer/main.ts new file mode 100644 index 00000000..aa6286de --- /dev/null +++ b/json-server/article-analyzer/main.ts @@ -0,0 +1,191 @@ +#!/usr/bin/env node +/* eslint-disable no-console */ + +/** + * article-analyzer — консольное приложение для анализа графа цитирования IT-статей. + * Пелля Р.Ю. + * + * Требования: + * - Node.js v22.22.1 + * + * Запуск: + * npx tsx json-server/article-analyzer/main.ts <- интерактивное меню + * npx tsx json-server/article-analyzer/main.ts [command] [options] + */ + +import path from 'path'; +import readline from 'readline'; +import { cmdBuildGraph } from './app/commands/buildGraph'; +import { cmdLoad } from './app/commands/cmdLoad'; +import { cmdCompare } from './app/commands/compare'; +import { cmdExport } from './app/commands/export'; +import { cmdTest } from './app/commands/launchTest'; +import { cmdPageRank } from './app/commands/rageRank'; +import { cmdReport } from './app/commands/report'; +import { printBanner, printHelp } from './app/print/help'; +import { MENU_ITEMS, printMenu } from './app/print/menu'; +import { BOLD, CYAN, GRAY, RED, YELLOW } from './app/tools'; + +const ROOT = path.join(__dirname, '../..'); + +// ИНТЕРАКТИВНОЕ МЕНЮ (readline, без зависимостей) + +(function main() { + async function runMenu(iter: number, damping: number) { + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + const ask = (q: string) => + new Promise((res) => { + rl.question(q, res); + }); + + printBanner(); + printMenu(); + + const loop = async () => { + const answer: string = String(await ask(GRAY('\n > '))); + const item = MENU_ITEMS.find((m) => m.key === answer); + + if (!item) { + console.log( + YELLOW(' Неизвестная команда: ') + + answer + + GRAY(' (введите h для справки)'), + ); + return loop(); + } + + try { + if (item.action === 'load') { + const fp = + String( + await ask( + GRAY( + ' Путь к JSON-файлу [data/articles.json]: ', + ), + ), + ) || path.join(ROOT, 'data', 'articles.json'); + cmdLoad(fp); + } + if (item.action === 'build-graph') { + cmdBuildGraph(); + } + if (item.action === 'pr-sparse') { + cmdPageRank('sparse', iter, damping); + } + if (item.action === 'pr-matrix') { + cmdPageRank('matrix', iter, damping); + } + if (item.action === 'compare') { + cmdCompare(iter, damping); + } + if (item.action === 'report') { + cmdReport(); + } + if (item.action === 'export') { + const fp: string = + String( + await ask(GRAY(' Имя файла [results.json]: ')), + ) || 'results.json'; + cmdExport(fp, iter, damping); + } + if (item.action === 'test-all') { + cmdTest('all', false); + } + if (item.action === 'test-equiv') { + cmdTest('equiv', false); + } + if (item.action === 'test-bnd') { + cmdTest('boundary', false); + } + if (item.action === 'test-branch') { + cmdTest('branch', false); + } + if (item.action === 'test-cond') { + cmdTest('condition', false); + } + if (item.action === 'help') { + printHelp(); + } + if (item.action === 'quit') { + console.log(GRAY('\n До свидания!\n')); + return rl.close(); + } + } catch (e: any) { + console.log(RED(' Ошибка: ') + e.message); + } + + printMenu(); + return loop(); + }; + + await loop(); + } + + // ТОЧКА ВХОДА — парсинг аргументов + + const argv = process.argv.slice(2); + const getOpt = (name: string, def: string) => { + const i = argv.indexOf(name); + return i !== -1 && argv[i + 1] ? argv[i + 1] : def; + }; + const hasFlag = (name: string) => argv.includes(name); + + const iter: number = parseInt(getOpt('--iter', '20'), 10); + const damping: number = parseFloat(getOpt('--damping', '0.85')); + const verbose: boolean = hasFlag('--verbose') || hasFlag('-v'); + + const cmd = argv.find((a) => !a.startsWith('-')); + const rest: string[] = argv.filter((a) => !a.startsWith('-') && a !== cmd); + + if (!cmd) { + runMenu(iter, damping).catch((e) => { + console.error(e); + process.exit(1); + }); + return; + } + + // С аргументами -> прямой вызов команды + printBanner(); + try { + if (cmd === 'help') { + printHelp(); + } else if (cmd === 'version') { + console.log(BOLD(' article-analyzer ') + CYAN('v1.0.0')); + } else if (cmd === 'load') { + if (!rest[0]) { + console.log(RED(' Укажите файл')); + process.exit(1); + } + cmdLoad(String(rest[0])); + } else if (cmd === 'build-graph') { + cmdBuildGraph(); + } else if (cmd === 'pagerank') { + cmdPageRank(rest[0] || 'sparse', iter, damping); + } else if (cmd === 'compare-pagerank') { + cmdCompare(iter, damping); + } else if (cmd === 'report') { + cmdReport(); + } else if (cmd === 'export') { + if (!rest[0]) { + console.log(RED(' Укажите имя выходного файла')); + process.exit(1); + } + cmdExport(String(rest[0]), iter, damping); + } else if (cmd === 'test') { + cmdTest(rest[0] || 'all', verbose); + } else { + console.log(RED(' [105] Неизвестная команда: ') + BOLD(cmd || '')); + console.log(GRAY(' Используйте help для справки')); + process.exit(1); + } + } catch (e: any) { + console.log(RED(' Ошибка: ') + e.message); + if (verbose) console.error(e.stack); + process.exit(1); + } +})(); diff --git a/json-server/article-analyzer/mock/articles.json b/json-server/article-analyzer/mock/articles.json new file mode 100644 index 00000000..f7248f4e --- /dev/null +++ b/json-server/article-analyzer/mock/articles.json @@ -0,0 +1,51 @@ +[ + { + "id": "a001", + "title": "Attention is All You Need", + "authors": ["Vaswani", "Shazeer", "Parmar"], + "year": 2017, + "citations": ["a002", "a003"] + }, + { + "id": "a002", + "title": "BERT: Pre-training of Deep Bidirectional Transformers", + "authors": ["Devlin", "Chang", "Lee"], + "year": 2018, + "citations": ["a001", "a003"] + }, + { + "id": "a003", + "title": "GPT-3: Language Models are Few-Shot Learners", + "authors": ["Brown", "Mann", "Ryder"], + "year": 2020, + "citations": ["a001"] + }, + { + "id": "a004", + "title": "Deep Residual Learning for Image Recognition", + "authors": ["He", "Zhang", "Ren"], + "year": 2016, + "citations": ["a005"] + }, + { + "id": "a005", + "title": "Very Deep Convolutional Networks (VGGNet)", + "authors": ["Simonyan", "Zisserman"], + "year": 2014, + "citations": [] + }, + { + "id": "a006", + "title": "Transformer-XL: Attentive Language Models", + "authors": ["Dai", "Yang"], + "year": 2019, + "citations": ["a001", "a002"] + }, + { + "id": "a007", + "title": "RoBERTa: A Robustly Optimized BERT Approach", + "authors": ["Liu", "Ott"], + "year": 2019, + "citations": ["a002", "a003", "a006"] + } +] From 08cd2634da56c6a0311db9b94928e0f54b2162c8 Mon Sep 17 00:00:00 2001 From: Pellya Date: Tue, 24 Mar 2026 22:33:49 +0300 Subject: [PATCH 3/6] Some fix for Rage ranks --- .../app/algorithm/algorithms.ts | 38 ---------------- .../article-analyzer/app/commands/cmdLoad.ts | 7 +-- json-server/article-analyzer/loader.ts | 44 +++++++++++++++---- 3 files changed, 39 insertions(+), 50 deletions(-) diff --git a/json-server/article-analyzer/app/algorithm/algorithms.ts b/json-server/article-analyzer/app/algorithm/algorithms.ts index c622cba9..7deba0fe 100644 --- a/json-server/article-analyzer/app/algorithm/algorithms.ts +++ b/json-server/article-analyzer/app/algorithm/algorithms.ts @@ -1,43 +1,5 @@ // АЛГОРИТМЫ (встроены в CLI — не требуют сборки TypeScript) -import path from 'path'; -import fs from 'fs'; - -export function normalizeArticles(raw: any[]) { - return raw.map((a) => { - if (!a.id) throw new Error('[103] Missing required field: id'); - if (!a.title) throw new Error('[103] Missing required field: title'); - const year = - a.year !== undefined && a.year !== null - ? a.year - : new Date().getFullYear(); - if (typeof year !== 'number' || year < 1900) - throw new Error(`[104] Invalid year: ${year}`); - if (a.citations !== undefined && !Array.isArray(a.citations)) - throw new Error('[104] citations must be an array'); - return { - id: String(a.id), - title: String(a.title), - year, - authors: Array.isArray(a.authors) ? a.authors : [], - citations: Array.isArray(a.citations) ? a.citations : [], - }; - }); -} - -export function loadArticles(filePath: string) { - const abs = path.resolve(filePath); - if (!fs.existsSync(abs)) - throw new Error(`[101] File not found: ${filePath}`); - let raw; - try { - raw = JSON.parse(fs.readFileSync(abs, 'utf8')); - } catch { - throw new Error(`[102] Invalid JSON: ${filePath}`); - } - if (!Array.isArray(raw)) throw new Error('[102] JSON must be an array'); - return normalizeArticles(raw); -} export function pagerankSparse( graph: any, damping: number, diff --git a/json-server/article-analyzer/app/commands/cmdLoad.ts b/json-server/article-analyzer/app/commands/cmdLoad.ts index ed76752c..07411151 100644 --- a/json-server/article-analyzer/app/commands/cmdLoad.ts +++ b/json-server/article-analyzer/app/commands/cmdLoad.ts @@ -1,10 +1,11 @@ -import { buildDense, buildSparse, loadArticles } from '../algorithm/algorithms'; +import { loadArticlesFromFile } from '../../loader'; +import { buildDense, buildSparse } from '../algorithm/algorithms'; import { state } from '../state'; import { BOLD, CYAN, GRAY, GREEN } from '../tools'; -export function cmdLoad(filePath: string, silent = false) { +export async function cmdLoad(filePath: string, silent = false) { if (!silent) console.log(GRAY(' Загрузка: ') + CYAN(filePath)); - state.articles = loadArticles(filePath); + state.articles = await loadArticlesFromFile(filePath, true); state.sparse = buildSparse(state.articles); state.dense = buildDense(state.articles); state.loadedFile = filePath; diff --git a/json-server/article-analyzer/loader.ts b/json-server/article-analyzer/loader.ts index b7e9556d..dfe1e572 100644 --- a/json-server/article-analyzer/loader.ts +++ b/json-server/article-analyzer/loader.ts @@ -1,6 +1,7 @@ /* eslint-disable no-restricted-syntax */ /* eslint-disable no-use-before-define */ -import { createReadStream } from 'fs'; +import fs, { createReadStream } from 'fs'; +import path from 'path'; import { createInterface } from 'readline'; import { Article, RawArticle } from './types'; @@ -11,7 +12,22 @@ import { Article, RawArticle } from './types'; */ export async function loadArticlesFromFile( filePath: string, + isLoad: boolean = false, ): Promise { + if (isLoad) { + const abs = path.resolve(filePath); + if (!fs.existsSync(abs)) + throw new Error(`[101] File not found: ${filePath}`); + let raw; + try { + raw = JSON.parse(fs.readFileSync(abs, 'utf8')); + } catch { + throw new Error(`[102] Invalid JSON: ${filePath}`); + } + if (!Array.isArray(raw)) throw new Error('[102] JSON must be an array'); + return normalizeArticles(raw); + } + const stream = createReadStream(filePath, { encoding: 'utf8' }); const rl = createInterface({ input: stream, crlfDelay: Infinity }); @@ -40,19 +56,29 @@ export async function loadArticlesFromFile( /** * Нормализует сырые данные статей к единому формату. */ -export function normalizeArticles(rawArticles: RawArticle[]): Article[] { +export async function normalizeArticles( + rawArticles: RawArticle[], +): Promise { return rawArticles.map((raw) => { - if (!raw.id) throw new Error('Missing required field: id'); - if (!raw.title) throw new Error('Missing required field: title'); + if (!raw.id) throw new Error('[103] Missing required field: id'); + if (!raw.title) throw new Error('[103] Missing required field: title'); if (raw.year && (typeof raw.year !== 'number' || raw.year < 1900)) { - throw new Error('Invalid year'); + throw new Error('[103] Invalid year'); } + const year = + raw.year !== undefined && raw.year !== null + ? raw.year + : new Date().getFullYear(); + if (typeof year !== 'number' || year < 1900) + throw new Error(`[104] Invalid year: ${year}`); + if (raw.citations !== undefined && !Array.isArray(raw.citations)) + throw new Error('[104] citations must be an array'); return { id: String(raw.id), - title: raw.title, - authors: raw.authors || [], - year: raw.year || new Date().getFullYear(), - citations: raw.citations || raw.references || [], + title: String(raw.title), + year, + authors: Array.isArray(raw.authors) ? raw.authors : [], + citations: Array.isArray(raw.citations) ? raw.citations : [], }; }); } From b7355d138fbf3ca8aabe18f48b16a5f609921085 Mon Sep 17 00:00:00 2001 From: Pellya Roman Date: Thu, 26 Mar 2026 10:41:37 +0300 Subject: [PATCH 4/6] Some fix and move to owner folder and some improve for cmd app --- .../{ => app}/__tests__/graph.test.ts | 10 +-- .../{ => app}/__tests__/loader.test.ts | 2 +- .../{ => app}/__tests__/pagerank.test.ts | 25 +++--- .../{ => app}/__tests__/validator.test.ts | 2 +- .../app/algorithm/algorithms.ts | 82 ------------------ .../article-analyzer/app/algorithm/graph.ts | 44 ++++++++++ .../app/algorithm/pagerank.ts | 68 +++++++++++++++ .../{ => app/algorithm}/validator.ts | 14 ++- .../app/commands/buildGraph.ts | 24 +++++- .../article-analyzer/app/commands/cmdLoad.ts | 7 +- .../article-analyzer/app/commands/compare.ts | 41 +++++++-- .../article-analyzer/app/commands/export.ts | 11 ++- .../app/commands/launchTest.ts | 2 - .../{ => app/commands}/loader.ts | 65 +++++++------- .../article-analyzer/app/commands/rageRank.ts | 26 +++++- .../article-analyzer/app/commands/report.ts | 17 +++- .../article-analyzer/app/ensureData.ts | 12 +-- .../{ => app}/mock/articles.json | 0 json-server/article-analyzer/app/state.ts | 11 ++- json-server/article-analyzer/app/types.ts | 28 ++++++ json-server/article-analyzer/graph.ts | 72 ---------------- json-server/article-analyzer/main.ts | 7 +- json-server/article-analyzer/pagerank.ts | 86 ------------------- json-server/article-analyzer/types.ts | 16 ---- 24 files changed, 321 insertions(+), 351 deletions(-) rename json-server/article-analyzer/{ => app}/__tests__/graph.test.ts (84%) rename json-server/article-analyzer/{ => app}/__tests__/loader.test.ts (98%) rename json-server/article-analyzer/{ => app}/__tests__/pagerank.test.ts (56%) rename json-server/article-analyzer/{ => app}/__tests__/validator.test.ts (93%) delete mode 100644 json-server/article-analyzer/app/algorithm/algorithms.ts create mode 100644 json-server/article-analyzer/app/algorithm/graph.ts create mode 100644 json-server/article-analyzer/app/algorithm/pagerank.ts rename json-server/article-analyzer/{ => app/algorithm}/validator.ts (91%) rename json-server/article-analyzer/{ => app/commands}/loader.ts (95%) rename json-server/article-analyzer/{ => app}/mock/articles.json (100%) create mode 100644 json-server/article-analyzer/app/types.ts delete mode 100644 json-server/article-analyzer/graph.ts delete mode 100644 json-server/article-analyzer/pagerank.ts delete mode 100644 json-server/article-analyzer/types.ts diff --git a/json-server/article-analyzer/__tests__/graph.test.ts b/json-server/article-analyzer/app/__tests__/graph.test.ts similarity index 84% rename from json-server/article-analyzer/__tests__/graph.test.ts rename to json-server/article-analyzer/app/__tests__/graph.test.ts index b63763f0..e6904f1f 100644 --- a/json-server/article-analyzer/__tests__/graph.test.ts +++ b/json-server/article-analyzer/app/__tests__/graph.test.ts @@ -1,4 +1,4 @@ -import { buildGraphSparse, buildGraphDense } from '../graph'; +import { buildDense, buildSparse } from '../algorithm/graph'; describe('Построение графа', () => { const articles = [ @@ -8,7 +8,7 @@ describe('Построение графа', () => { ]; test('Разреженное представление – проверка ветвей outDegree > 0 и =0', () => { - const graph = buildGraphSparse(articles); + const graph = buildSparse(articles); expect(graph.outDegree).toEqual([1, 2, 1]); expect(graph.outLinks[0]).toEqual([1]); expect(graph.outLinks[1]).toEqual([0, 2]); @@ -16,7 +16,7 @@ describe('Построение графа', () => { }); test('Плотное представление', () => { - const graph = buildGraphDense(articles); + const graph = buildDense(articles); expect(graph.matrix[0][1]).toBe(1); expect(graph.matrix[1][0]).toBe(1); expect(graph.matrix[1][2]).toBe(1); @@ -35,9 +35,7 @@ describe('Построение графа', () => { }, { id: '2', title: 'B', authors: [], year: 2020, citations: [] }, ]; - const graph = buildGraphSparse(articlesMissing, { - ignoreMissing: true, - }); + const graph = buildSparse(articlesMissing); expect(graph.outLinks[0]).toEqual([1]); // только ссылка на '2' }); }); diff --git a/json-server/article-analyzer/__tests__/loader.test.ts b/json-server/article-analyzer/app/__tests__/loader.test.ts similarity index 98% rename from json-server/article-analyzer/__tests__/loader.test.ts rename to json-server/article-analyzer/app/__tests__/loader.test.ts index 85f91075..75332b65 100644 --- a/json-server/article-analyzer/__tests__/loader.test.ts +++ b/json-server/article-analyzer/app/__tests__/loader.test.ts @@ -1,6 +1,6 @@ import fs from 'fs'; import { Readable } from 'stream'; -import { loadArticlesFromFile } from '../loader'; +import { loadArticlesFromFile } from '../commands/loader'; jest.mock('fs'); diff --git a/json-server/article-analyzer/__tests__/pagerank.test.ts b/json-server/article-analyzer/app/__tests__/pagerank.test.ts similarity index 56% rename from json-server/article-analyzer/__tests__/pagerank.test.ts rename to json-server/article-analyzer/app/__tests__/pagerank.test.ts index 53ae8d4b..e978a5a0 100644 --- a/json-server/article-analyzer/__tests__/pagerank.test.ts +++ b/json-server/article-analyzer/app/__tests__/pagerank.test.ts @@ -1,6 +1,5 @@ -/* eslint-disable no-plusplus */ -import { pagerankSparse, pagerankDense } from '../pagerank'; -import { buildGraphSparse, buildGraphDense } from '../graph'; +import { buildDense, buildSparse } from '../algorithm/graph'; +import { pagerankDense, pagerankSparse } from '../algorithm/pagerank'; describe('PageRank', () => { const articles = [ @@ -8,35 +7,35 @@ describe('PageRank', () => { { id: '2', title: 'B', authors: [], year: 2020, citations: ['1', '3'] }, { id: '3', title: 'C', authors: [], year: 2020, citations: ['1'] }, ]; - const graphSparse = buildGraphSparse(articles); - const graphDense = buildGraphDense(articles); - const n = 3; + const graphSparse = buildSparse(articles); + const graphDense = buildDense(articles); + const { n } = graphDense; test('Сравнение двух реализаций (результаты должны совпадать)', () => { - const prSparse = pagerankSparse(graphSparse, 0.85, 20, n); - const prDense = pagerankDense(graphDense, 0.85, 20, n); - for (let i = 0; i < n; i++) { + const prSparse = pagerankSparse(graphSparse, 0.85, 20); + const prDense = pagerankDense(graphDense, 0.85, 20); + for (let i = 0; i < n; i += 1) { expect(prSparse[i]).toBeCloseTo(prDense[i], 6); } }); test('iterations = 1 (минимальное допустимое)', () => { - expect(() => pagerankSparse(graphSparse, 0.85, 1, n)).not.toThrow(); + expect(() => pagerankSparse(graphSparse, 0.85, 1)).not.toThrow(); }); test('iterations = 0 (недопустимо)', () => { - expect(() => pagerankSparse(graphSparse, 0.85, 0, n)).toThrow( + expect(() => pagerankSparse(graphSparse, 0.85, 0)).toThrow( 'Iterations must be >= 1', ); }); test('damping = 0.5 (допустимо)', () => { - const pr = pagerankSparse(graphSparse, 0.5, 20, n); + const pr = pagerankSparse(graphSparse, 0.5, 20); expect(pr).toBeDefined(); }); test('damping = 1 (недопустимо)', () => { - expect(() => pagerankSparse(graphSparse, 1, 20, n)).toThrow( + expect(() => pagerankSparse(graphSparse, 1, 20)).toThrow( 'Damping must be in (0,1)', ); }); diff --git a/json-server/article-analyzer/__tests__/validator.test.ts b/json-server/article-analyzer/app/__tests__/validator.test.ts similarity index 93% rename from json-server/article-analyzer/__tests__/validator.test.ts rename to json-server/article-analyzer/app/__tests__/validator.test.ts index 87412234..151b2212 100644 --- a/json-server/article-analyzer/__tests__/validator.test.ts +++ b/json-server/article-analyzer/app/__tests__/validator.test.ts @@ -1,4 +1,4 @@ -import { validateArticle } from '../validator'; +import { validateArticle } from '../algorithm/validator'; describe('Валидация статей', () => { test.each([ diff --git a/json-server/article-analyzer/app/algorithm/algorithms.ts b/json-server/article-analyzer/app/algorithm/algorithms.ts deleted file mode 100644 index 7deba0fe..00000000 --- a/json-server/article-analyzer/app/algorithm/algorithms.ts +++ /dev/null @@ -1,82 +0,0 @@ -// АЛГОРИТМЫ (встроены в CLI — не требуют сборки TypeScript) - -export function pagerankSparse( - graph: any, - damping: number, - iterations: number, -) { - if (iterations < 1) throw new Error('Iterations must be >= 1'); - if (damping <= 0 || damping >= 1) - throw new Error('Damping must be in (0,1)'); - const { n, outDegree, outLinks } = graph; - let pr = Array(n).fill(1 / n); - for (let k = 0; k < iterations; k += 1) { - const np = Array(n).fill((1 - damping) / n); - for (let v = 0; v < n; v += 1) { - if (outDegree[v] > 0) { - // ветка true - const c = (damping * pr[v]) / outDegree[v]; - // eslint-disable-next-line no-restricted-syntax - for (const j of outLinks[v]) np[j] += c; - } else { - // висячая вершина - const c = (damping * pr[v]) / n; - for (let j = 0; j < n; j += 1) np[j] += c; - } - } - pr = np; - } - return pr; -} - -export function pagerankDense(graph: any, damping: number, iterations: number) { - if (iterations < 1) throw new Error('Iterations must be >= 1'); - if (damping <= 0 || damping >= 1) - throw new Error('Damping must be in (0,1)'); - const { n, matrix } = graph; - const M = Array.from({ length: n }, (_, i) => { - const deg = matrix[i].reduce((s: any, v: any) => s + v, 0); - return Array.from({ length: n }, (_, j) => - deg > 0 ? matrix[i][j] / deg : 1 / n, - ); - }); - let pr = Array(n).fill(1 / n); - for (let k = 0; k < iterations; k += 1) { - const np = Array(n).fill((1 - damping) / n); - for (let j = 0; j < n; j += 1) - for (let i = 0; i < n; i += 1) np[j] += damping * M[i][j] * pr[i]; - pr = np; - } - return pr; -} - -export function buildSparse(articles: any[]) { - const n = articles.length; - const idx = new Map(articles.map((a, i) => [a.id, i])); - const outLinks = Array.from({ length: n }, () => []); - const inLinks = Array.from({ length: n }, () => []); - const outDegree = Array(n).fill(0); - articles.forEach((a, i) => { - (a.citations || []).forEach((cid: any) => { - const j = idx.get(cid); - if (j === undefined) return; // ignoreMissing - outLinks[i].push(j); - inLinks[j].push(i); - outDegree[i] += 1; - }); - }); - return { outLinks, inLinks, outDegree, n }; -} - -export function buildDense(articles: any[]) { - const n = articles.length; - const idx = new Map(articles.map((a, i) => [a.id, i])); - const matrix = Array.from({ length: n }, () => Array(n).fill(0)); - articles.forEach((a, i) => - (a.citations || []).forEach((cid: any) => { - const j = idx.get(cid); - if (j !== undefined) matrix[i][j] = 1; - }), - ); - return { matrix, n }; -} diff --git a/json-server/article-analyzer/app/algorithm/graph.ts b/json-server/article-analyzer/app/algorithm/graph.ts new file mode 100644 index 00000000..2c29b66a --- /dev/null +++ b/json-server/article-analyzer/app/algorithm/graph.ts @@ -0,0 +1,44 @@ +import { Article, GraphDense, GraphSparse } from '../types'; + +/** + * Строит разреженное представление графа. + */ + +export function buildSparse(articles: Article[]): GraphSparse { + const n = articles.length; + + const idx = new Map(articles.map((a, i) => [a.id, i])); + const outLinks: number[][] = Array.from({ length: n }, () => []); + const inLinks: number[][] = Array.from({ length: n }, () => []); + const outDegree = Array(n).fill(0); + + articles.forEach((a, i) => { + (a.citations || []).forEach((cid: any) => { + const j = idx.get(cid); + if (j === undefined) return; // ignoreMissing + outLinks[i].push(j); + inLinks[j].push(i); + outDegree[i] += 1; + }); + }); + + return { outLinks, inLinks, outDegree, n }; +} + +/** + * Строит плотную матрицу смежности. + */ +export function buildDense(articles: Article[]): GraphDense { + const n = articles.length; + const idx = new Map(articles.map((a, i) => [a.id, i])); + const matrix = Array.from({ length: n }, () => Array(n).fill(0)); + + articles.forEach((a, i) => + (a.citations || []).forEach((cid: any) => { + const j = idx.get(cid); + if (j !== undefined) matrix[i][j] = 1; + }), + ); + + return { matrix, n }; +} diff --git a/json-server/article-analyzer/app/algorithm/pagerank.ts b/json-server/article-analyzer/app/algorithm/pagerank.ts new file mode 100644 index 00000000..47ff6acf --- /dev/null +++ b/json-server/article-analyzer/app/algorithm/pagerank.ts @@ -0,0 +1,68 @@ +import { GraphDense, GraphSparse } from '../types'; + +export function pagerankSparse( + graph: GraphSparse, + damping: number, + iterations: number, +): number[] { + if (iterations < 1) throw new Error('Iterations must be >= 1'); + if (damping <= 0 || damping >= 1) + throw new Error('Damping must be in (0,1)'); + + const { n, outDegree, outLinks } = graph; + + let pr: number[] = Array(n).fill(1 / n); + + for (let k = 0; k < iterations; k += 1) { + const newPr = Array(n).fill((1 - damping) / n); + for (let v = 0; v < n; v += 1) { + if (outDegree[v] > 0) { + // ветка true + const c = (damping * pr[v]) / outDegree[v]; + + // eslint-disable-next-line no-restricted-syntax + for (const j of outLinks[v]) newPr[j] += c; + } else { + // висячая вершина + const c = (damping * pr[v]) / n; + for (let j = 0; j < n; j += 1) newPr[j] += c; + } + } + pr = newPr; + } + + return pr; +} + +/** + * Плотная версия PageRank. + */ +export function pagerankDense( + graph: GraphDense, + damping: number, + iterations: number, +): number[] { + if (iterations < 1) throw new Error('Iterations must be >= 1'); + if (damping <= 0 || damping >= 1) + throw new Error('Damping must be in (0,1)'); + + const { n, matrix } = graph; + + const M = Array.from({ length: n }, (_, i) => { + const deg = matrix[i].reduce((s, v) => s + v, 0); + return Array.from({ length: n }, (_, j) => + deg > 0 ? matrix[i][j] / deg : 1 / n, + ); + }); + + let pr: number[] = Array(n).fill(1 / n); + + for (let k = 0; k < iterations; k += 1) { + const np = Array(n).fill((1 - damping) / n); + for (let j = 0; j < n; j += 1) + for (let i = 0; i < n; i += 1) np[j] += damping * M[i][j] * pr[i]; + pr = np; + } + + return pr; +} diff --git a/json-server/article-analyzer/validator.ts b/json-server/article-analyzer/app/algorithm/validator.ts similarity index 91% rename from json-server/article-analyzer/validator.ts rename to json-server/article-analyzer/app/algorithm/validator.ts index 5d6bca10..5d536109 100644 --- a/json-server/article-analyzer/validator.ts +++ b/json-server/article-analyzer/app/algorithm/validator.ts @@ -8,14 +8,22 @@ export interface ArticleInput { export function validateArticle(article: ArticleInput): boolean { if (!article.id || typeof article.id !== 'string') return false; + if (!article.title || typeof article.title !== 'string') return false; - if (article.authors !== undefined && !Array.isArray(article.authors)) + + if (article.authors !== undefined && !Array.isArray(article.authors)) { return false; + } + if (article.year !== undefined) { - if (typeof article.year !== 'number' || article.year < 1900) + if (typeof article.year !== 'number' || article.year < 1900) { return false; + } } - if (article.citations !== undefined && !Array.isArray(article.citations)) + + if (article.citations !== undefined && !Array.isArray(article.citations)) { return false; + } + return true; } diff --git a/json-server/article-analyzer/app/commands/buildGraph.ts b/json-server/article-analyzer/app/commands/buildGraph.ts index fb958001..6c3ed851 100644 --- a/json-server/article-analyzer/app/commands/buildGraph.ts +++ b/json-server/article-analyzer/app/commands/buildGraph.ts @@ -4,6 +4,12 @@ import { BOLD, CYAN, GRAY, GREEN, HR, NL, YELLOW } from '../tools'; export function cmdBuildGraph() { if (!ensureData()) return; + + if (!state.sparse) { + console.log('Ошибка с построением графа, нет sparse-представления'); + return; + } + const edges = state.sparse.outLinks.reduce((s, l) => s + l.length, 0); const dangling = state.sparse.outDegree.filter((d) => d === 0).length; const avgDeg = (edges / state.sparse.n).toFixed(2); @@ -35,6 +41,11 @@ export function cmdBuildGraph() { ); NL(); + if (!state.articles) { + console.log('Ошибка с построением графа, нет articles'); + return; + } + // Матрица смежности (до 8×8) const n = Math.min(state.sparse.n, 8); const labels = state.articles @@ -46,6 +57,8 @@ export function cmdBuildGraph() { for (let i = 0; i < n; i += 1) { const row = Array.from({ length: n }, (_, j) => { + if (!state.dense) return GRAY(' 0 '); + const v = state.dense.matrix[i][j]; return v ? GREEN(' 1 ') : GRAY(' 0 '); }).join(''); @@ -56,11 +69,20 @@ export function cmdBuildGraph() { // Списки смежности console.log(GRAY(' Списки смежности (out[v]):')); state.articles.slice(0, 10).forEach((a, i) => { + if (!state.sparse) { + console.log( + GRAY(' ') + BOLD(a.id.padEnd(8)) + GRAY('→ [') + GRAY(']'), + ); + return; + } + const neighbors = state.sparse.outLinks[i] - .map((j) => CYAN(state.articles[j].id)) + .map((j) => CYAN(state.articles ? state.articles[j].id : '0')) .join(', ') || GRAY('—'); + const deg = state.sparse.outDegree[i]; + console.log( GRAY(' ') + BOLD(a.id.padEnd(8)) + diff --git a/json-server/article-analyzer/app/commands/cmdLoad.ts b/json-server/article-analyzer/app/commands/cmdLoad.ts index 07411151..46546d1b 100644 --- a/json-server/article-analyzer/app/commands/cmdLoad.ts +++ b/json-server/article-analyzer/app/commands/cmdLoad.ts @@ -1,15 +1,18 @@ -import { loadArticlesFromFile } from '../../loader'; -import { buildDense, buildSparse } from '../algorithm/algorithms'; +import { buildDense, buildSparse } from '../algorithm/graph'; import { state } from '../state'; import { BOLD, CYAN, GRAY, GREEN } from '../tools'; +import { loadArticlesFromFile } from './loader'; export async function cmdLoad(filePath: string, silent = false) { if (!silent) console.log(GRAY(' Загрузка: ') + CYAN(filePath)); + state.articles = await loadArticlesFromFile(filePath, true); state.sparse = buildSparse(state.articles); state.dense = buildDense(state.articles); state.loadedFile = filePath; + const edges = state.sparse.outLinks.reduce((s, l) => s + l.length, 0); + if (!silent) { console.log( GREEN(' ✓ Загружено статей : ') + BOLD(state.articles.length), diff --git a/json-server/article-analyzer/app/commands/compare.ts b/json-server/article-analyzer/app/commands/compare.ts index 8f712016..c01d0ac5 100644 --- a/json-server/article-analyzer/app/commands/compare.ts +++ b/json-server/article-analyzer/app/commands/compare.ts @@ -1,7 +1,7 @@ import { BOLD, CYAN, GRAY, GREEN, HR, NL, YELLOW } from '../tools'; -import { pagerankDense, pagerankSparse } from '../algorithm/algorithms'; import { ensureData } from '../ensureData'; import { state } from '../state'; +import { pagerankDense, pagerankSparse } from '../algorithm/pagerank'; export function cmdCompare(iter: number, damping: number) { if (!ensureData()) return; @@ -18,8 +18,19 @@ export function cmdCompare(iter: number, damping: number) { const runs = 3; let sumDense = 0; let sumSparse = 0; - let prDense: any[]; - let prSparse: any[]; + let prDense: number[]; + let prSparse: number[]; + + if (!state.dense) { + console.log('невозможно сравнить, нет state.dense'); + return; + } + + if (!state.sparse) { + console.log('невозможно сравнить, нет state.sparse'); + return; + } + for (let r = 0; r < runs; r += 1) { let t = Date.now(); prDense = pagerankDense(state.dense, damping, iter); @@ -28,13 +39,15 @@ export function cmdCompare(iter: number, damping: number) { prSparse = pagerankSparse(state.sparse, damping, iter); sumSparse += Date.now() - t; } + const tDense = (sumDense / runs).toFixed(2); const tSparse = (sumSparse / runs).toFixed(2); // Проверяем совпадение let maxDiff = 0; - for (let i = 0; i < state.sparse.n; i += 1) + for (let i = 0; i < state.sparse.n; i += 1) { maxDiff = Math.max(maxDiff, Math.abs(prDense[i] - prSparse[i])); + } const COL = 28; const row = (label: string, v1: string | number, v2: string | number) => @@ -50,6 +63,7 @@ export function cmdCompare(iter: number, damping: number) { GREEN(BOLD('Способ 2: Спис. смежности')), ); console.log(GRAY(` ${'─'.repeat(72)}`)); + row('Структура', 'Плотная матрица N×N', 'Списки смежности'); row('Память', 'O(N²)', 'O(N + E)'); row('Итерация', 'O(N²)', 'O(N + E)'); @@ -68,6 +82,7 @@ export function cmdCompare(iter: number, damping: number) { row('Итераций', iter, iter); row(`Время, мс (avg ${runs} runs)`, `${tDense} мс`, `${tSparse} мс`); NL(); + if (maxDiff < 1e-9) { console.log(GREEN(' ✓ Результаты идентичны (|diff| < 1e-9)')); } else { @@ -81,19 +96,29 @@ export function cmdCompare(iter: number, damping: number) { console.log(HR()); console.log(BOLD(' Ранжирование статей (оба метода):')); NL(); + + if (!state.articles) { + console.log( + 'Ошибка с построением графа, нет articles, не могу вывести топ по обоим методам', + ); + return; + } + const rD = state.articles - .map((a: any, i: string | number) => ({ ...a, rank: prDense[i] })) - .sort((a: { rank: number }, b: { rank: number }) => b.rank - a.rank); + .map((a, i) => ({ ...a, rank: prDense[i] })) + .sort((a, b) => b.rank - a.rank); const rS = state.articles - .map((a: any, i: string | number) => ({ ...a, rank: prSparse[i] })) - .sort((a: { rank: number }, b: { rank: number }) => b.rank - a.rank); + .map((a, i) => ({ ...a, rank: prSparse[i] })) + .sort((a, b) => b.rank - a.rank); const topN = Math.min(7, state.articles.length); + console.log( GRAY(' # ') + CYAN(BOLD('Матрица ')) + GREEN(BOLD('Разреженные списки')), ); console.log(GRAY(` ${'─'.repeat(72)}`)); + for (let i = 0; i < topN; i += 1) { console.log( GRAY(` ${String(i + 1).padEnd(4)}`) + diff --git a/json-server/article-analyzer/app/commands/export.ts b/json-server/article-analyzer/app/commands/export.ts index b0a03a95..40545837 100644 --- a/json-server/article-analyzer/app/commands/export.ts +++ b/json-server/article-analyzer/app/commands/export.ts @@ -1,11 +1,17 @@ import fs from 'fs'; -import { pagerankSparse } from '../algorithm/algorithms.ts'; import { ensureData } from '../ensureData'; import { BOLD, CYAN, GRAY, GREEN } from '../tools'; -import { state } from '../state.ts'; +import { state } from '../state'; +import { pagerankSparse } from '../algorithm/pagerank'; export function cmdExport(outFile: string, iter: number, damping: number) { if (!ensureData()) return; + + if (!state.sparse) { + console.log('Нет данных для экспорта'); + return; + } + const pr = pagerankSparse(state.sparse, damping, iter); if (!state.sparse || !state.articles) return; @@ -30,6 +36,7 @@ export function cmdExport(outFile: string, iter: number, damping: number) { })) .sort((a, b) => b.rank - a.rank), }; + try { fs.writeFileSync(outFile, JSON.stringify(result, null, 2), 'utf8'); console.log(GREEN(' ✓ Результаты экспортированы: ') + CYAN(outFile)); diff --git a/json-server/article-analyzer/app/commands/launchTest.ts b/json-server/article-analyzer/app/commands/launchTest.ts index 0fad976b..9cca979f 100644 --- a/json-server/article-analyzer/app/commands/launchTest.ts +++ b/json-server/article-analyzer/app/commands/launchTest.ts @@ -1,11 +1,9 @@ -/* eslint-disable no-console */ import fs from 'fs'; import path from 'path'; import { spawnSync } from 'child_process'; import { BOLD, CYAN, GRAY, GREEN, HR, NL, RED } from '../tools'; const ROOT = path.join(__dirname, '../../../../'); -// const ROOT = path.join(__dirname); export function cmdTest(group: string, verbose: boolean) { const jestBin = path.join(ROOT, 'node_modules', '.bin', 'jest'); diff --git a/json-server/article-analyzer/loader.ts b/json-server/article-analyzer/app/commands/loader.ts similarity index 95% rename from json-server/article-analyzer/loader.ts rename to json-server/article-analyzer/app/commands/loader.ts index dfe1e572..37c9ae1d 100644 --- a/json-server/article-analyzer/loader.ts +++ b/json-server/article-analyzer/app/commands/loader.ts @@ -1,9 +1,37 @@ -/* eslint-disable no-restricted-syntax */ -/* eslint-disable no-use-before-define */ import fs, { createReadStream } from 'fs'; import path from 'path'; import { createInterface } from 'readline'; -import { Article, RawArticle } from './types'; +import { Article, RawArticle } from '../types'; + +/** + * Нормализует сырые данные статей к единому формату. + */ +export async function normalizeArticles( + rawArticles: RawArticle[], +): Promise { + return rawArticles.map((raw) => { + if (!raw.id) throw new Error('[103] Missing required field: id'); + if (!raw.title) throw new Error('[103] Missing required field: title'); + if (raw.year && (typeof raw.year !== 'number' || raw.year < 1900)) { + throw new Error('[103] Invalid year'); + } + const year = + raw.year !== undefined && raw.year !== null + ? raw.year + : new Date().getFullYear(); + if (typeof year !== 'number' || year < 1900) + throw new Error(`[104] Invalid year: ${year}`); + if (raw.citations !== undefined && !Array.isArray(raw.citations)) + throw new Error('[104] citations must be an array'); + return { + id: String(raw.id), + title: String(raw.title), + year, + authors: Array.isArray(raw.authors) ? raw.authors : [], + citations: Array.isArray(raw.citations) ? raw.citations : [], + }; + }); +} /** * Загружает статьи из JSON-файла с поддержкой потоковой обработки. @@ -33,6 +61,7 @@ export async function loadArticlesFromFile( let buffer = ''; try { + // eslint-disable-next-line no-restricted-syntax for await (const line of rl) { buffer += line; } @@ -52,33 +81,3 @@ export async function loadArticlesFromFile( // normalizeArticles выбросит собственную ошибку, если данные некорректны return normalizeArticles(articles); } - -/** - * Нормализует сырые данные статей к единому формату. - */ -export async function normalizeArticles( - rawArticles: RawArticle[], -): Promise { - return rawArticles.map((raw) => { - if (!raw.id) throw new Error('[103] Missing required field: id'); - if (!raw.title) throw new Error('[103] Missing required field: title'); - if (raw.year && (typeof raw.year !== 'number' || raw.year < 1900)) { - throw new Error('[103] Invalid year'); - } - const year = - raw.year !== undefined && raw.year !== null - ? raw.year - : new Date().getFullYear(); - if (typeof year !== 'number' || year < 1900) - throw new Error(`[104] Invalid year: ${year}`); - if (raw.citations !== undefined && !Array.isArray(raw.citations)) - throw new Error('[104] citations must be an array'); - return { - id: String(raw.id), - title: String(raw.title), - year, - authors: Array.isArray(raw.authors) ? raw.authors : [], - citations: Array.isArray(raw.citations) ? raw.citations : [], - }; - }); -} diff --git a/json-server/article-analyzer/app/commands/rageRank.ts b/json-server/article-analyzer/app/commands/rageRank.ts index 3303f31e..6df1c8d7 100644 --- a/json-server/article-analyzer/app/commands/rageRank.ts +++ b/json-server/article-analyzer/app/commands/rageRank.ts @@ -1,7 +1,7 @@ import { BOLD, CYAN, DIM, GRAY, GREEN, HR, NL, WHITE, YELLOW } from '../tools'; -import { pagerankDense, pagerankSparse } from '../algorithm/algorithms'; import { ensureData } from '../ensureData'; import { state } from '../state'; +import { pagerankDense, pagerankSparse } from '../algorithm/pagerank'; export function cmdPageRank(method: string, iter: number, damping: number) { if (!ensureData()) return; @@ -28,6 +28,16 @@ export function cmdPageRank(method: string, iter: number, damping: number) { NL(); const t0 = Date.now(); + + if (!state.dense) { + console.log(' Нет dense-представления'); + return; + } + if (!state.sparse) { + console.log('Нет sparse-представления'); + return; + } + const pr = useSparse ? pagerankSparse(state.sparse, damping, iter) : pagerankDense(state.dense, damping, iter); @@ -39,8 +49,8 @@ export function cmdPageRank(method: string, iter: number, damping: number) { } const ranked = state.articles - .map((a: any, i: string | number) => ({ ...a, rank: pr[i] })) - .sort((a: { rank: number }, b: { rank: number }) => b.rank - a.rank); + .map((a, i) => ({ ...a, rank: pr[i] })) + .sort((a, b) => b.rank - a.rank); const maxR = ranked[0].rank; const topN = Math.min(10, ranked.length); @@ -69,6 +79,16 @@ export function cmdPageRank(method: string, iter: number, damping: number) { a.title.slice(0, 44).padEnd(45), )}${GRAY(' rank: ')}${GREEN(a.rank.toFixed(6))}`, ); + + if (!state.sparse) { + console.log('Нет sparse-представления'); + return; + } + if (!state.articles) { + console.log('Нет статей'); + return; + } + console.log( GRAY(' ') + filled + diff --git a/json-server/article-analyzer/app/commands/report.ts b/json-server/article-analyzer/app/commands/report.ts index 8df53c00..8be4ee2c 100644 --- a/json-server/article-analyzer/app/commands/report.ts +++ b/json-server/article-analyzer/app/commands/report.ts @@ -1,17 +1,18 @@ -import { pagerankSparse } from '../algorithm/algorithms'; +import { pagerankSparse } from '../algorithm/pagerank'; import { ensureData } from '../ensureData'; import { state } from '../state'; import { BOLD, CYAN, GRAY, GREEN, HR, NL, YELLOW } from '../tools'; export function cmdReport() { if (!ensureData()) return; - const pr = pagerankSparse(state.sparse, 0.85, 20); if (!state.sparse) { console.log('Ошибка с отчетом'); return; } + const pr = pagerankSparse(state.sparse, 0.85, 20); + console.log('outLinks', state.sparse.outLinks); const edges = state.sparse.outLinks.reduce( @@ -30,6 +31,12 @@ export function cmdReport() { console.log( GRAY(' Источник данных: ') + CYAN(state.loadedFile || 'demo'), ); + + if (!state.articles) { + console.log('Нет статей, поэтому не могу посчитать PageRank'); + return; + } + console.log(GRAY(' Всего статей: ') + BOLD(state.articles.length)); console.log(GRAY(' Всего цитирований: ') + BOLD(edges)); console.log( @@ -40,10 +47,12 @@ export function cmdReport() { NL(); const ranked = state.articles - .map((a: any, i: string | number) => ({ ...a, rank: pr[i] })) - .sort((a: { rank: number }, b: { rank: number }) => b.rank - a.rank); + .map((a, i) => ({ ...a, rank: pr[i] })) + .sort((a, b) => b.rank - a.rank); + console.log(BOLD(' Топ статей по PageRank (метод: разреженные списки):')); NL(); + ranked.forEach((a: { title: string | any[]; rank: number }, i: number) => { // eslint-disable-next-line no-nested-ternary const medal = i === 0 ? YELLOW('★') : i < 3 ? GRAY('·') : GRAY(' '); diff --git a/json-server/article-analyzer/app/ensureData.ts b/json-server/article-analyzer/app/ensureData.ts index 0849baf3..3abf48c3 100644 --- a/json-server/article-analyzer/app/ensureData.ts +++ b/json-server/article-analyzer/app/ensureData.ts @@ -1,19 +1,9 @@ -/* eslint-disable no-console */ import path from 'path'; import fs from 'fs'; import { state } from './state'; import { CYAN, GRAY, YELLOW } from './tools'; import { cmdLoad } from './commands/cmdLoad'; -// const ROOT = path.join(__dirname, '../../../'); -// const demo = path.join( -// ROOT, -// 'json-server', -// 'article-analyzer', -// 'mock', -// 'articles.json', -// ); - export function ensureData() { if (state.articles) return true; const demo = path.join(__dirname, '../mock/articles.json'); @@ -21,7 +11,7 @@ export function ensureData() { if (fs.existsSync(demo)) { console.log( GRAY(' → Данные не загружены, используются demo: ') + - CYAN('../mock/articles.json'), + CYAN('mock/articles.json'), ); cmdLoad(demo, true); return true; diff --git a/json-server/article-analyzer/mock/articles.json b/json-server/article-analyzer/app/mock/articles.json similarity index 100% rename from json-server/article-analyzer/mock/articles.json rename to json-server/article-analyzer/app/mock/articles.json diff --git a/json-server/article-analyzer/app/state.ts b/json-server/article-analyzer/app/state.ts index e8fcdf59..b1459921 100644 --- a/json-server/article-analyzer/app/state.ts +++ b/json-server/article-analyzer/app/state.ts @@ -1,5 +1,14 @@ +import { Article, GraphDense, GraphSparse } from './types'; + +interface State { + articles: Article[] | null; + sparse: GraphSparse | null; + dense: GraphDense | null; + loadedFile: string | null; +} + // СОСТОЯНИЕ СЕССИИ -export const state = { +export const state: State = { articles: null, sparse: null, dense: null, diff --git a/json-server/article-analyzer/app/types.ts b/json-server/article-analyzer/app/types.ts new file mode 100644 index 00000000..e80020f1 --- /dev/null +++ b/json-server/article-analyzer/app/types.ts @@ -0,0 +1,28 @@ +export interface Article { + id: string; + title: string; + authors: string[]; + year: number; + citations: string[]; +} + +export interface RawArticle { + id: string | number; + title: string; + authors?: string[]; + year?: number; + citations?: string[]; + references?: string[]; +} + +export interface GraphDense { + matrix: number[][]; // плотная матрица смежности + n: number; +} + +export interface GraphSparse { + outLinks: number[][]; // для каждой вершины список индексов исходящих соседей + inLinks: number[][]; // входящие соседи + outDegree: number[]; + n: number; +} diff --git a/json-server/article-analyzer/graph.ts b/json-server/article-analyzer/graph.ts deleted file mode 100644 index d69b08c8..00000000 --- a/json-server/article-analyzer/graph.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Article } from './types'; - -export interface GraphSparse { - outLinks: number[][]; // для каждой вершины список индексов исходящих соседей - inLinks: number[][]; // входящие соседи - outDegree: number[]; - n: number; -} - -export interface GraphDense { - matrix: number[][]; // плотная матрица смежности - n: number; -} - -/** - * Строит разреженное представление графа. - */ -export function buildGraphSparse( - articles: Article[], - options = { ignoreMissing: false }, -): GraphSparse { - const idToIndex = new Map(); - articles.forEach((a, idx) => idToIndex.set(a.id, idx)); - - const outLinks: number[][] = Array(articles.length) - .fill(0) - .map(() => []); - const inLinks: number[][] = Array(articles.length) - .fill(0) - .map(() => []); - const outDegree = Array(articles.length).fill(0); - - articles.forEach((article, idx) => { - const targets = article.citations - .map((ref) => idToIndex.get(ref)) - .filter((t) => t !== undefined) as number[]; - if ( - !options.ignoreMissing && - targets.length !== article.citations.length - ) { - throw new Error('Some citations refer to missing articles'); - } - outLinks[idx] = targets; - outDegree[idx] = targets.length; - targets.forEach((t) => inLinks[t].push(idx)); - }); - - return { outLinks, inLinks, outDegree, n: articles.length }; -} - -/** - * Строит плотную матрицу смежности. - */ -export function buildGraphDense(articles: Article[]): GraphDense { - const n = articles.length; - const idToIndex = new Map(); - articles.forEach((a, idx) => idToIndex.set(a.id, idx)); - - const matrix = Array(n) - .fill(0) - .map(() => Array(n).fill(0)); - articles.forEach((article, i) => { - article.citations.forEach((ref) => { - const j = idToIndex.get(ref); - if (j !== undefined) { - matrix[i][j] = 1; - } - }); - }); - - return { matrix, n }; -} diff --git a/json-server/article-analyzer/main.ts b/json-server/article-analyzer/main.ts index aa6286de..c8f5bbc0 100644 --- a/json-server/article-analyzer/main.ts +++ b/json-server/article-analyzer/main.ts @@ -26,8 +26,6 @@ import { printBanner, printHelp } from './app/print/help'; import { MENU_ITEMS, printMenu } from './app/print/menu'; import { BOLD, CYAN, GRAY, RED, YELLOW } from './app/tools'; -const ROOT = path.join(__dirname, '../..'); - // ИНТЕРАКТИВНОЕ МЕНЮ (readline, без зависимостей) (function main() { @@ -64,10 +62,11 @@ const ROOT = path.join(__dirname, '../..'); String( await ask( GRAY( - ' Путь к JSON-файлу [data/articles.json]: ', + ' Путь к JSON-файлу [mock/articles.json]: ', ), ), - ) || path.join(ROOT, 'data', 'articles.json'); + ) || + path.join(__dirname, 'app', 'mock', 'articles.json'); cmdLoad(fp); } if (item.action === 'build-graph') { diff --git a/json-server/article-analyzer/pagerank.ts b/json-server/article-analyzer/pagerank.ts deleted file mode 100644 index 6624170e..00000000 --- a/json-server/article-analyzer/pagerank.ts +++ /dev/null @@ -1,86 +0,0 @@ -/* eslint-disable no-restricted-syntax */ -/* eslint-disable no-plusplus */ -import { GraphSparse, GraphDense } from './graph'; - -/** - * Разреженная версия PageRank. - */ -export function pagerankSparse( - graph: GraphSparse, - damping: number, - iterations: number, - n: number, -): number[] { - if (iterations < 1) throw new Error('Iterations must be >= 1'); - if (damping <= 0 || damping >= 1) - throw new Error('Damping must be in (0,1)'); - - let pr = new Array(n).fill(1 / n); - const base = (1 - damping) / n; - - for (let iter = 0; iter < iterations; iter++) { - const newPr = new Array(n).fill(base); - for (let i = 0; i < n; i++) { - if (graph.outDegree[i] === 0) { - // висячая вершина: размазываем равномерно - const contribution = (damping * pr[i]) / n; - for (let j = 0; j < n; j++) { - newPr[j] += contribution; - } - } else { - const contribution = (damping * pr[i]) / graph.outDegree[i]; - for (const j of graph.outLinks[i]) { - newPr[j] += contribution; - } - } - } - pr = newPr; - } - return pr; -} - -/** - * Плотная версия PageRank. - */ -export function pagerankDense( - graph: GraphDense, - damping: number, - iterations: number, - n: number, -): number[] { - if (iterations < 1) throw new Error('Iterations must be >= 1'); - if (damping <= 0 || damping >= 1) - throw new Error('Damping must be in (0,1)'); - - // Вычисляем исходящие степени - const outDegree = Array(n).fill(0); - for (let i = 0; i < n; i++) { - for (let j = 0; j < n; j++) { - outDegree[i] += graph.matrix[i][j]; - } - } - - let pr = new Array(n).fill(1 / n); - const base = (1 - damping) / n; - - for (let iter = 0; iter < iterations; iter++) { - const newPr = new Array(n).fill(base); - for (let i = 0; i < n; i++) { - if (outDegree[i] === 0) { - const contribution = (damping * pr[i]) / n; - for (let j = 0; j < n; j++) { - newPr[j] += contribution; - } - } else { - const contribution = (damping * pr[i]) / outDegree[i]; - for (let j = 0; j < n; j++) { - if (graph.matrix[i][j] > 0) { - newPr[j] += contribution; - } - } - } - } - pr = newPr; - } - return pr; -} diff --git a/json-server/article-analyzer/types.ts b/json-server/article-analyzer/types.ts deleted file mode 100644 index fb1818f2..00000000 --- a/json-server/article-analyzer/types.ts +++ /dev/null @@ -1,16 +0,0 @@ -export interface Article { - id: string; - title: string; - authors: string[]; - year: number; - citations: string[]; -} - -export interface RawArticle { - id: string | number; - title: string; - authors?: string[]; - year?: number; - citations?: string[]; - references?: string[]; -} From 08ceee12e8063a416c2e441b69f6aec055e4f111 Mon Sep 17 00:00:00 2001 From: Pellya Roman Date: Sat, 28 Mar 2026 12:54:11 +0300 Subject: [PATCH 5/6] Some fix for paths --- json-server/article-analyzer/app/__tests__/loader.test.ts | 2 +- .../article-analyzer/app/{commands => algorithm}/loader.ts | 0 json-server/article-analyzer/app/commands/cmdLoad.ts | 2 +- json-server/article-analyzer/main.ts | 5 +++++ 4 files changed, 7 insertions(+), 2 deletions(-) rename json-server/article-analyzer/app/{commands => algorithm}/loader.ts (100%) diff --git a/json-server/article-analyzer/app/__tests__/loader.test.ts b/json-server/article-analyzer/app/__tests__/loader.test.ts index 75332b65..f668d926 100644 --- a/json-server/article-analyzer/app/__tests__/loader.test.ts +++ b/json-server/article-analyzer/app/__tests__/loader.test.ts @@ -1,6 +1,6 @@ import fs from 'fs'; import { Readable } from 'stream'; -import { loadArticlesFromFile } from '../commands/loader'; +import { loadArticlesFromFile } from '../algorithm/loader'; jest.mock('fs'); diff --git a/json-server/article-analyzer/app/commands/loader.ts b/json-server/article-analyzer/app/algorithm/loader.ts similarity index 100% rename from json-server/article-analyzer/app/commands/loader.ts rename to json-server/article-analyzer/app/algorithm/loader.ts diff --git a/json-server/article-analyzer/app/commands/cmdLoad.ts b/json-server/article-analyzer/app/commands/cmdLoad.ts index 46546d1b..b3fb088f 100644 --- a/json-server/article-analyzer/app/commands/cmdLoad.ts +++ b/json-server/article-analyzer/app/commands/cmdLoad.ts @@ -1,7 +1,7 @@ import { buildDense, buildSparse } from '../algorithm/graph'; import { state } from '../state'; import { BOLD, CYAN, GRAY, GREEN } from '../tools'; -import { loadArticlesFromFile } from './loader'; +import { loadArticlesFromFile } from '../algorithm/loader'; export async function cmdLoad(filePath: string, silent = false) { if (!silent) console.log(GRAY(' Загрузка: ') + CYAN(filePath)); diff --git a/json-server/article-analyzer/main.ts b/json-server/article-analyzer/main.ts index c8f5bbc0..a0acd584 100644 --- a/json-server/article-analyzer/main.ts +++ b/json-server/article-analyzer/main.ts @@ -11,6 +11,11 @@ * Запуск: * npx tsx json-server/article-analyzer/main.ts <- интерактивное меню * npx tsx json-server/article-analyzer/main.ts [command] [options] + * + * npx jest json-server/article-analyzer/app/__tests__/ --coverage + * + * Для запуска мутационного тестирования: + * npx stryker run --mutate "json-server/article-analyzer/app/algorithm/**!/*.ts" --incremental */ import path from 'path'; From 34075973ac82b4012fb5d18f0631ea2937d59985 Mon Sep 17 00:00:00 2001 From: Pellya Roman Date: Sat, 28 Mar 2026 12:58:02 +0300 Subject: [PATCH 6/6] Add mutation tests for MTPO --- .gitignore | 8 +- .strykerignore | 9 + package-lock.json | 3190 +++++++++++++++++++++++++++++++++----------- package.json | 2 + stryker.config.mjs | 15 + 5 files changed, 2445 insertions(+), 779 deletions(-) create mode 100644 .strykerignore create mode 100644 stryker.config.mjs diff --git a/.gitignore b/.gitignore index 7c4e7f06..583f7974 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,14 @@ node_modules storybook-static +coverage/ + .loki/report.html .loki/report.json /testplane-report -.testplane \ No newline at end of file +.testplane + +# stryker temp files +.stryker-tmp +reports/ diff --git a/.strykerignore b/.strykerignore new file mode 100644 index 00000000..6d462c29 --- /dev/null +++ b/.strykerignore @@ -0,0 +1,9 @@ +**/__tests__/** +**/*.test.ts +**/mock/** +**/node_modules/** +**/dist/** +**/coverage/** +**/stryker-tmp/** +**/*.d.ts +src/ \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index fc752c5a..a1becc0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,6 +34,8 @@ "@storybook/manager-webpack5": "^6.5.16", "@storybook/react": "^6.5.16", "@storybook/testing-library": "^0.0.13", + "@stryker-mutator/core": "^9.6.0", + "@stryker-mutator/jest-runner": "^9.6.0", "@svgr/webpack": "^6.2.1", "@swc/core": "^1.15.11", "@testing-library/jest-dom": "^5.16.2", @@ -99,62 +101,53 @@ "license": "MIT", "peer": true }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", - "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.17.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz", - "integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helpers": "^7.17.2", - "@babel/parser": "^7.17.3", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -164,6 +157,13 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, "node_modules/@babel/core/node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -197,27 +197,30 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.10.tgz", - "integrity": "sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==", + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.24.9", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.27.3" }, "engines": { "node": ">=6.9.0" @@ -236,14 +239,15 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -276,19 +280,18 @@ "dev": true }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", - "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", + "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.6", "semver": "^6.3.1" }, "engines": { @@ -407,6 +410,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-hoist-variables": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", @@ -420,41 +433,43 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", - "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.8" + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", - "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.24.0" + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", - "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.24.3", - "@babel/helper-simple-access": "^7.24.5", - "@babel/helper-split-export-declaration": "^7.24.5", - "@babel/helper-validator-identifier": "^7.24.5" + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -464,22 +479,24 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", - "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -502,14 +519,15 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", - "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", + "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.7", - "@babel/helper-optimise-call-expression": "^7.24.7" + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -518,26 +536,15 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", - "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", - "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -556,28 +563,31 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -597,14 +607,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", - "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5" + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" }, "engines": { "node": ">=6.9.0" @@ -688,10 +698,14 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", - "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -786,14 +800,15 @@ } }, "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.7.tgz", - "integrity": "sha512-RL9GR0pUG5Kc8BUWLNDm2T5OpYwSX15r98I0IkgmRQTXuELq/OynH8xtMTMvTJFjXbMWFVTKtYkTaYQsuAwQlQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.29.0.tgz", + "integrity": "sha512-CVBVv3VY/XRMxRYq5dwr2DS7/MvqPm23cOCjbwNnVrfOqcWlnefua1uUs0sjdKOGjvPUG633o07uWzJq4oI6dA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-decorators": "^7.24.7" + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-syntax-decorators": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1080,12 +1095,13 @@ } }, "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.7.tgz", - "integrity": "sha512-Ui4uLJJrRV1lb38zg1yYTmRKmiZLiftDEvZN2iq3kd9kUFU+PttmzTbAFC2ucRk/XJmtek6G23gPsuZbhrT8fQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.28.6.tgz", + "integrity": "sha512-71EYI0ONURHJBL4rSFXnITXqXrrY8q4P0q006DPfN+Rk+ASM+++IBXem/ruokgBZR8YNEWZ8R6B+rCb8VcUTqA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1173,12 +1189,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", - "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1290,12 +1307,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", - "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1414,12 +1432,14 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz", - "integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", + "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -1459,6 +1479,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", + "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-exponentiation-operator": { "version": "7.24.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz", @@ -1571,14 +1608,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", - "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", + "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-simple-access": "^7.22.5" + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1903,15 +1940,17 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.4.tgz", - "integrity": "sha512-79t3CQ8+oBGk/80SQ8MN3Bs3obf83zJ0YZjDmDaEZN8MqhMI760apl5z6a20kFeMXBwJX99VpKT8CKxEBp5H1g==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.6.tgz", + "integrity": "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.24.4", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-typescript": "^7.24.1" + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -2102,14 +2141,17 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz", - "integrity": "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz", + "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-transform-typescript": "^7.16.7" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -2249,35 +2291,34 @@ } }, "node_modules/@babel/template": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", - "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", - "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.8", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.8", - "@babel/types": "^7.24.8", - "debug": "^4.3.1", - "globals": "^11.1.0" + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" @@ -2300,15 +2341,6 @@ } } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/traverse/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -2316,14 +2348,14 @@ "dev": true }, "node_modules/@babel/types": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", - "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -3791,17 +3823,25 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -3813,15 +3853,6 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/source-map": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", @@ -3833,16 +3864,18 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -5119,6 +5152,13 @@ "win32" ] }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "dev": true, + "license": "MIT" + }, "node_modules/@sinclair/typebox": { "version": "0.24.51", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", @@ -12908,6 +12948,785 @@ "dev": true, "license": "MIT" }, + "node_modules/@stryker-mutator/api": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@stryker-mutator/api/-/api-9.6.0.tgz", + "integrity": "sha512-kJEEwOVoWDXGEIXuM+9efT6LSJ7nyxnQQvjEoKg8GSZXbDUjfD0tqA0aBD06U1SzQLKCM7ffjgPffr154MHZKw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "mutation-testing-metrics": "3.7.2", + "mutation-testing-report-schema": "3.7.2", + "tslib": "~2.8.0", + "typed-inject": "~5.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@stryker-mutator/core": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@stryker-mutator/core/-/core-9.6.0.tgz", + "integrity": "sha512-oSbw01l6HXHt0iW9x5fQj7yHGGT8ZjCkXSkI7Bsu0juO7Q6vRMXk7XcvKpCBgRgzKXi1osg8+iIzj7acHuxepQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@inquirer/prompts": "^8.0.0", + "@stryker-mutator/api": "9.6.0", + "@stryker-mutator/instrumenter": "9.6.0", + "@stryker-mutator/util": "9.6.0", + "ajv": "~8.18.0", + "chalk": "~5.6.0", + "commander": "~14.0.0", + "diff-match-patch": "1.0.5", + "emoji-regex": "~10.6.0", + "execa": "~9.6.0", + "json-rpc-2.0": "^1.7.0", + "lodash.groupby": "~4.6.0", + "minimatch": "~10.2.4", + "mutation-server-protocol": "~0.4.0", + "mutation-testing-elements": "3.7.2", + "mutation-testing-metrics": "3.7.2", + "mutation-testing-report-schema": "3.7.2", + "npm-run-path": "~6.0.0", + "progress": "~2.0.3", + "rxjs": "~7.8.1", + "semver": "^7.6.3", + "source-map": "~0.7.4", + "tree-kill": "~1.2.2", + "tslib": "2.8.1", + "typed-inject": "~5.0.0", + "typed-rest-client": "~2.2.0" + }, + "bin": { + "stryker": "bin/stryker.js" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/ansi": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-2.0.4.tgz", + "integrity": "sha512-DpcZrQObd7S0R/U3bFdkcT5ebRwbTTC4D3tCc1vsJizmgPLxNJBo+AAFmrZwe8zk30P2QzgzGWZ3Q9uJwWuhIg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/checkbox": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-5.1.2.tgz", + "integrity": "sha512-PubpMPO2nJgMufkoB3P2wwxNXEMUXnBIKi/ACzDUYfaoPuM7gSTmuxJeMscoLVEsR4qqrCMf5p0SiYGWnVJ8kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.4", + "@inquirer/core": "^11.1.7", + "@inquirer/figures": "^2.0.4", + "@inquirer/type": "^4.0.4" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/confirm": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-6.0.10.tgz", + "integrity": "sha512-tiNyA73pgpQ0FQ7axqtoLUe4GDYjNCDcVsbgcA5anvwg2z6i+suEngLKKJrWKJolT//GFPZHwN30binDIHgSgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^11.1.7", + "@inquirer/type": "^4.0.4" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/core": { + "version": "11.1.7", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-11.1.7.tgz", + "integrity": "sha512-1BiBNDk9btIwYIzNZpkikIHXWeNzNncJePPqwDyVMhXhD1ebqbpn1mKGctpoqAbzywZfdG0O4tvmsGIcOevAPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.4", + "@inquirer/figures": "^2.0.4", + "@inquirer/type": "^4.0.4", + "cli-width": "^4.1.0", + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/editor": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-5.0.10.tgz", + "integrity": "sha512-VJx4XyaKea7t8hEApTw5dxeIyMtWXre2OiyJcICCRZI4hkoHsMoCnl/KbUnJJExLbH9csLLHMVR144ZhFE1CwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^11.1.7", + "@inquirer/external-editor": "^2.0.4", + "@inquirer/type": "^4.0.4" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/expand": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-5.0.10.tgz", + "integrity": "sha512-fC0UHJPXsTRvY2fObiwuQYaAnHrp3aDqfwKUJSdfpgv18QUG054ezGbaRNStk/BKD5IPijeMKWej8VV8O5Q/eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^11.1.7", + "@inquirer/type": "^4.0.4" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/external-editor": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-2.0.4.tgz", + "integrity": "sha512-Prenuv9C1PHj2Itx0BcAOVBTonz02Hc2Nd2DbU67PdGUaqn0nPCnV34oDyyoaZHnmfRxkpuhh/u51ThkrO+RdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^2.1.1", + "iconv-lite": "^0.7.2" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/figures": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-2.0.4.tgz", + "integrity": "sha512-eLBsjlS7rPS3WEhmOmh1znQ5IsQrxWzxWDxO51e4urv+iVrSnIHbq4zqJIOiyNdYLa+BVjwOtdetcQx1lWPpiQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/input": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-5.0.10.tgz", + "integrity": "sha512-nvZ6qEVeX/zVtZ1dY2hTGDQpVGD3R7MYPLODPgKO8Y+RAqxkrP3i/3NwF3fZpLdaMiNuK0z2NaYIx9tPwiSegQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^11.1.7", + "@inquirer/type": "^4.0.4" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/number": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-4.0.10.tgz", + "integrity": "sha512-Ht8OQstxiS3APMGjHV0aYAjRAysidWdwurWEo2i8yI5xbhOBWqizT0+MU1S2GCcuhIBg+3SgWVjEoXgfhY+XaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^11.1.7", + "@inquirer/type": "^4.0.4" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/password": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-5.0.10.tgz", + "integrity": "sha512-QbNyvIE8q2GTqKLYSsA8ATG+eETo+m31DSR0+AU7x3d2FhaTWzqQek80dj3JGTo743kQc6mhBR0erMjYw5jQ0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.4", + "@inquirer/core": "^11.1.7", + "@inquirer/type": "^4.0.4" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/prompts": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-8.3.2.tgz", + "integrity": "sha512-yFroiSj2iiBFlm59amdTvAcQFvWS6ph5oKESls/uqPBect7rTU2GbjyZO2DqxMGuIwVA8z0P4K6ViPcd/cp+0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/checkbox": "^5.1.2", + "@inquirer/confirm": "^6.0.10", + "@inquirer/editor": "^5.0.10", + "@inquirer/expand": "^5.0.10", + "@inquirer/input": "^5.0.10", + "@inquirer/number": "^4.0.10", + "@inquirer/password": "^5.0.10", + "@inquirer/rawlist": "^5.2.6", + "@inquirer/search": "^4.1.6", + "@inquirer/select": "^5.1.2" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/rawlist": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-5.2.6.tgz", + "integrity": "sha512-jfw0MLJ5TilNsa9zlJ6nmRM0ZFVZhhTICt4/6CU2Dv1ndY7l3sqqo1gIYZyMMDw0LvE1u1nzJNisfHEhJIxq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^11.1.7", + "@inquirer/type": "^4.0.4" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/search": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-4.1.6.tgz", + "integrity": "sha512-3/6kTRae98hhDevENScy7cdFEuURnSpM3JbBNg8yfXLw88HgTOl+neUuy/l9W0No5NzGsLVydhBzTIxZP7yChQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^11.1.7", + "@inquirer/figures": "^2.0.4", + "@inquirer/type": "^4.0.4" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/select": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-5.1.2.tgz", + "integrity": "sha512-kTK8YIkHV+f02y7bWCh7E0u2/11lul5WepVTclr3UMBtBr05PgcZNWfMa7FY57ihpQFQH/spLMHTcr0rXy50tA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.4", + "@inquirer/core": "^11.1.7", + "@inquirer/figures": "^2.0.4", + "@inquirer/type": "^4.0.4" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@stryker-mutator/core/node_modules/@inquirer/type": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-4.0.4.tgz", + "integrity": "sha512-PamArxO3cFJZoOzspzo6cxVlLeIftyBsZw/S9bKY5DzxqJVZgjoj1oP8d0rskKtp7sZxBycsoer1g6UeJV1BBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@stryker-mutator/core/node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@stryker-mutator/core/node_modules/@types/node": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz", + "integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/@stryker-mutator/core/node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@stryker-mutator/core/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@stryker-mutator/core/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@stryker-mutator/core/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@stryker-mutator/core/node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@stryker-mutator/core/node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@stryker-mutator/core/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@stryker-mutator/core/node_modules/execa": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", + "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.6", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.1", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.2.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": "^18.19.0 || >=20.5.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@stryker-mutator/core/node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@stryker-mutator/core/node_modules/human-signals": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", + "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@stryker-mutator/core/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@stryker-mutator/core/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@stryker-mutator/core/node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@stryker-mutator/core/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/@stryker-mutator/core/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@stryker-mutator/core/node_modules/mute-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-3.0.0.tgz", + "integrity": "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@stryker-mutator/core/node_modules/npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@stryker-mutator/core/node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@stryker-mutator/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@stryker-mutator/core/node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@stryker-mutator/core/node_modules/strip-final-newline": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@stryker-mutator/core/node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@stryker-mutator/core/node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@stryker-mutator/instrumenter": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@stryker-mutator/instrumenter/-/instrumenter-9.6.0.tgz", + "integrity": "sha512-tWdRYfm9LF4Go7cNOos0xEIOEnN7ZOSj38rfXvGZS9IINlvYBrBCl2xcz/67v6l5A7xksMWWByZRIq2bgdnnUg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/core": "~7.29.0", + "@babel/generator": "~7.29.0", + "@babel/parser": "~7.29.0", + "@babel/plugin-proposal-decorators": "~7.29.0", + "@babel/plugin-transform-explicit-resource-management": "^7.28.0", + "@babel/preset-typescript": "~7.28.0", + "@stryker-mutator/api": "9.6.0", + "@stryker-mutator/util": "9.6.0", + "angular-html-parser": "~10.4.0", + "semver": "~7.7.0", + "tslib": "2.8.1", + "weapon-regex": "~1.3.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@stryker-mutator/jest-runner": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@stryker-mutator/jest-runner/-/jest-runner-9.6.0.tgz", + "integrity": "sha512-o98fwUe9VSXkHaiixAm3FJzQjUFAtZSkh6eWya79nCbqOV9mYQCMUmCN0apEVQZzKyW35FGVgjCohuFUQ9n+gQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@stryker-mutator/api": "9.6.0", + "@stryker-mutator/util": "9.6.0", + "semver": "~7.7.0", + "tslib": "~2.8.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@stryker-mutator/core": "9.6.0" + } + }, + "node_modules/@stryker-mutator/util": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@stryker-mutator/util/-/util-9.6.0.tgz", + "integrity": "sha512-gw7fJOFNHEj9inAEOodD9RrrMEMhZmWJ46Ww/kDJAXlSsBBmdwCzeomNLngmLTvgp14z7Tfq85DHYwvmNMdOxA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", @@ -13082,74 +13901,6 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@svgr/core/node_modules/@babel/core": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", - "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.24.5", - "@babel/helpers": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@svgr/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/@svgr/core/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@svgr/core/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@svgr/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@svgr/hast-util-to-babel-ast": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz", @@ -13201,74 +13952,6 @@ "@svgr/core": "^6.0.0" } }, - "node_modules/@svgr/plugin-jsx/node_modules/@babel/core": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", - "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.24.5", - "@babel/helpers": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@svgr/plugin-jsx/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/@svgr/plugin-jsx/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@svgr/plugin-jsx/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@svgr/plugin-jsx/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@svgr/plugin-svgo": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.5.1.tgz", @@ -16519,6 +17202,16 @@ "ajv": "^6.9.1" } }, + "node_modules/angular-html-parser": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/angular-html-parser/-/angular-html-parser-10.4.0.tgz", + "integrity": "sha512-++nLNyZwRfHqFh7akH5Gw/JYizoFlMRz0KRigfwfsLqV8ZqlcVRb1LkPEWdYvEKDnbktknM2J4BXaYUGrQZPww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -18021,6 +18714,19 @@ "node": "^4.5.0 || >= 5.9" } }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.11", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.11.tgz", + "integrity": "sha512-DAKrHphkJyiGuau/cFieRYhcTFeK/lBuD++C7cZ6KZHbMhBrisoi+EvhQ5RZrIfV5qwsW8kgQ07JIC+MDJRAhg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/basic-auth": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -18420,9 +19126,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { @@ -18438,11 +19144,13 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" @@ -18801,6 +19509,23 @@ "node": ">= 0.4" } }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/call-me-maybe": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", @@ -18899,9 +19624,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001612", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001612.tgz", - "integrity": "sha512-lFgnZ07UhaCcsSZgWW0K5j4e69dK1u/ltrL9lTUiFOwNHs12S3UMIEYgBV0Z6C6hRDev7iRnMzzYmKabYdXF9g==", + "version": "1.0.30001781", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001781.tgz", + "integrity": "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==", "dev": true, "funding": [ { @@ -18916,7 +19641,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/capture-exit": { "version": "2.0.0", @@ -19035,6 +19761,13 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/chardet": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", + "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", + "dev": true, + "license": "MIT" + }, "node_modules/check-error": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", @@ -21776,6 +22509,13 @@ "node": ">=0.3.1" } }, + "node_modules/diff-match-patch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", + "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/diff-sequences": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", @@ -22216,10 +22956,11 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.745", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.745.tgz", - "integrity": "sha512-tRbzkaRI5gbUn5DEvF0dV4TQbMZ5CLkWeTAXmpC9IrYT+GE+x76i9p+o3RJ5l9XmdQlI1pPhVtE9uNcJJ0G0EA==", - "dev": true + "version": "1.5.325", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.325.tgz", + "integrity": "sha512-PwfIw7WQSt3xX7yOf5OE/unLzsK9CaN2f/FvV3WjPR1Knoc1T9vePRVV4W1EM301JzzysK51K7FNKcusCr0zYA==", + "dev": true, + "license": "ISC" }, "node_modules/elliptic": { "version": "6.5.6", @@ -22781,10 +23522,11 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -24131,6 +24873,23 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-string-truncated-width": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz", + "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-string-width": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz", + "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-string-truncated-width": "^3.0.2" + } + }, "node_modules/fast-uri": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", @@ -24147,6 +24906,16 @@ } ] }, + "node_modules/fast-wrap-ansi": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.0.tgz", + "integrity": "sha512-rLV8JHxTyhVmFYhBJuMujcrHqOT2cnO5Zxj37qROj23CP39GXubJRBUFF0z8KFK77Uc0SukZUf7JZhsVEQ6n8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-string-width": "^3.0.2" + } + }, "node_modules/fast-xml-parser": { "version": "5.3.5", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.3.5.tgz", @@ -24253,6 +25022,35 @@ "deprecated": "This module is no longer supported.", "dev": true }, + "node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-unicode-supported": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -28834,6 +29632,13 @@ "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", "dev": true }, + "node_modules/js-md4": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/js-md4/-/js-md4-0.3.2.tgz", + "integrity": "sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==", + "dev": true, + "license": "MIT" + }, "node_modules/js-string-escape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", @@ -28963,15 +29768,16 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-buffer": { @@ -29001,6 +29807,13 @@ "jju": "^1.1.0" } }, + "node_modules/json-rpc-2.0": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/json-rpc-2.0/-/json-rpc-2.0-1.7.1.tgz", + "integrity": "sha512-JqZjhjAanbpkXIzFE7u8mE/iFblawwlXtONaCvRqI+pyABVz7B4M1EUNpyVW+dZjqgQ2L5HFmZCmOCgUKm00hg==", + "dev": true, + "license": "MIT" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -29597,6 +30410,13 @@ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, + "node_modules/lodash.groupby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", + "integrity": "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -30966,6 +31786,43 @@ "mustache": "bin/mustache" } }, + "node_modules/mutation-server-protocol": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mutation-server-protocol/-/mutation-server-protocol-0.4.1.tgz", + "integrity": "sha512-SBGK0j8hLDne7bktgThKI8kGvGTx3rY3LAeQTmOKZ5bVnL/7TorLMvcVF7dIPJCu5RNUWhkkuF53kurygYVt3g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "zod": "^4.1.12" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/mutation-testing-elements": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/mutation-testing-elements/-/mutation-testing-elements-3.7.2.tgz", + "integrity": "sha512-i7X2Q4X5eYon72W2QQ9HND7plVhQcqTnv+Xc3KeYslRZSJ4WYJoal8LFdbWm7dKWLNE0rYkCUrvboasWzF3MMA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/mutation-testing-metrics": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/mutation-testing-metrics/-/mutation-testing-metrics-3.7.2.tgz", + "integrity": "sha512-ichXZSC4FeJbcVHYOWzWUhNuTJGogc0WiQol8lqEBrBSp+ADl3fmcZMqrx0ogInEUiImn+A8JyTk6uh9vd25TQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "mutation-testing-report-schema": "3.7.2" + } + }, + "node_modules/mutation-testing-report-schema": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/mutation-testing-report-schema/-/mutation-testing-report-schema-3.7.2.tgz", + "integrity": "sha512-fN5M61SDzIOeJyatMOhGPLDOFz5BQIjTNPjo4PcHIEUWrejO4i4B5PFuQ/2l43709hEsTxeiXX00H73WERKcDw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/mute-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", @@ -31220,10 +32077,11 @@ } }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "dev": true, + "license": "MIT" }, "node_modules/normalize-package-data": { "version": "3.0.3", @@ -31450,10 +32308,14 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -32229,6 +33091,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", @@ -32917,6 +33792,22 @@ "node": ">= 0.8" } }, + "node_modules/pretty-ms": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", + "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -35906,15 +36797,73 @@ } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -39154,10 +40103,11 @@ } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" }, "node_modules/tsutils": { "version": "3.21.0", @@ -39186,6 +40136,16 @@ "integrity": "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==", "dev": true }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -39305,6 +40265,49 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/typed-inject": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/typed-inject/-/typed-inject-5.0.0.tgz", + "integrity": "sha512-0Ql2ORqBORLMdAW89TQKZsb1PQkFGImFfVmncXWe7a+AA3+7dh7Se9exxZowH4kbnlvKEFkMxUYdHUpjYWFJaA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/typed-rest-client": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-2.2.0.tgz", + "integrity": "sha512-/e2Rk9g20N0r44kaQLb3v6QGuryOD8SPb53t43Y5kqXXA+SqWuU7zLiMxetw61jNn/JFrxTdr5nPDhGY/eTNhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "des.js": "^1.1.0", + "js-md4": "^0.3.2", + "qs": "^6.14.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" + }, + "engines": { + "node": ">= 16.0.0" + } + }, + "node_modules/typed-rest-client/node_modules/qs": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -39425,6 +40428,13 @@ "ieee754": "^1.1.13" } }, + "node_modules/underscore": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", + "dev": true, + "license": "MIT" + }, "node_modules/undici": { "version": "6.12.0", "resolved": "https://registry.npmjs.org/undici/-/undici-6.12.0.tgz", @@ -39795,9 +40805,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -39813,9 +40823,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -40610,6 +41621,13 @@ "defaults": "^1.0.3" } }, + "node_modules/weapon-regex": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/weapon-regex/-/weapon-regex-1.3.6.tgz", + "integrity": "sha512-wsf1m1jmMrso5nhwVFJJHSubEBf3+pereGd7+nBKtYJ18KoB/PWJOHS3WRkwS04VrOU0iJr2bZU+l1QaTJ+9nA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/web-namespaces": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", @@ -41692,6 +42710,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yoctocolors": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", + "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/yoctocolors-cjs": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", @@ -41774,6 +42805,16 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/zwitch": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", @@ -41793,55 +42834,52 @@ "dev": true, "peer": true }, - "@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, "@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, "requires": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" } }, "@babel/compat-data": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", - "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", "dev": true }, "@babel/core": { - "version": "7.17.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz", - "integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helpers": "^7.17.2", - "@babel/parser": "^7.17.3", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "dependencies": { + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -41866,24 +42904,25 @@ } }, "@babel/generator": { - "version": "7.24.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.10.tgz", - "integrity": "sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==", + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "dev": true, "requires": { - "@babel/types": "^7.24.9", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" } }, "@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", "dev": true, "requires": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.27.3" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { @@ -41896,14 +42935,14 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "dev": true, "requires": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -41932,19 +42971,17 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", - "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", + "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.6", "semver": "^6.3.1" }, "dependencies": { @@ -42031,6 +43068,12 @@ "@babel/types": "^7.24.7" } }, + "@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true + }, "@babel/helper-hoist-variables": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", @@ -42041,50 +43084,49 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", - "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", "dev": true, "requires": { - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.8" + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" } }, "@babel/helper-module-imports": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", - "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "dev": true, "requires": { - "@babel/types": "^7.24.0" + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" } }, "@babel/helper-module-transforms": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", - "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.24.3", - "@babel/helper-simple-access": "^7.24.5", - "@babel/helper-split-export-declaration": "^7.24.5", - "@babel/helper-validator-identifier": "^7.24.5" + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" } }, "@babel/helper-optimise-call-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", - "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", "dev": true, "requires": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.27.1" } }, "@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "dev": true }, "@babel/helper-remap-async-to-generator": { @@ -42099,33 +43141,24 @@ } }, "@babel/helper-replace-supers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", - "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.7", - "@babel/helper-optimise-call-expression": "^7.24.7" - } - }, - "@babel/helper-simple-access": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", - "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", + "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", "dev": true, "requires": { - "@babel/types": "^7.24.5" + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.28.6" } }, "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", - "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", "dev": true, "requires": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" } }, "@babel/helper-split-export-declaration": { @@ -42138,21 +43171,21 @@ } }, "@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true }, "@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true }, "@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true }, "@babel/helper-wrap-function": { @@ -42167,14 +43200,13 @@ } }, "@babel/helpers": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", - "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", "dev": true, "requires": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5" + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" } }, "@babel/highlight": { @@ -42242,10 +43274,13 @@ } }, "@babel/parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", - "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", - "dev": true + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "dev": true, + "requires": { + "@babel/types": "^7.29.0" + } }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.24.1", @@ -42301,14 +43336,14 @@ } }, "@babel/plugin-proposal-decorators": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.7.tgz", - "integrity": "sha512-RL9GR0pUG5Kc8BUWLNDm2T5OpYwSX15r98I0IkgmRQTXuELq/OynH8xtMTMvTJFjXbMWFVTKtYkTaYQsuAwQlQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.29.0.tgz", + "integrity": "sha512-CVBVv3VY/XRMxRYq5dwr2DS7/MvqPm23cOCjbwNnVrfOqcWlnefua1uUs0sjdKOGjvPUG633o07uWzJq4oI6dA==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-decorators": "^7.24.7" + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-syntax-decorators": "^7.28.6" } }, "@babel/plugin-proposal-dynamic-import": { @@ -42484,12 +43519,12 @@ } }, "@babel/plugin-syntax-decorators": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.7.tgz", - "integrity": "sha512-Ui4uLJJrRV1lb38zg1yYTmRKmiZLiftDEvZN2iq3kd9kUFU+PttmzTbAFC2ucRk/XJmtek6G23gPsuZbhrT8fQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.28.6.tgz", + "integrity": "sha512-71EYI0ONURHJBL4rSFXnITXqXrrY8q4P0q006DPfN+Rk+ASM+++IBXem/ruokgBZR8YNEWZ8R6B+rCb8VcUTqA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.28.6" } }, "@babel/plugin-syntax-dynamic-import": { @@ -42547,12 +43582,12 @@ } }, "@babel/plugin-syntax-jsx": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", - "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.28.6" } }, "@babel/plugin-syntax-logical-assignment-operators": { @@ -42628,12 +43663,12 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", - "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.28.6" } }, "@babel/plugin-transform-arrow-functions": { @@ -42709,12 +43744,13 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz", - "integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", + "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" } }, "@babel/plugin-transform-dotall-regex": { @@ -42736,6 +43772,16 @@ "@babel/helper-plugin-utils": "^7.24.0" } }, + "@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", + "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5" + } + }, "@babel/plugin-transform-exponentiation-operator": { "version": "7.24.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz", @@ -42806,14 +43852,13 @@ } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", - "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", + "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-simple-access": "^7.22.5" + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" } }, "@babel/plugin-transform-modules-systemjs": { @@ -43012,15 +44057,16 @@ } }, "@babel/plugin-transform-typescript": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.4.tgz", - "integrity": "sha512-79t3CQ8+oBGk/80SQ8MN3Bs3obf83zJ0YZjDmDaEZN8MqhMI760apl5z6a20kFeMXBwJX99VpKT8CKxEBp5H1g==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.6.tgz", + "integrity": "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.24.4", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-typescript": "^7.24.1" + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.28.6" } }, "@babel/plugin-transform-unicode-escapes": { @@ -43171,14 +44217,16 @@ } }, "@babel/preset-typescript": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz", - "integrity": "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz", + "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-transform-typescript": "^7.16.7" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.28.5" } }, "@babel/register": { @@ -43281,32 +44329,29 @@ } }, "@babel/template": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", - "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" } }, "@babel/traverse": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", - "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.8", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.8", - "@babel/types": "^7.24.8", - "debug": "^4.3.1", - "globals": "^11.1.0" + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" }, "dependencies": { "debug": { @@ -43318,12 +44363,6 @@ "ms": "2.1.2" } }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -43333,14 +44372,13 @@ } }, "@babel/types": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", - "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, "requires": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" } }, "@base2/pretty-print-object": { @@ -44284,13 +45322,22 @@ } }, "@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "requires": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, @@ -44300,12 +45347,6 @@ "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true }, - "@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true - }, "@jridgewell/source-map": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", @@ -44317,15 +45358,15 @@ } }, "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.1.0", @@ -45192,6 +46233,12 @@ "dev": true, "optional": true }, + "@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "dev": true + }, "@sinclair/typebox": { "version": "0.24.51", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", @@ -50958,6 +52005,462 @@ } } }, + "@stryker-mutator/api": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@stryker-mutator/api/-/api-9.6.0.tgz", + "integrity": "sha512-kJEEwOVoWDXGEIXuM+9efT6LSJ7nyxnQQvjEoKg8GSZXbDUjfD0tqA0aBD06U1SzQLKCM7ffjgPffr154MHZKw==", + "dev": true, + "requires": { + "mutation-testing-metrics": "3.7.2", + "mutation-testing-report-schema": "3.7.2", + "tslib": "~2.8.0", + "typed-inject": "~5.0.0" + } + }, + "@stryker-mutator/core": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@stryker-mutator/core/-/core-9.6.0.tgz", + "integrity": "sha512-oSbw01l6HXHt0iW9x5fQj7yHGGT8ZjCkXSkI7Bsu0juO7Q6vRMXk7XcvKpCBgRgzKXi1osg8+iIzj7acHuxepQ==", + "dev": true, + "requires": { + "@inquirer/prompts": "^8.0.0", + "@stryker-mutator/api": "9.6.0", + "@stryker-mutator/instrumenter": "9.6.0", + "@stryker-mutator/util": "9.6.0", + "ajv": "~8.18.0", + "chalk": "~5.6.0", + "commander": "~14.0.0", + "diff-match-patch": "1.0.5", + "emoji-regex": "~10.6.0", + "execa": "~9.6.0", + "json-rpc-2.0": "^1.7.0", + "lodash.groupby": "~4.6.0", + "minimatch": "~10.2.4", + "mutation-server-protocol": "~0.4.0", + "mutation-testing-elements": "3.7.2", + "mutation-testing-metrics": "3.7.2", + "mutation-testing-report-schema": "3.7.2", + "npm-run-path": "~6.0.0", + "progress": "~2.0.3", + "rxjs": "~7.8.1", + "semver": "^7.6.3", + "source-map": "~0.7.4", + "tree-kill": "~1.2.2", + "tslib": "2.8.1", + "typed-inject": "~5.0.0", + "typed-rest-client": "~2.2.0" + }, + "dependencies": { + "@inquirer/ansi": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-2.0.4.tgz", + "integrity": "sha512-DpcZrQObd7S0R/U3bFdkcT5ebRwbTTC4D3tCc1vsJizmgPLxNJBo+AAFmrZwe8zk30P2QzgzGWZ3Q9uJwWuhIg==", + "dev": true + }, + "@inquirer/checkbox": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-5.1.2.tgz", + "integrity": "sha512-PubpMPO2nJgMufkoB3P2wwxNXEMUXnBIKi/ACzDUYfaoPuM7gSTmuxJeMscoLVEsR4qqrCMf5p0SiYGWnVJ8kw==", + "dev": true, + "requires": { + "@inquirer/ansi": "^2.0.4", + "@inquirer/core": "^11.1.7", + "@inquirer/figures": "^2.0.4", + "@inquirer/type": "^4.0.4" + } + }, + "@inquirer/confirm": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-6.0.10.tgz", + "integrity": "sha512-tiNyA73pgpQ0FQ7axqtoLUe4GDYjNCDcVsbgcA5anvwg2z6i+suEngLKKJrWKJolT//GFPZHwN30binDIHgSgQ==", + "dev": true, + "requires": { + "@inquirer/core": "^11.1.7", + "@inquirer/type": "^4.0.4" + } + }, + "@inquirer/core": { + "version": "11.1.7", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-11.1.7.tgz", + "integrity": "sha512-1BiBNDk9btIwYIzNZpkikIHXWeNzNncJePPqwDyVMhXhD1ebqbpn1mKGctpoqAbzywZfdG0O4tvmsGIcOevAPQ==", + "dev": true, + "requires": { + "@inquirer/ansi": "^2.0.4", + "@inquirer/figures": "^2.0.4", + "@inquirer/type": "^4.0.4", + "cli-width": "^4.1.0", + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" + } + }, + "@inquirer/editor": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-5.0.10.tgz", + "integrity": "sha512-VJx4XyaKea7t8hEApTw5dxeIyMtWXre2OiyJcICCRZI4hkoHsMoCnl/KbUnJJExLbH9csLLHMVR144ZhFE1CwA==", + "dev": true, + "requires": { + "@inquirer/core": "^11.1.7", + "@inquirer/external-editor": "^2.0.4", + "@inquirer/type": "^4.0.4" + } + }, + "@inquirer/expand": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-5.0.10.tgz", + "integrity": "sha512-fC0UHJPXsTRvY2fObiwuQYaAnHrp3aDqfwKUJSdfpgv18QUG054ezGbaRNStk/BKD5IPijeMKWej8VV8O5Q/eQ==", + "dev": true, + "requires": { + "@inquirer/core": "^11.1.7", + "@inquirer/type": "^4.0.4" + } + }, + "@inquirer/external-editor": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-2.0.4.tgz", + "integrity": "sha512-Prenuv9C1PHj2Itx0BcAOVBTonz02Hc2Nd2DbU67PdGUaqn0nPCnV34oDyyoaZHnmfRxkpuhh/u51ThkrO+RdA==", + "dev": true, + "requires": { + "chardet": "^2.1.1", + "iconv-lite": "^0.7.2" + } + }, + "@inquirer/figures": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-2.0.4.tgz", + "integrity": "sha512-eLBsjlS7rPS3WEhmOmh1znQ5IsQrxWzxWDxO51e4urv+iVrSnIHbq4zqJIOiyNdYLa+BVjwOtdetcQx1lWPpiQ==", + "dev": true + }, + "@inquirer/input": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-5.0.10.tgz", + "integrity": "sha512-nvZ6qEVeX/zVtZ1dY2hTGDQpVGD3R7MYPLODPgKO8Y+RAqxkrP3i/3NwF3fZpLdaMiNuK0z2NaYIx9tPwiSegQ==", + "dev": true, + "requires": { + "@inquirer/core": "^11.1.7", + "@inquirer/type": "^4.0.4" + } + }, + "@inquirer/number": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-4.0.10.tgz", + "integrity": "sha512-Ht8OQstxiS3APMGjHV0aYAjRAysidWdwurWEo2i8yI5xbhOBWqizT0+MU1S2GCcuhIBg+3SgWVjEoXgfhY+XaA==", + "dev": true, + "requires": { + "@inquirer/core": "^11.1.7", + "@inquirer/type": "^4.0.4" + } + }, + "@inquirer/password": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-5.0.10.tgz", + "integrity": "sha512-QbNyvIE8q2GTqKLYSsA8ATG+eETo+m31DSR0+AU7x3d2FhaTWzqQek80dj3JGTo743kQc6mhBR0erMjYw5jQ0A==", + "dev": true, + "requires": { + "@inquirer/ansi": "^2.0.4", + "@inquirer/core": "^11.1.7", + "@inquirer/type": "^4.0.4" + } + }, + "@inquirer/prompts": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-8.3.2.tgz", + "integrity": "sha512-yFroiSj2iiBFlm59amdTvAcQFvWS6ph5oKESls/uqPBect7rTU2GbjyZO2DqxMGuIwVA8z0P4K6ViPcd/cp+0w==", + "dev": true, + "requires": { + "@inquirer/checkbox": "^5.1.2", + "@inquirer/confirm": "^6.0.10", + "@inquirer/editor": "^5.0.10", + "@inquirer/expand": "^5.0.10", + "@inquirer/input": "^5.0.10", + "@inquirer/number": "^4.0.10", + "@inquirer/password": "^5.0.10", + "@inquirer/rawlist": "^5.2.6", + "@inquirer/search": "^4.1.6", + "@inquirer/select": "^5.1.2" + } + }, + "@inquirer/rawlist": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-5.2.6.tgz", + "integrity": "sha512-jfw0MLJ5TilNsa9zlJ6nmRM0ZFVZhhTICt4/6CU2Dv1ndY7l3sqqo1gIYZyMMDw0LvE1u1nzJNisfHEhJIxq5w==", + "dev": true, + "requires": { + "@inquirer/core": "^11.1.7", + "@inquirer/type": "^4.0.4" + } + }, + "@inquirer/search": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-4.1.6.tgz", + "integrity": "sha512-3/6kTRae98hhDevENScy7cdFEuURnSpM3JbBNg8yfXLw88HgTOl+neUuy/l9W0No5NzGsLVydhBzTIxZP7yChQ==", + "dev": true, + "requires": { + "@inquirer/core": "^11.1.7", + "@inquirer/figures": "^2.0.4", + "@inquirer/type": "^4.0.4" + } + }, + "@inquirer/select": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-5.1.2.tgz", + "integrity": "sha512-kTK8YIkHV+f02y7bWCh7E0u2/11lul5WepVTclr3UMBtBr05PgcZNWfMa7FY57ihpQFQH/spLMHTcr0rXy50tA==", + "dev": true, + "requires": { + "@inquirer/ansi": "^2.0.4", + "@inquirer/core": "^11.1.7", + "@inquirer/figures": "^2.0.4", + "@inquirer/type": "^4.0.4" + } + }, + "@inquirer/type": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-4.0.4.tgz", + "integrity": "sha512-PamArxO3cFJZoOzspzo6cxVlLeIftyBsZw/S9bKY5DzxqJVZgjoj1oP8d0rskKtp7sZxBycsoer1g6UeJV1BBA==", + "dev": true, + "requires": {} + }, + "@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true + }, + "@types/node": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz", + "integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "undici-types": "~7.18.0" + } + }, + "ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + } + }, + "balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true + }, + "brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "requires": { + "balanced-match": "^4.0.2" + } + }, + "chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true + }, + "commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true + }, + "execa": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", + "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==", + "dev": true, + "requires": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.6", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.1", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.2.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.1.1" + } + }, + "get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "dev": true, + "requires": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + } + }, + "human-signals": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", + "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", + "dev": true + }, + "iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true + }, + "is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "dev": true + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "requires": { + "brace-expansion": "^5.0.2" + } + }, + "mute-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-3.0.0.tgz", + "integrity": "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==", + "dev": true + }, + "npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", + "dev": true, + "requires": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, + "dependencies": { + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + } + } + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "dev": true + }, + "strip-final-newline": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", + "dev": true + }, + "undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, + "optional": true, + "peer": true + }, + "unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true + } + } + }, + "@stryker-mutator/instrumenter": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@stryker-mutator/instrumenter/-/instrumenter-9.6.0.tgz", + "integrity": "sha512-tWdRYfm9LF4Go7cNOos0xEIOEnN7ZOSj38rfXvGZS9IINlvYBrBCl2xcz/67v6l5A7xksMWWByZRIq2bgdnnUg==", + "dev": true, + "requires": { + "@babel/core": "~7.29.0", + "@babel/generator": "~7.29.0", + "@babel/parser": "~7.29.0", + "@babel/plugin-proposal-decorators": "~7.29.0", + "@babel/plugin-transform-explicit-resource-management": "^7.28.0", + "@babel/preset-typescript": "~7.28.0", + "@stryker-mutator/api": "9.6.0", + "@stryker-mutator/util": "9.6.0", + "angular-html-parser": "~10.4.0", + "semver": "~7.7.0", + "tslib": "2.8.1", + "weapon-regex": "~1.3.2" + } + }, + "@stryker-mutator/jest-runner": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@stryker-mutator/jest-runner/-/jest-runner-9.6.0.tgz", + "integrity": "sha512-o98fwUe9VSXkHaiixAm3FJzQjUFAtZSkh6eWya79nCbqOV9mYQCMUmCN0apEVQZzKyW35FGVgjCohuFUQ9n+gQ==", + "dev": true, + "requires": { + "@stryker-mutator/api": "9.6.0", + "@stryker-mutator/util": "9.6.0", + "semver": "~7.7.0", + "tslib": "~2.8.0" + } + }, + "@stryker-mutator/util": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@stryker-mutator/util/-/util-9.6.0.tgz", + "integrity": "sha512-gw7fJOFNHEj9inAEOodD9RrrMEMhZmWJ46Ww/kDJAXlSsBBmdwCzeomNLngmLTvgp14z7Tfq85DHYwvmNMdOxA==", + "dev": true + }, "@svgr/babel-plugin-add-jsx-attribute": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", @@ -51041,58 +52544,6 @@ "@svgr/plugin-jsx": "^6.5.1", "camelcase": "^6.2.0", "cosmiconfig": "^7.0.1" - }, - "dependencies": { - "@babel/core": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", - "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.24.5", - "@babel/helpers": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - } - }, - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } } }, "@svgr/hast-util-to-babel-ast": { @@ -51123,58 +52574,6 @@ "@svgr/babel-preset": "^6.5.1", "@svgr/hast-util-to-babel-ast": "^6.5.1", "svg-parser": "^2.0.4" - }, - "dependencies": { - "@babel/core": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", - "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.24.5", - "@babel/helpers": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - } - }, - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } } }, "@svgr/plugin-svgo": { @@ -53656,6 +55055,12 @@ "dev": true, "requires": {} }, + "angular-html-parser": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/angular-html-parser/-/angular-html-parser-10.4.0.tgz", + "integrity": "sha512-++nLNyZwRfHqFh7akH5Gw/JYizoFlMRz0KRigfwfsLqV8ZqlcVRb1LkPEWdYvEKDnbktknM2J4BXaYUGrQZPww==", + "dev": true + }, "ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -54759,6 +56164,12 @@ "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", "dev": true }, + "baseline-browser-mapping": { + "version": "2.10.11", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.11.tgz", + "integrity": "sha512-DAKrHphkJyiGuau/cFieRYhcTFeK/lBuD++C7cZ6KZHbMhBrisoi+EvhQ5RZrIfV5qwsW8kgQ07JIC+MDJRAhg==", + "dev": true + }, "basic-auth": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -55107,15 +56518,16 @@ } }, "browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" } }, "bser": { @@ -55387,6 +56799,16 @@ "function-bind": "^1.1.2" } }, + "call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + } + }, "call-me-maybe": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", @@ -55459,9 +56881,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001612", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001612.tgz", - "integrity": "sha512-lFgnZ07UhaCcsSZgWW0K5j4e69dK1u/ltrL9lTUiFOwNHs12S3UMIEYgBV0Z6C6hRDev7iRnMzzYmKabYdXF9g==", + "version": "1.0.30001781", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001781.tgz", + "integrity": "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==", "dev": true }, "capture-exit": { @@ -55544,6 +56966,12 @@ "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", "dev": true }, + "chardet": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", + "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", + "dev": true + }, "check-error": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", @@ -57588,6 +59016,12 @@ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, + "diff-match-patch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", + "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==", + "dev": true + }, "diff-sequences": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", @@ -57928,9 +59362,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.4.745", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.745.tgz", - "integrity": "sha512-tRbzkaRI5gbUn5DEvF0dV4TQbMZ5CLkWeTAXmpC9IrYT+GE+x76i9p+o3RJ5l9XmdQlI1pPhVtE9uNcJJ0G0EA==", + "version": "1.5.325", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.325.tgz", + "integrity": "sha512-PwfIw7WQSt3xX7yOf5OE/unLzsK9CaN2f/FvV3WjPR1Knoc1T9vePRVV4W1EM301JzzysK51K7FNKcusCr0zYA==", "dev": true }, "elliptic": { @@ -58363,9 +59797,9 @@ } }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true }, "escape-goat": { @@ -59393,12 +60827,36 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "fast-string-truncated-width": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz", + "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==", + "dev": true + }, + "fast-string-width": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz", + "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==", + "dev": true, + "requires": { + "fast-string-truncated-width": "^3.0.2" + } + }, "fast-uri": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", "dev": true }, + "fast-wrap-ansi": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.0.tgz", + "integrity": "sha512-rLV8JHxTyhVmFYhBJuMujcrHqOT2cnO5Zxj37qROj23CP39GXubJRBUFF0z8KFK77Uc0SukZUf7JZhsVEQ6n8w==", + "dev": true, + "requires": { + "fast-string-width": "^3.0.2" + } + }, "fast-xml-parser": { "version": "5.3.5", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.3.5.tgz", @@ -59472,6 +60930,23 @@ "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", "dev": true }, + "figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "dev": true, + "requires": { + "is-unicode-supported": "^2.0.0" + }, + "dependencies": { + "is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true + } + } + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -62785,6 +64260,12 @@ "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", "dev": true }, + "js-md4": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/js-md4/-/js-md4-0.3.2.tgz", + "integrity": "sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==", + "dev": true + }, "js-string-escape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", @@ -62876,9 +64357,9 @@ } }, "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true }, "json-buffer": { @@ -62908,6 +64389,12 @@ "jju": "^1.1.0" } }, + "json-rpc-2.0": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/json-rpc-2.0/-/json-rpc-2.0-1.7.1.tgz", + "integrity": "sha512-JqZjhjAanbpkXIzFE7u8mE/iFblawwlXtONaCvRqI+pyABVz7B4M1EUNpyVW+dZjqgQ2L5HFmZCmOCgUKm00hg==", + "dev": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -63376,6 +64863,12 @@ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, + "lodash.groupby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", + "integrity": "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==", + "dev": true + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -64405,6 +65898,36 @@ "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", "dev": true }, + "mutation-server-protocol": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mutation-server-protocol/-/mutation-server-protocol-0.4.1.tgz", + "integrity": "sha512-SBGK0j8hLDne7bktgThKI8kGvGTx3rY3LAeQTmOKZ5bVnL/7TorLMvcVF7dIPJCu5RNUWhkkuF53kurygYVt3g==", + "dev": true, + "requires": { + "zod": "^4.1.12" + } + }, + "mutation-testing-elements": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/mutation-testing-elements/-/mutation-testing-elements-3.7.2.tgz", + "integrity": "sha512-i7X2Q4X5eYon72W2QQ9HND7plVhQcqTnv+Xc3KeYslRZSJ4WYJoal8LFdbWm7dKWLNE0rYkCUrvboasWzF3MMA==", + "dev": true + }, + "mutation-testing-metrics": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/mutation-testing-metrics/-/mutation-testing-metrics-3.7.2.tgz", + "integrity": "sha512-ichXZSC4FeJbcVHYOWzWUhNuTJGogc0WiQol8lqEBrBSp+ADl3fmcZMqrx0ogInEUiImn+A8JyTk6uh9vd25TQ==", + "dev": true, + "requires": { + "mutation-testing-report-schema": "3.7.2" + } + }, + "mutation-testing-report-schema": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/mutation-testing-report-schema/-/mutation-testing-report-schema-3.7.2.tgz", + "integrity": "sha512-fN5M61SDzIOeJyatMOhGPLDOFz5BQIjTNPjo4PcHIEUWrejO4i4B5PFuQ/2l43709hEsTxeiXX00H73WERKcDw==", + "dev": true + }, "mute-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", @@ -64600,9 +66123,9 @@ } }, "node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", "dev": true }, "normalize-package-data": { @@ -64778,9 +66301,9 @@ } }, "object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true }, "object-is": { @@ -65362,6 +66885,12 @@ "lines-and-columns": "^1.1.6" } }, + "parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "dev": true + }, "parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", @@ -65843,6 +67372,15 @@ "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", "dev": true }, + "pretty-ms": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", + "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==", + "dev": true, + "requires": { + "parse-ms": "^4.0.0" + } + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -68066,15 +69604,51 @@ } }, "side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "requires": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + } + }, + "side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + } + }, + "side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + } + }, + "side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" } }, "signal-exit": { @@ -70359,9 +71933,9 @@ } }, "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true }, "tsutils": { @@ -70387,6 +71961,12 @@ "integrity": "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==", "dev": true }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -70470,6 +72050,36 @@ "possible-typed-array-names": "^1.0.0" } }, + "typed-inject": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/typed-inject/-/typed-inject-5.0.0.tgz", + "integrity": "sha512-0Ql2ORqBORLMdAW89TQKZsb1PQkFGImFfVmncXWe7a+AA3+7dh7Se9exxZowH4kbnlvKEFkMxUYdHUpjYWFJaA==", + "dev": true + }, + "typed-rest-client": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-2.2.0.tgz", + "integrity": "sha512-/e2Rk9g20N0r44kaQLb3v6QGuryOD8SPb53t43Y5kqXXA+SqWuU7zLiMxetw61jNn/JFrxTdr5nPDhGY/eTNhQ==", + "dev": true, + "requires": { + "des.js": "^1.1.0", + "js-md4": "^0.3.2", + "qs": "^6.14.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" + }, + "dependencies": { + "qs": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "dev": true, + "requires": { + "side-channel": "^1.1.0" + } + } + } + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -70538,6 +72148,12 @@ } } }, + "underscore": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", + "dev": true + }, "undici": { "version": "6.12.0", "resolved": "https://registry.npmjs.org/undici/-/undici-6.12.0.tgz", @@ -70811,13 +72427,13 @@ "optional": true }, "update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" } }, "update-notifier": { @@ -71469,6 +73085,12 @@ "defaults": "^1.0.3" } }, + "weapon-regex": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/weapon-regex/-/weapon-regex-1.3.6.tgz", + "integrity": "sha512-wsf1m1jmMrso5nhwVFJJHSubEBf3+pereGd7+nBKtYJ18KoB/PWJOHS3WRkwS04VrOU0iJr2bZU+l1QaTJ+9nA==", + "dev": true + }, "web-namespaces": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", @@ -72254,6 +73876,12 @@ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true }, + "yoctocolors": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", + "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", + "dev": true + }, "yoctocolors-cjs": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", @@ -72305,6 +73933,12 @@ } } }, + "zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "dev": true + }, "zwitch": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", diff --git a/package.json b/package.json index 9abd5b71..98023a2e 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,8 @@ "@storybook/manager-webpack5": "^6.5.16", "@storybook/react": "^6.5.16", "@storybook/testing-library": "^0.0.13", + "@stryker-mutator/core": "^9.6.0", + "@stryker-mutator/jest-runner": "^9.6.0", "@svgr/webpack": "^6.2.1", "@swc/core": "^1.15.11", "@testing-library/jest-dom": "^5.16.2", diff --git a/stryker.config.mjs b/stryker.config.mjs new file mode 100644 index 00000000..451f425b --- /dev/null +++ b/stryker.config.mjs @@ -0,0 +1,15 @@ +// @ts-check +/** @type {import('@stryker-mutator/api/core').PartialStrykerOptions} */ +const config = { + _comment: + // eslint-disable-next-line max-len + "This config was generated using 'stryker init'. Please take a look at: https://stryker-mutator.io/docs/stryker-js/configuration/ for more information.", + packageManager: 'npm', + reporters: ['html', 'clear-text', 'progress'], + testRunner: 'jest', + + testRunner_comment: + 'Take a look at https://stryker-mutator.io/docs/stryker-js/jest-runner for information about the jest plugin.', + coverageAnalysis: 'perTest', +}; +export default config;