diff --git a/lib/adapters/config/playwright.ts b/lib/adapters/config/playwright.ts new file mode 100644 index 000000000..70114236f --- /dev/null +++ b/lib/adapters/config/playwright.ts @@ -0,0 +1,121 @@ +import path from 'node:path'; +import crypto from 'node:crypto'; +import _ from 'lodash'; + +import type {ConfigAdapter, BrowserConfigAdapter} from './index'; +import type {FullConfig, FullProject} from '@playwright/test/reporter'; +import type {TestAdapter} from '../test'; + +export type PwtProject = FullProject & { + snapshotPathTemplate?: string; +}; + +export type PwtConfig = FullConfig & { + testDir?: string; + snapshotDir?: string; + snapshotPathTemplate?: string; + projects?: PwtProject[] +} + +export const DEFAULT_BROWSER_ID = 'chromium'; +const DEFAULT_SNAPSHOT_PATH_TEMPLATE = '{snapshotDir}/{testFileDir}/{testFileName}-snapshots/{arg}{-projectName}{-snapshotSuffix}{ext}'; + +export class PlaywrightConfigAdapter implements ConfigAdapter { + private _config: PwtConfig; + private _browserIds: string[]; + + static create(this: new (config: PwtConfig) => T, config: PwtConfig): T { + return new this(config); + } + + constructor(config: PwtConfig) { + this._config = config; + this._browserIds = _.isEmpty(this._config.projects) ? [DEFAULT_BROWSER_ID] : this._config.projects.map(prj => prj.name).filter(Boolean); + } + + get original(): PwtConfig { + return this._config; + } + + get tolerance(): number { + return 2.3; + } + + get antialiasingTolerance(): number { + return 4; + } + + getScreenshotPath(test: TestAdapter, stateName: string): string { + const subPath = `${stateName}.png`; + const parsedSubPath = path.parse(subPath); + const parsedRelativeTestFilePath = path.parse(test.file); + + const currProject = (this._config.projects || []).find(prj => prj.name === test.browserId) as PwtProject || {}; + const projectNamePathSegment = sanitizeForFilePath(test.browserId); + + const snapshotPathTemplate = currProject.snapshotPathTemplate || this._config.snapshotPathTemplate || DEFAULT_SNAPSHOT_PATH_TEMPLATE; + + const testDir = path.resolve(currProject.testDir || this._config.testDir || ''); + let snapshotDir = currProject.snapshotDir || this._config.snapshotDir; + snapshotDir = snapshotDir ? path.resolve(snapshotDir) : testDir; + + const snapshotSuffix = process.platform; + + const snapshotPath = snapshotPathTemplate + .replace(/\{(.)?testDir\}/g, '$1' + testDir) + .replace(/\{(.)?snapshotDir\}/g, '$1' + snapshotDir) + .replace(/\{(.)?snapshotSuffix\}/g, snapshotSuffix ? '$1' + snapshotSuffix : '') + .replace(/\{(.)?testFileDir\}/g, '$1' + parsedRelativeTestFilePath.dir) + .replace(/\{(.)?platform\}/g, '$1' + process.platform) + .replace(/\{(.)?projectName\}/g, projectNamePathSegment ? '$1' + projectNamePathSegment : '') + .replace(/\{(.)?testName\}/g, '$1' + fsSanitizedTestName(test.titlePath)) + .replace(/\{(.)?testFileName\}/g, '$1' + parsedRelativeTestFilePath.base) + .replace(/\{(.)?testFilePath\}/g, '$1' + test.file) + .replace(/\{(.)?arg\}/g, '$1' + path.join(parsedSubPath.dir, parsedSubPath.name)) + .replace(/\{(.)?ext\}/g, parsedSubPath.ext ? '$1' + parsedSubPath.ext : ''); + + return path.normalize(path.resolve(snapshotPath)); + } + + getBrowserIds(): string[] { + return this._browserIds; + } + + forBrowser(browserId: string): BrowserConfigAdapter { + return { + id: browserId, + retry: 0 + }; + } +} + +function sanitizeForFilePath(s: string): string { + // eslint-disable-next-line no-control-regex + return s.replace(/[\x00-\x2C\x2E-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F]+/g, '-'); +} + +function fsSanitizedTestName(titlePath: string[]): string { + const fullTitleWithoutSpec = titlePath.join(' '); + + return sanitizeForFilePath(trimLongString(fullTitleWithoutSpec)); +} + +function trimLongString(s: string, length = 100): string { + if (s.length <= length) { + return s; + } + + const hash = calculateSha1(s); + const middle = `-${hash.substring(0, 5)}-`; + const start = Math.floor((length - middle.length) / 2); + const end = length - middle.length - start; + + return s.substring(0, start) + middle + s.slice(-end); +} + +function calculateSha1(buffer: Buffer | string): string { + const hash = crypto.createHash('sha1'); + hash.update(buffer); + + return hash.digest('hex'); +} diff --git a/lib/adapters/test-collection/playwright.ts b/lib/adapters/test-collection/playwright.ts new file mode 100644 index 000000000..b91cb9e79 --- /dev/null +++ b/lib/adapters/test-collection/playwright.ts @@ -0,0 +1,23 @@ +import {PlaywrightTestAdapter, type PwtRawTest} from '../test/playwright'; +import type {TestCollectionAdapter, TestsCallback} from './index'; + +export class PlaywrightTestCollectionAdapter implements TestCollectionAdapter { + private _tests: PwtRawTest[]; + + static create( + this: new (tests: PwtRawTest[]) => T, + tests: PwtRawTest[] + ): T { + return new this(tests); + } + + constructor(tests: PwtRawTest[]) { + this._tests = tests; + } + + eachTest(cb: TestsCallback): void { + for (const test of this._tests) { + cb(PlaywrightTestAdapter.create(test), test.browserName); + } + } +} diff --git a/lib/adapters/test-result/playwright.ts b/lib/adapters/test-result/playwright.ts index 30e3a5174..d0fc17751 100644 --- a/lib/adapters/test-result/playwright.ts +++ b/lib/adapters/test-result/playwright.ts @@ -6,20 +6,27 @@ import stripAnsi from 'strip-ansi'; import {ReporterTestResult} from './index'; import {getError, getShortMD5, isImageDiffError, isNoRefImageError} from '../../common-utils'; -import {ERROR, FAIL, PWT_TITLE_DELIMITER, SUCCESS, TestStatus} from '../../constants'; +import {ERROR, FAIL, SUCCESS, UPDATED, TestStatus, DEFAULT_TITLE_DELIMITER} from '../../constants'; import {ErrorName} from '../../errors'; import { DiffOptions, ErrorDetails, ImageFile, ImageInfoDiff, - ImageInfoFull, ImageInfoNoRef, ImageInfoPageError, ImageInfoPageSuccess, ImageInfoSuccess, + ImageInfoFull, ImageInfoNoRef, ImageInfoPageError, ImageInfoPageSuccess, ImageInfoSuccess, ImageInfoUpdated, ImageSize, TestError } from '../../types'; import type {CoordBounds} from 'looks-same'; -export type PlaywrightAttachment = PlaywrightTestResult['attachments'][number]; +export type PlaywrightAttachment = PlaywrightTestResult['attachments'][number] & { + relativePath?: string, + size?: { + width: number; + height: number; + }, + isUpdated?: boolean +}; type ExtendedError = TestError & {meta?: T & {type: string}}; @@ -32,7 +39,7 @@ export enum PwtTestStatus { FAILED = 'failed', TIMED_OUT = 'timedOut', INTERRUPTED = 'interrupted', - SKIPPED = 'skipped', + SKIPPED = 'skipped' } export enum ImageTitleEnding { @@ -48,7 +55,19 @@ export const DEFAULT_DIFF_OPTIONS = { diffColor: '#ff00ff' } satisfies Partial; -export const getStatus = (result: PlaywrightTestResult): TestStatus => { +export interface TestResultWithGuiStatus extends Omit { + status: PlaywrightTestResult['status'] | TestStatus.RUNNING | TestStatus.UPDATED; +} + +export const getStatus = (result: TestResultWithGuiStatus): TestStatus => { + if (result.status === TestStatus.RUNNING) { + return TestStatus.RUNNING; + } + + if (result.status === TestStatus.UPDATED) { + return TestStatus.UPDATED; + } + if (result.status === PwtTestStatus.PASSED) { return TestStatus.SUCCESS; } @@ -127,7 +146,8 @@ const getImageData = (attachment: PlaywrightAttachment | undefined): ImageFile | return { path: attachment.path as string, - size: _.pick(sizeOf(attachment.path as string), ['height', 'width']) as ImageSize + size: !attachment.size ? _.pick(sizeOf(attachment.path as string), ['height', 'width']) as ImageSize : attachment.size, + ...(attachment.relativePath ? {relativePath: attachment.relativePath} : {}) }; }; @@ -136,6 +156,15 @@ export class PlaywrightTestResultAdapter implements ReporterTestResult { private readonly _testResult: PlaywrightTestResult; private _attempt: number; + static create( + this: new (testCase: PlaywrightTestCase, testResult: PlaywrightTestResult, attempt: number) => T, + testCase: PlaywrightTestCase, + testResult: PlaywrightTestResult, + attempt: number + ): T { + return new this(testCase, testResult, attempt); + } + constructor(testCase: PlaywrightTestCase, testResult: PlaywrightTestResult, attempt: number) { this._testCase = testCase; this._testResult = testResult; @@ -157,6 +186,7 @@ export class PlaywrightTestResultAdapter implements ReporterTestResult { get error(): TestError | undefined { const message = extractErrorMessage(this._testResult); + if (message) { const result: TestError = {name: ErrorName.GENERAL_ERROR, message}; @@ -165,7 +195,7 @@ export class PlaywrightTestResultAdapter implements ReporterTestResult { result.stack = stack; } - if (message.includes('snapshot doesn\'t exist') && message.includes('.png')) { + if (/snapshot .*doesn't exist/.test(message) && message.includes('.png')) { result.name = ErrorName.NO_REF_IMAGE; } else if (message.includes('Screenshot comparison failed')) { result.name = ErrorName.IMAGE_DIFF; @@ -185,7 +215,7 @@ export class PlaywrightTestResultAdapter implements ReporterTestResult { } get fullName(): string { - return this.testPath.join(PWT_TITLE_DELIMITER); + return this.testPath.join(DEFAULT_TITLE_DELIMITER); } get history(): string[] { @@ -193,7 +223,7 @@ export class PlaywrightTestResultAdapter implements ReporterTestResult { } get id(): string { - return this.testPath.concat(this.browserId, this.attempt.toString()).join(' '); + return this.testPath.concat(this.browserId, this.attempt.toString()).join(DEFAULT_TITLE_DELIMITER); } get imageDir(): string { @@ -230,6 +260,14 @@ export class PlaywrightTestResultAdapter implements ReporterTestResult { error: _.pick(error, ['message', 'name', 'stack']), actualImg } satisfies ImageInfoNoRef; + } else if (expectedAttachment?.isUpdated && expectedImg && actualImg) { + return { + status: UPDATED, + stateName: state, + refImg: _.clone(expectedImg), + expectedImg, + actualImg + } satisfies ImageInfoUpdated; } else if (!error && expectedImg) { return { status: SUCCESS, @@ -281,6 +319,7 @@ export class PlaywrightTestResultAdapter implements ReporterTestResult { get status(): TestStatus { const status = getStatus(this._testResult); + if (status === TestStatus.FAIL) { if (isNoRefImageError(this.error) || isImageDiffError(this.error)) { return FAIL; diff --git a/lib/adapters/test/index.ts b/lib/adapters/test/index.ts index 26e1d090c..d548efe11 100644 --- a/lib/adapters/test/index.ts +++ b/lib/adapters/test/index.ts @@ -1,14 +1,30 @@ import {TestStatus} from '../../constants'; import type {ReporterTestResult} from '../test-result'; +import type {AssertViewResult} from '../../types'; + +export interface CreateTestResultOpts { + status: TestStatus; + attempt?: number; + assertViewResults?: AssertViewResult[]; + error?: Error; + sessionId?: string; + meta?: { + url?: string; + } +} export interface TestAdapter { readonly id: string; readonly pending: boolean; readonly disabled: boolean; readonly browserId: string; + readonly file: string; + readonly title: string; + readonly titlePath: string[]; clone(): TestAdapter; fullTitle(): string; isSilentlySkipped(): boolean; - formatTestResult(status: TestStatus, attempt?: number): ReporterTestResult; + // TODO: rename to mkTestResult ??? + createTestResult(opts: CreateTestResultOpts): ReporterTestResult; } diff --git a/lib/adapters/test/playwright.ts b/lib/adapters/test/playwright.ts new file mode 100644 index 000000000..a59ab6f39 --- /dev/null +++ b/lib/adapters/test/playwright.ts @@ -0,0 +1,158 @@ +import _ from 'lodash'; +import type {TestCase, TestResult} from '@playwright/test/reporter'; + +import {PlaywrightTestResultAdapter, ImageTitleEnding, type PlaywrightAttachment} from '../test-result/playwright'; +import {UNKNOWN_ATTEMPT} from '../../constants'; + +import type {TestAdapter, CreateTestResultOpts} from './'; +import type {ReporterTestResult} from '../test-result'; +import type {AssertViewResult, ImageFile, RefImageFile} from '../../types'; +import type {ImageDiffError} from '../../errors'; + +export type PwtRawTest = { + file: string; + browserName: string; + title: string; + titlePath: string[]; +} + +export class PlaywrightTestAdapter implements TestAdapter { + private _test: PwtRawTest; + + static create(this: new (test: PwtRawTest) => T, test: PwtRawTest): T { + return new this(test); + } + + constructor(test: PwtRawTest) { + this._test = test; + } + + get originalTest(): PwtRawTest { + return this._test; + } + + get id(): string { + return this._test.title; + } + + get file(): string { + return this._test.file; + } + + get title(): string { + return this._test.title; + } + + get titlePath(): string[] { + return this._test.titlePath; + } + + get pending(): boolean { + return false; + } + + get disabled(): boolean { + return false; + } + + get silentSkip(): boolean { + return false; + } + + get skipReason(): string { + return ''; + } + + get browserId(): string { + return this._test.browserName; + } + + get browserVersion(): string { + return ''; + } + + fullTitle(): string { + return this._test.title; + } + + clone(): PlaywrightTestAdapter { + return PlaywrightTestAdapter.create(_.cloneDeep(this._test)); + } + + isSilentlySkipped(): boolean { + return false; + } + + createTestResult(opts: CreateTestResultOpts): ReporterTestResult { + const {status, attempt = UNKNOWN_ATTEMPT, assertViewResults = []} = opts; + + const testCase = { + titlePath: () => ['', this._test.browserName, this._test.file, ...this._test.titlePath], + title: this._test.title, + annotations: [], + location: { + file: this._test.file + }, + parent: { + project: () => ({ + name: this._test.browserName + }) + } + } as unknown as TestCase; + + const attachments = assertViewResults.map(assertViewResult => { + const attachmentByState = [generateExpectedAttachment(assertViewResult, assertViewResult.refImg)]; + + if ((assertViewResult as ImageDiffError).currImg) { + attachmentByState.push(generateActualAttachment(assertViewResult, (assertViewResult as ImageDiffError).currImg)); + } + + if ((assertViewResult as ImageDiffError).diffImg) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + attachmentByState.push(generateDiffAttachment(assertViewResult, (assertViewResult as ImageDiffError).diffImg!)); + } + + return attachmentByState; + }).flat(); + + const result = { + attachments, + status, + steps: [], + startTime: new Date() + } as unknown as TestResult; + + return PlaywrightTestResultAdapter.create(testCase, result, attempt); + } +} + +function generateExpectedAttachment(assertViewResult: AssertViewResult, imageFile: ImageFile): PlaywrightAttachment { + return { + name: `${assertViewResult.stateName}${ImageTitleEnding.Expected}`, + relativePath: (assertViewResult.refImg as RefImageFile).relativePath, + ...generateAttachment(assertViewResult, imageFile) + }; +} + +function generateActualAttachment(assertViewResult: AssertViewResult, imageFile: ImageFile): PlaywrightAttachment { + return { + name: `${assertViewResult.stateName}${ImageTitleEnding.Actual}`, + ...generateAttachment(assertViewResult, imageFile) + }; +} + +function generateDiffAttachment(assertViewResult: AssertViewResult, imageFile: ImageFile): PlaywrightAttachment { + return { + name: `${assertViewResult.stateName}${ImageTitleEnding.Diff}`, + ...generateAttachment(assertViewResult, imageFile) + }; +} + +function generateAttachment(assertViewResult: AssertViewResult, imageFile: ImageFile): Pick { + return { + path: imageFile.path, + contentType: 'image/png', + size: imageFile.size, + isUpdated: assertViewResult.isUpdated + }; +} diff --git a/lib/adapters/test/testplane.ts b/lib/adapters/test/testplane.ts index 6a2b4a561..7cd89c90a 100644 --- a/lib/adapters/test/testplane.ts +++ b/lib/adapters/test/testplane.ts @@ -1,7 +1,7 @@ import {TestplaneTestResultAdapter} from '../test-result/testplane'; -import {TestStatus, UNKNOWN_ATTEMPT} from '../../constants'; +import {UNKNOWN_ATTEMPT, TESTPLANE_TITLE_DELIMITER} from '../../constants'; -import type {TestAdapter} from './'; +import type {TestAdapter, CreateTestResultOpts} from './'; import type {Test, Suite} from 'testplane'; import type {ReporterTestResult} from '../test-result'; @@ -24,6 +24,18 @@ export class TestplaneTestAdapter implements TestAdapter { return this._test.id; } + get file(): string { + return this._test.file; + } + + get title(): string { + return this._test.title; + } + + get titlePath(): string[] { + return this._test.fullTitle().split(TESTPLANE_TITLE_DELIMITER); + } + get pending(): boolean { return this._test.pending; } @@ -48,7 +60,21 @@ export class TestplaneTestAdapter implements TestAdapter { return Boolean(runnable.silentSkip || runnable.parent && this.isSilentlySkipped(runnable.parent)); } - formatTestResult(status: TestStatus, attempt: number = UNKNOWN_ATTEMPT): ReporterTestResult { - return TestplaneTestResultAdapter.create(this._test, {attempt, status}); + createTestResult(opts: CreateTestResultOpts): ReporterTestResult { + const {status, assertViewResults, error, sessionId, meta, attempt = UNKNOWN_ATTEMPT} = opts; + const test = this._test.clone(); + + [ + {key: 'assertViewResults', value: assertViewResults}, + {key: 'err', value: error}, + {key: 'sessionId', value: sessionId}, + {key: 'meta', value: meta} + ].forEach(({key, value}) => { + if (value) { + test[key] = value; + } + }); + + return TestplaneTestResultAdapter.create(test, {attempt, status}); } } diff --git a/lib/adapters/tool/index.ts b/lib/adapters/tool/index.ts index 915f850cd..06fdeca0a 100644 --- a/lib/adapters/tool/index.ts +++ b/lib/adapters/tool/index.ts @@ -44,7 +44,9 @@ export const makeToolAdapter = async (opts: ToolAdapterOptionsFromCli): Promise< return TestplaneToolAdapter.create(opts); } else if (opts.toolName === ToolName.Playwright) { - throw new Error('Playwright is not supported yet'); + const {PlaywrightToolAdapter} = await import('./playwright'); + + return PlaywrightToolAdapter.create(opts); } else { throw new Error(`Tool adapter with name: "${opts.toolName}" is not supported`); } diff --git a/lib/adapters/tool/playwright/index.ts b/lib/adapters/tool/playwright/index.ts new file mode 100644 index 000000000..2d8d0d73e --- /dev/null +++ b/lib/adapters/tool/playwright/index.ts @@ -0,0 +1,305 @@ +import path from 'node:path'; +import os from 'node:os'; +import {spawn} from 'node:child_process'; + +import npmWhich from 'npm-which'; +import PQueue from 'p-queue'; +import _ from 'lodash'; + +import {PlaywrightConfigAdapter, DEFAULT_BROWSER_ID} from '../../config/playwright'; +import {PlaywrightTestCollectionAdapter} from '../../test-collection/playwright'; +import {parseConfig} from '../../../config'; +import {HtmlReporter} from '../../../plugin-api'; +import {setupTransformHook} from './transformer'; +import {ToolName, UNKNOWN_ATTEMPT, PWT_TITLE_DELIMITER, DEFAULT_TITLE_DELIMITER, TestStatus} from '../../../constants'; +import {ClientEvents} from '../../../gui/constants'; +import {GuiApi} from '../../../gui/api'; +import {PlaywrightTestResultAdapter} from '../../test-result/playwright'; +import ipc from './ipc'; +import pkg from '../../../../package.json'; +import {logger} from '../../../common-utils'; + +import type {ToolAdapter, ToolAdapterOptionsFromCli} from '../index'; +import type {GuiReportBuilder} from '../../../report-builder/gui'; +import type {EventSource} from '../../../gui/event-source'; +import type {PwtRawTest} from '../../test/playwright'; +import type {ReporterConfig} from '../../../types'; +import type {TestSpec} from '../types'; +import type {FullConfig, TestCase, TestResult} from '@playwright/test/reporter'; +import type {TestBranch} from '../../../tests-tree-builder/gui'; +import type {PwtEventMessage} from './reporter'; + +export const DEFAULT_CONFIG_PATHS = [ + `${ToolName.Playwright}.config.ts`, + `${ToolName.Playwright}.config.js`, + `${ToolName.Playwright}.config.mts`, + `${ToolName.Playwright}.config.mjs`, + `${ToolName.Playwright}.config.cts`, + `${ToolName.Playwright}.config.cjs` +]; + +export class PlaywrightToolAdapter implements ToolAdapter { + private _toolName: ToolName; + private _configPath: string; + private _config: PlaywrightConfigAdapter; + private _reporterConfig: ReporterConfig; + private _haveProjectsInConfig: boolean; + private _htmlReporter: HtmlReporter; + private _pwtBinaryPath: string; + private _reportBuilder!: GuiReportBuilder; + private _eventSource!: EventSource; + private _guiApi?: GuiApi; + + static create( + this: new (options: ToolAdapterOptionsFromCli) => PlaywrightToolAdapter, + options: ToolAdapterOptionsFromCli + ): PlaywrightToolAdapter { + return new this(options); + } + + constructor(opts: ToolAdapterOptionsFromCli) { + const {config, configPath} = readPwtConfig(opts); + + this._configPath = configPath; + this._config = PlaywrightConfigAdapter.create(config); + this._toolName = opts.toolName; + + const pluginOpts = getPluginOptions(this._config.original); + this._reporterConfig = parseConfig(pluginOpts); + + this._haveProjectsInConfig = !_.isEmpty(this._config.original.projects); + + this._htmlReporter = HtmlReporter.create(this._reporterConfig, {toolName: ToolName.Playwright}); + this._pwtBinaryPath = npmWhich.sync(ToolName.Playwright, {cwd: process.cwd()}); + } + + get toolName(): ToolName { + return this._toolName; + } + + get config(): PlaywrightConfigAdapter { + return this._config; + } + + // TODO: should cpecify for testplane ??? + get configPath(): string { + return this._configPath; + } + + get reporterConfig(): ReporterConfig { + return this._reporterConfig; + } + + get htmlReporter(): HtmlReporter { + return this._htmlReporter; + } + + get guiApi(): GuiApi | undefined { + return this._guiApi; + } + + initGuiApi(): void { + this._guiApi = GuiApi.create(); + } + + async readTests(): Promise { + const stdout = await new Promise((resolve, reject) => { + // specify default browser in order to get correct stdout with browser name + const browserArgs = this._haveProjectsInConfig ? [] : ['--browser', DEFAULT_BROWSER_ID]; + + const child = spawn(this._pwtBinaryPath, ['test', '--list', '--reporter', 'list', '--config', this._configPath, ...browserArgs]); + let stdout = ''; + let stderr = ''; + + child.stdout.on('data', (data) => stdout += data); + child.stderr.on('data', (data) => stderr += data); + + child.on('error', (error) => reject(error)); + + child.on('exit', (code) => { + if (code !== 0) { + return reject(new Error(`Playwright process with reading tests exited with code: ${code}, stderr: ${stderr}`)); + } + + resolve(stdout); + }); + }); + + const stdoutByLine = stdout.split('\n').map(v => v.trim()); + const startIndex = stdoutByLine.findIndex(v => v === 'Listing tests:'); + const endIndex = stdoutByLine.findIndex(v => /total: \d+ tests? in \d+ file/i.test(v)); + + const tests = stdoutByLine.slice(startIndex + 1, endIndex).map(line => { + const [browserName, file, ...titlePath] = line.split(PWT_TITLE_DELIMITER); + + return { + browserName: browserName.slice(1, -1), + file: file.split(':')[0], + title: titlePath.join(DEFAULT_TITLE_DELIMITER), + titlePath + } as PwtRawTest; + }); + + return PlaywrightTestCollectionAdapter.create(tests); + } + + async run(_testCollection: PlaywrightTestCollectionAdapter, tests: TestSpec[] = []): Promise { + if (!this._reportBuilder || !this._eventSource) { + throw new Error('"reportBuilder" and "eventSource" instances must be initialize before run tests'); + } + + const queue = new PQueue({concurrency: os.cpus().length}); + + return new Promise((resolve, reject) => { + const args = prepareRunArgs(tests, this._configPath, this._haveProjectsInConfig); + const child = spawn(this._pwtBinaryPath, args, { + stdio: ['inherit', 'inherit', 'inherit', 'ipc'] + }); + + ipc.on(ClientEvents.BEGIN_STATE, (data) => { + data.result.status = TestStatus.RUNNING; + + queue.add(async () => { + const testBranch = await registerTestResult(data, this._reportBuilder); + + this._eventSource.emit(data.event, testBranch); + }).catch(reject); + }, child); + + ipc.on(ClientEvents.TEST_RESULT, (data) => { + queue.add(async () => { + const testBranch = await registerTestResult(data, this._reportBuilder); + + this._eventSource.emit(data.event, testBranch); + }).catch(reject); + }, child); + + ipc.on(ClientEvents.END, (data) => { + queue.onIdle().then(() => this._eventSource.emit(data.event)); + }, child); + + child.on('error', (data) => reject(data)); + + child.on('exit', (code) => { + queue.onIdle().then(() => resolve(!code)); + }); + }); + } + + // Can't handle test results here because pwt does not provide api for this, so save instances and use them in custom reporter + handleTestResults(reportBuilder: GuiReportBuilder, eventSource: EventSource): void { + this._reportBuilder = reportBuilder; + this._eventSource = eventSource; + } + + updateReference(): void {} + + halt(err: Error): void { + logger.error(err); + process.exit(1); + } +} + +function readPwtConfig(opts: ToolAdapterOptionsFromCli): {configPath: string, config: FullConfig} { + const configPaths = opts.configPath ? [opts.configPath] : DEFAULT_CONFIG_PATHS; + let originalConfig!: FullConfig; + let resolvedConfigPath!: string; + + const revertTransformHook = setupTransformHook(); + + for (const configPath of configPaths) { + try { + resolvedConfigPath = path.resolve(configPath); + // eslint-disable-next-line @typescript-eslint/no-var-requires + const configModule = require(resolvedConfigPath); + originalConfig = configModule.__esModule ? configModule.default : configModule; + + break; + } catch (err) { + if ((err as NodeJS.ErrnoException).code !== 'MODULE_NOT_FOUND') { + throw err; + } + } + } + + revertTransformHook(); + + if (!originalConfig) { + throw new Error(`Unable to read config from paths: ${configPaths.join(', ')}`); + } + + return {config: originalConfig, configPath: resolvedConfigPath}; +} + +async function registerTestResult(eventMsg: PwtEventMessage, reportBuilder: GuiReportBuilder): Promise { + const {test, result, browserName, titlePath} = eventMsg; + + const testCase = { + ...test, + titlePath: () => titlePath, + parent: { + ...test.parent, + project: () => ({ + name: browserName + }) + } + } as TestCase; + + const testResult = { + ...result, + startTime: new Date(result.startTime) + } as TestResult; + + const formattedResultWithoutAttempt = PlaywrightTestResultAdapter.create(testCase, testResult, UNKNOWN_ATTEMPT); + const formattedResult = await reportBuilder.addTestResult(formattedResultWithoutAttempt); + + return reportBuilder.getTestBranch(formattedResult.id); +} + +function prepareRunArgs(tests: TestSpec[], configPath: string, haveProjectsInConfig: boolean): string[] { + const testNames = new Set(); + const browserNames = new Set(); + + for (const {testName, browserName} of tests) { + testNames.add(testName); + browserNames.add(browserName); + } + + const args = ['test', '--reporter', path.resolve(__dirname, './reporter'), '--config', configPath]; + + if (testNames.size > 0) { + args.push('--grep', Array.from(testNames).join('|')); + args.push('--retries', '0'); + } + + if (browserNames.size > 0) { + const projectArgs = Array.from(browserNames).flatMap(broName => [haveProjectsInConfig ? '--project' : '--browser', broName]); + args.push(...projectArgs); + } else if (!haveProjectsInConfig) { + args.push(...['--browser', DEFAULT_BROWSER_ID]); + } + + return args; +} + +function getPluginOptions(config: PlaywrightConfigAdapter['original']): Partial { + const {reporter: reporters} = config; + + if (!_.isArray(reporters)) { + return {}; + } + + for (const reporter of reporters) { + if (_.isString(reporter)) { + continue; + } + + const [reporterName, reporterOpts = {}] = reporter; + + if (reporterName === `${pkg.name}/${ToolName.Playwright}`) { + return reporterOpts; + } + } + + return {}; +} diff --git a/lib/adapters/tool/playwright/ipc.ts b/lib/adapters/tool/playwright/ipc.ts new file mode 100644 index 000000000..b54d55c2d --- /dev/null +++ b/lib/adapters/tool/playwright/ipc.ts @@ -0,0 +1,17 @@ +import _ from 'lodash'; +import type {ChildProcess} from 'node:child_process'; + +export default { + emit: (event: string, data: Record = {}): void => { + process.send && process.send({event, ...data}); + }, + on: >(event: string, handler: (msg: T & {event: string}) => void, proc: ChildProcess | NodeJS.Process = process): void => { + proc.on('message', (msg: T & {event: string}) => { + if (event !== _.get(msg, 'event')) { + return; + } + + handler(msg); + }); + } +}; diff --git a/lib/adapters/tool/playwright/reporter.ts b/lib/adapters/tool/playwright/reporter.ts new file mode 100644 index 000000000..32c23a547 --- /dev/null +++ b/lib/adapters/tool/playwright/reporter.ts @@ -0,0 +1,36 @@ +import stringify from 'json-stringify-safe'; +import ipc from './ipc'; +import {ClientEvents} from '../../../gui/constants'; + +import type {Reporter, TestCase} from '@playwright/test/reporter'; +import type {TestResultWithGuiStatus} from '../../test-result/playwright'; + +export type PwtEventMessage = { + test: TestCase; + result: TestResultWithGuiStatus; + browserName: string; + titlePath: string[]; +}; + +export default class MyReporter implements Reporter { + onTestBegin(test: TestCase, result: TestResultWithGuiStatus): void { + ipc.emit(ClientEvents.BEGIN_STATE, getEmittedData(test, result)); + } + + onTestEnd(test: TestCase, result: TestResultWithGuiStatus): void { + ipc.emit(ClientEvents.TEST_RESULT, getEmittedData(test, result)); + } + + onEnd(): void { + ipc.emit(ClientEvents.END); + } +} + +function getEmittedData(test: TestCase, result: TestResultWithGuiStatus): PwtEventMessage { + return { + test: JSON.parse(stringify(test)), + result: JSON.parse(stringify(result)), + browserName: test.parent.project()?.name || '', + titlePath: test.titlePath() + }; +} diff --git a/lib/adapters/tool/playwright/transformer.ts b/lib/adapters/tool/playwright/transformer.ts new file mode 100644 index 000000000..0d10b082a --- /dev/null +++ b/lib/adapters/tool/playwright/transformer.ts @@ -0,0 +1,2 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +export const setupTransformHook: () => VoidFunction = require('../../../bundle').setupTransformHook; diff --git a/lib/adapters/tool/testplane/index.ts b/lib/adapters/tool/testplane/index.ts index 3a82be7b2..5e366e3b4 100644 --- a/lib/adapters/tool/testplane/index.ts +++ b/lib/adapters/tool/testplane/index.ts @@ -47,7 +47,7 @@ export class TestplaneToolAdapter implements ToolAdapter { private _htmlReporter: HtmlReporter; private _guiApi?: GuiApi; - static create( + static create( this: new (options: Options) => TestplaneToolAdapter, options: Options ): TestplaneToolAdapter { diff --git a/lib/bundle/constants.ts b/lib/bundle/constants.ts new file mode 100644 index 000000000..6dcfb3b5a --- /dev/null +++ b/lib/bundle/constants.ts @@ -0,0 +1 @@ +export const TRANSFORM_EXTENSIONS = ['.ts', '.mts', '.mjs']; diff --git a/lib/bundle/index.ts b/lib/bundle/index.ts new file mode 100644 index 000000000..275b2dab7 --- /dev/null +++ b/lib/bundle/index.ts @@ -0,0 +1,2 @@ +export * from './transformer'; +export * from './constants'; diff --git a/lib/bundle/transformer.ts b/lib/bundle/transformer.ts new file mode 100644 index 000000000..5238a4772 --- /dev/null +++ b/lib/bundle/transformer.ts @@ -0,0 +1,26 @@ +import * as babel from '@babel/core'; +import {addHook} from 'pirates'; +import {TRANSFORM_EXTENSIONS} from './constants'; + +import type {TransformOptions} from '@babel/core'; + +export const setupTransformHook = (): VoidFunction => { + const transformOptions: TransformOptions = { + browserslistConfigFile: false, + babelrc: false, + configFile: false, + compact: false, + plugins: [ + require('@babel/plugin-transform-modules-commonjs') + ] + }; + + const revertTransformHook = addHook( + (originalCode, filename) => { + return babel.transform(originalCode, {filename, ...transformOptions})?.code as string; + }, + {exts: TRANSFORM_EXTENSIONS} + ); + + return revertTransformHook; +}; diff --git a/lib/cli/index.ts b/lib/cli/index.ts index 206dbff49..1c6f49093 100644 --- a/lib/cli/index.ts +++ b/lib/cli/index.ts @@ -4,7 +4,8 @@ import {Command} from '@gemini-testing/commander'; import pkg from '../../package.json'; import {ToolName} from '../constants'; -import {makeToolAdapter} from '../adapters/tool'; +import {makeToolAdapter, type ToolAdapter} from '../adapters/tool'; +import {logger} from '../common-utils'; export const commands = { GUI: 'gui', @@ -12,6 +13,28 @@ export const commands = { REMOVE_UNUSED_SCREENS: 'remove-unused-screens' } as const; +let toolAdapter: ToolAdapter; + +process.on('uncaughtException', err => { + logger.error(err.stack); + process.exit(1); +}); + +process.on('unhandledRejection', (reason, p) => { + const error = new Error([ + `Unhandled Rejection in ${toolAdapter ? toolAdapter.toolName + ':' : ''}${process.pid}:`, + `Promise: ${JSON.stringify(p)}`, + `Reason: ${_.get(reason, 'stack', reason)}` + ].join('\n')); + + if (toolAdapter) { + toolAdapter.halt(error, 60000); + } else { + logger.error(error); + process.exit(1); + } +}); + export const run = async (): Promise => { const program = new Command(pkg.name) .version(pkg.version) @@ -26,7 +49,7 @@ export const run = async (): Promise => { throw new Error(`Tool with name: "${toolName}" is not supported, try to use one of these: ${availableToolNames.map(t => `"${t}"`).join(', ')}`); } - const toolAdapter = await makeToolAdapter({toolName: toolName as ToolName, configPath}); + toolAdapter = await makeToolAdapter({toolName: toolName as ToolName, configPath}); for (const commandName of _.values(commands)) { const registerCmd = (await import(path.resolve(__dirname, './commands', commandName))).default; diff --git a/lib/common-utils.ts b/lib/common-utils.ts index 9302bf007..2cb714cec 100644 --- a/lib/common-utils.ts +++ b/lib/common-utils.ts @@ -5,14 +5,13 @@ import axios, {AxiosRequestConfig} from 'axios'; import { ERROR, FAIL, - TESTPLANE_TITLE_DELIMITER, - IDLE, PWT_TITLE_DELIMITER, + DEFAULT_TITLE_DELIMITER, + IDLE, QUEUED, RUNNING, SKIPPED, SUCCESS, TestStatus, - ToolName, UPDATED } from './constants'; @@ -161,6 +160,7 @@ export const determineStatus = (testResult: Pick (imagesInfo as {error: {name?: string}}).error ?? {}); + if (hasDiff(imageErrors) || hasNoRefImageErrors({assertViewResults: imageErrors})) { return FAIL; } @@ -239,16 +239,12 @@ export const isCheckboxIndeterminate = (status: number): boolean => Number(statu export const isCheckboxUnchecked = (status: number): boolean => Number(status) === UNCHECKED; export const getToggledCheckboxState = (status: number): number => isCheckboxChecked(status) ? UNCHECKED : CHECKED; -export const getTitleDelimiter = (toolName: ToolName): string => { - return toolName === ToolName.Playwright ? PWT_TITLE_DELIMITER : TESTPLANE_TITLE_DELIMITER; -}; - export function getDetailsFileName(testId: string, browserId: string, attempt: number): string { return `${testId}-${browserId}_${Number(attempt) + 1}_${Date.now()}.json`; } export const getTestHash = (testResult: ReporterTestResult): string => { - return testResult.testPath.concat(testResult.browserId, testResult.attempt.toString()).join(' '); + return testResult.testPath.concat(testResult.browserId, testResult.attempt.toString()).join(DEFAULT_TITLE_DELIMITER); }; export const isImageBufferData = (imageData: ImageBuffer | ImageFile | ImageBase64 | undefined): imageData is ImageBuffer => { diff --git a/lib/constants/tests.ts b/lib/constants/tests.ts index 5ebae8c5b..7cb7a9f5b 100644 --- a/lib/constants/tests.ts +++ b/lib/constants/tests.ts @@ -1,4 +1,5 @@ -export const TESTPLANE_TITLE_DELIMITER = ' '; +export const DEFAULT_TITLE_DELIMITER = ' '; +export const TESTPLANE_TITLE_DELIMITER = DEFAULT_TITLE_DELIMITER; export const PWT_TITLE_DELIMITER = ' › '; diff --git a/lib/db-utils/server.ts b/lib/db-utils/server.ts index bd3e60e8c..de688be22 100644 --- a/lib/db-utils/server.ts +++ b/lib/db-utils/server.ts @@ -9,7 +9,7 @@ import NestedError from 'nested-error-stacks'; import {StaticTestsTreeBuilder} from '../tests-tree-builder/static'; import * as commonSqliteUtils from './common'; import {isUrl, fetchFile, normalizeUrls, logger} from '../common-utils'; -import {DATABASE_URLS_JSON_NAME, DB_COLUMNS, LOCAL_DATABASE_NAME, TestStatus, ToolName} from '../constants'; +import {DATABASE_URLS_JSON_NAME, DB_COLUMNS, LOCAL_DATABASE_NAME, TestStatus} from '../constants'; import {DbLoadResult, HandleDatabasesOptions} from './common'; import {DbUrlsJsonData, RawSuitesRow, ReporterConfig} from '../types'; import {Tree} from '../tests-tree-builder/base'; @@ -57,10 +57,10 @@ export async function mergeDatabases(srcDbPaths: string[], reportPath: string): } } -export function getTestsTreeFromDatabase(toolName: ToolName, dbPath: string, baseHost: string): Tree { +export function getTestsTreeFromDatabase(dbPath: string, baseHost: string): Tree { try { const db = new Database(dbPath, {readonly: true, fileMustExist: true}); - const testsTreeBuilder = StaticTestsTreeBuilder.create({toolName, baseHost}); + const testsTreeBuilder = StaticTestsTreeBuilder.create({baseHost}); const suitesRows = (db.prepare(commonSqliteUtils.selectAllSuitesQuery()) .raw() diff --git a/lib/gui/server.ts b/lib/gui/server.ts index 996c0a53e..af7e03093 100644 --- a/lib/gui/server.ts +++ b/lib/gui/server.ts @@ -103,7 +103,9 @@ export const start = async (args: ServerArgs): Promise => { server.post('/update-reference', (req, res) => { app.updateReferenceImage(req.body) - .then((updatedTests) => res.json(updatedTests)) + .then((updatedTests) => { + return res.json(updatedTests); + }) .catch(({message}) => res.status(INTERNAL_SERVER_ERROR).send({error: message})); }); diff --git a/lib/gui/tool-runner/index.ts b/lib/gui/tool-runner/index.ts index e4f35d804..c223f4a67 100644 --- a/lib/gui/tool-runner/index.ts +++ b/lib/gui/tool-runner/index.ts @@ -4,7 +4,6 @@ import os from 'node:os'; import {CommanderStatic} from '@gemini-testing/commander'; import chalk from 'chalk'; import fs from 'fs-extra'; -import type {Test as TestplaneTest} from 'testplane'; import _ from 'lodash'; import looksSame, {CoordBounds} from 'looks-same'; import PQueue from 'p-queue'; @@ -19,7 +18,7 @@ import {SqliteImageStore} from '../../image-store'; import * as reporterHelper from '../../reporter-helpers'; import {logger, getShortMD5, isUpdatedStatus} from '../../common-utils'; import {formatId, mkFullTitle, mergeDatabasesForReuse, filterByEqualDiffSizes} from './utils'; -import {formatTestResult, getExpectedCacheKey} from '../../server-utils'; +import {getExpectedCacheKey} from '../../server-utils'; import {getTestsTreeFromDatabase} from '../../db-utils/server'; import { UPDATED, @@ -28,25 +27,25 @@ import { ToolName, DATABASE_URLS_JSON_NAME, LOCAL_DATABASE_NAME, - PluginEvents + PluginEvents, + UNKNOWN_ATTEMPT } from '../../constants'; import type {ToolAdapter} from '../../adapters/tool'; -import type {GuiCliOptions, ServerArgs} from '../index'; -import type {TestBranch, TestEqualDiffsData, TestRefUpdateData} from '../../tests-tree-builder/gui'; +import type {TestAdapter} from '../../adapters/test'; +import type {TestCollectionAdapter} from '../../adapters/test-collection'; import type {ReporterTestResult} from '../../adapters/test-result'; -import type {Tree, TreeImage} from '../../tests-tree-builder/base'; +import type {ConfigAdapter} from '../../adapters/config'; import type {TestSpec} from '../../adapters/tool/types'; +import type {GuiCliOptions, ServerArgs} from '../'; +import type {TestBranch, TestEqualDiffsData, TestRefUpdateData} from '../../tests-tree-builder/gui'; +import type {Tree, TreeImage} from '../../tests-tree-builder/base'; import type { AssertViewResult, - TestplaneTestResult, ImageFile, ImageInfoDiff, ImageInfoUpdated, ImageInfoWithState, ReporterConfig, TestSpecByPath, RefImageFile } from '../../types'; -import type {TestAdapter} from '../../adapters/test/index'; -import type {TestCollectionAdapter} from '../../adapters/test-collection'; -import type {ConfigAdapter} from '../../adapters/config'; export type ToolRunnerTree = GuiReportBuilderResult & Pick; @@ -66,7 +65,7 @@ export class ToolRunner { private _reporterConfig: ReporterConfig; private _eventSource: EventSource; protected _reportBuilder: GuiReportBuilder | null; - private _tests: Record; + private _testAdapters: Record; private _expectedImagesCache: Cache<[TestSpecByPath, string | undefined], string>; static create(this: new (args: ServerArgs) => T, args: ServerArgs): T { @@ -88,7 +87,7 @@ export class ToolRunner { this._eventSource = new EventSource(); this._reportBuilder = null; - this._tests = {}; + this._testAdapters = {}; this._expectedImagesCache = new Cache(getExpectedCacheKey); } @@ -114,7 +113,12 @@ export class ToolRunner { reportPath: this._toolAdapter.htmlReporter.config.path }); - this._reportBuilder = GuiReportBuilder.create(this._toolAdapter.htmlReporter, this._reporterConfig, {dbClient, imagesInfoSaver}); + this._reportBuilder = GuiReportBuilder.create({ + htmlReporter: this._toolAdapter.htmlReporter, + reporterConfig: this._reporterConfig, + dbClient, + imagesInfoSaver + }); this._toolAdapter.handleTestResults(this._reportBuilder, this._eventSource); this._collection = await this._readTests(); @@ -175,17 +179,36 @@ export class ToolRunner { const reportBuilder = this._ensureReportBuilder(); return Promise.all(tests.map(async (test): Promise => { - const updateResult = this._createTestplaneTestResult(test); + const testAdapter = this._getTestAdapterById(test); + const assertViewResults = this._prepareAssertViewResults(test.imagesInfo, testAdapter); + const {sessionId, url} = test.metaInfo as {sessionId?: string; url?: string}; + const latestAttempt = reportBuilder.getLatestAttempt({ - fullName: updateResult.fullTitle(), - browserId: updateResult.browserId + fullName: testAdapter.fullTitle(), + browserId: testAdapter.browserId }); - const latestResult = formatTestResult(updateResult, UPDATED, latestAttempt); + + const latestResult = testAdapter.createTestResult({ + assertViewResults, + status: UPDATED, + attempt: latestAttempt, + error: test.error, + sessionId, + meta: {url} + }); + const estimatedStatus = reportBuilder.getUpdatedReferenceTestStatus(latestResult); - const formattedResultWithoutAttempt = formatTestResult(updateResult, UPDATED); - const formattedResult = reportBuilder.provideAttempt(formattedResultWithoutAttempt); + const formattedResultWithoutAttempt = testAdapter.createTestResult({ + assertViewResults, + status: UPDATED, + attempt: UNKNOWN_ATTEMPT, + error: test.error, + sessionId, + meta: {url} + }); + const formattedResult = reportBuilder.provideAttempt(formattedResultWithoutAttempt); const formattedResultUpdated = await reporterHelper.updateReferenceImages(formattedResult, this._reportPath, this._handleReferenceUpdate.bind(this)); await reportBuilder.addTestResult(formattedResultUpdated, {status: estimatedStatus}); @@ -199,8 +222,18 @@ export class ToolRunner { const reportBuilder = this._ensureReportBuilder(); await Promise.all(tests.map(async (test) => { - const updateResult = this._createTestplaneTestResult(test); - const formattedResultWithoutAttempt = formatTestResult(updateResult, UPDATED); + const testAdapter = this._getTestAdapterById(test); + const assertViewResults = this._prepareAssertViewResults(test.imagesInfo, testAdapter); + const {sessionId, url} = test.metaInfo as {sessionId?: string; url?: string}; + + const formattedResultWithoutAttempt = testAdapter.createTestResult({ + assertViewResults, + status: UPDATED, + attempt: UNKNOWN_ATTEMPT, + error: test.error, + sessionId, + meta: {url} + }); await Promise.all(formattedResultWithoutAttempt.imagesInfo.map(async (imageInfo) => { const {stateName} = imageInfo as ImageInfoWithState; @@ -230,10 +263,10 @@ export class ToolRunner { await reporterHelper.revertReferenceImage(removedResult, newResult, stateName); } - if (previousExpectedPath && (updateResult as TestplaneTest).fullTitle) { + if (previousExpectedPath) { this._expectedImagesCache.set([{ - testPath: [(updateResult as TestplaneTest).fullTitle()], - browserId: (updateResult as TestplaneTest).browserId + testPath: [testAdapter.fullTitle()], + browserId: testAdapter.browserId }, stateName], previousExpectedPath); } })); @@ -302,12 +335,13 @@ export class ToolRunner { // TODO: remove toString after publish major version const testId = formatId(test.id.toString(), browserId); - this._tests[testId] = _.extend(test, {browserId}); + + this._testAdapters[testId] = _.extend(test, {browserId}); if (test.pending) { - queue.add(async () => reportBuilder.addTestResult(test.formatTestResult(SKIPPED))); + queue.add(async () => reportBuilder.addTestResult(test.createTestResult({status: SKIPPED}))); } else { - queue.add(async () => reportBuilder.addTestResult(test.formatTestResult(IDLE))); + queue.add(async () => reportBuilder.addTestResult(test.createTestResult({status: IDLE}))); } }); @@ -315,38 +349,30 @@ export class ToolRunner { await this._fillTestsTree(); } - protected _createTestplaneTestResult(updateData: TestRefUpdateData): TestplaneTestResult { - const {browserId} = updateData; + protected _getTestAdapterById(updateData: TestRefUpdateData): TestAdapter { const fullTitle = mkFullTitle(updateData); - const testId = formatId(getShortMD5(fullTitle), browserId); - const testplaneTest = this._tests[testId]; - const {sessionId, url} = updateData.metaInfo as {sessionId?: string; url?: string}; + const testId = this._toolAdapter.toolName === ToolName.Playwright + ? formatId(fullTitle, updateData.browserId) + : formatId(getShortMD5(fullTitle), updateData.browserId); + + return this._testAdapters[testId]; + } + + protected _prepareAssertViewResults(imagesInfo: TestRefUpdateData['imagesInfo'], testAdapter: TestAdapter): AssertViewResult[] { const assertViewResults: AssertViewResult[] = []; - updateData.imagesInfo + imagesInfo .filter(({stateName, actualImg}) => Boolean(stateName) && Boolean(actualImg)) .forEach((imageInfo) => { const {stateName, actualImg} = imageInfo as {stateName: string, actualImg: ImageFile}; - const absoluteRefImgPath = this._toolAdapter.config.getScreenshotPath(testplaneTest, stateName); + const absoluteRefImgPath = this._toolAdapter.config.getScreenshotPath(testAdapter, stateName); const relativeRefImgPath = absoluteRefImgPath && path.relative(process.cwd(), absoluteRefImgPath); const refImg: RefImageFile = {path: absoluteRefImgPath, relativePath: relativeRefImgPath, size: actualImg.size}; assertViewResults.push({stateName, refImg, currImg: actualImg, isUpdated: isUpdatedStatus(imageInfo.status)}); }); - // TODO: should use original test here from test adapter ??? - const testplaneTestResult: TestplaneTestResult = _.merge({}, testplaneTest, { - assertViewResults, - err: updateData.error as TestplaneTestResult['err'], - sessionId, - meta: {url} - } satisfies Partial) as unknown as TestplaneTestResult; - - // _.merge can't fully clone test object since hermione@7+ - // TODO: use separate object to represent test results. Do not extend test object with test results - return testplaneTest && testplaneTest.clone - ? Object.assign(testplaneTest.clone(), testplaneTestResult) - : testplaneTestResult; + return assertViewResults; } protected _handleReferenceUpdate(testResult: ReporterTestResult, imageInfo: ImageInfoUpdated, state: string): void { @@ -372,7 +398,7 @@ export class ToolRunner { const dbPath = path.resolve(this._reportPath, LOCAL_DATABASE_NAME); if (await fs.pathExists(dbPath)) { - return getTestsTreeFromDatabase(ToolName.Testplane, dbPath, this._reporterConfig.baseHost); + return getTestsTreeFromDatabase(dbPath, this._reporterConfig.baseHost); } logger.warn(chalk.yellow(`Nothing to reuse in ${this._reportPath}: can not load data from ${DATABASE_URLS_JSON_NAME}`)); diff --git a/lib/report-builder/gui.ts b/lib/report-builder/gui.ts index 91e6ac19e..2142193de 100644 --- a/lib/report-builder/gui.ts +++ b/lib/report-builder/gui.ts @@ -1,13 +1,13 @@ import _ from 'lodash'; import {StaticReportBuilder, StaticReportBuilderOptions} from './static'; import {GuiTestsTreeBuilder, TestBranch, TestEqualDiffsData, TestRefUpdateData} from '../tests-tree-builder/gui'; -import {UPDATED, DB_COLUMNS, ToolName, TestStatus, TESTPLANE_TITLE_DELIMITER, SKIPPED, SUCCESS} from '../constants'; +import {UPDATED, DB_COLUMNS, TestStatus, SKIPPED, SUCCESS, DEFAULT_TITLE_DELIMITER} from '../constants'; import {ConfigForStaticFile, getConfigForStaticFile} from '../server-utils'; import {ReporterTestResult} from '../adapters/test-result'; import {Tree, TreeImage} from '../tests-tree-builder/base'; import {ImageInfoFull, ImageInfoWithState, ReporterConfig} from '../types'; import {determineStatus, isUpdatedStatus} from '../common-utils'; -import {HtmlReporter, HtmlReporterValues} from '../plugin-api'; +import {HtmlReporterValues} from '../plugin-api'; import {SkipItem} from '../tests-tree-builder/static'; import {copyAndUpdate} from '../adapters/test-result/utils'; @@ -33,10 +33,10 @@ export class GuiReportBuilder extends StaticReportBuilder { private _skips: SkipItem[]; private _apiValues?: HtmlReporterValues; - constructor(htmlReporter: HtmlReporter, pluginConfig: ReporterConfig, options: StaticReportBuilderOptions) { - super(htmlReporter, pluginConfig, options); + constructor(options: StaticReportBuilderOptions) { + super(options); - this._testsTree = GuiTestsTreeBuilder.create({toolName: ToolName.Testplane, baseHost: pluginConfig.baseHost}); + this._testsTree = GuiTestsTreeBuilder.create({baseHost: this._reporterConfig.baseHost}); this._skips = []; } @@ -51,15 +51,15 @@ export class GuiReportBuilder extends StaticReportBuilder { // Fill test attempt manager with data from db for (const [, testResult] of Object.entries(tree.results.byId)) { this._testAttemptManager.registerAttempt({ - fullName: testResult.suitePath.join(TESTPLANE_TITLE_DELIMITER), + fullName: testResult.suitePath.join(DEFAULT_TITLE_DELIMITER), browserId: testResult.name }, testResult.status, testResult.attempt); } } getResult(): GuiReportBuilderResult { - const {customGui} = this._pluginConfig; - const config = {...getConfigForStaticFile(this._pluginConfig), customGui}; + const {customGui} = this._reporterConfig; + const config = {...getConfigForStaticFile(this._reporterConfig), customGui}; this._testsTree.sortTree(); @@ -87,7 +87,6 @@ export class GuiReportBuilder extends StaticReportBuilder { undoAcceptImage(testResultWithoutAttempt: ReporterTestResult, stateName: string): UndoAcceptImageResult | null { const attempt = this._testAttemptManager.getCurrentAttempt(testResultWithoutAttempt); const testResult = copyAndUpdate(testResultWithoutAttempt, {attempt}); - const resultId = testResult.id; const suitePath = testResult.testPath; const browserName = testResult.browserId; diff --git a/lib/report-builder/static.ts b/lib/report-builder/static.ts index 141d82cf1..e51dbf7e1 100644 --- a/lib/report-builder/static.ts +++ b/lib/report-builder/static.ts @@ -24,30 +24,30 @@ import {ImagesInfoSaver} from '../images-info-saver'; const ignoredStatuses = [RUNNING, IDLE]; export interface StaticReportBuilderOptions { + htmlReporter: HtmlReporter, + reporterConfig: ReporterConfig, dbClient: SqliteClient; imagesInfoSaver: ImagesInfoSaver; } export class StaticReportBuilder { protected _htmlReporter: HtmlReporter; - protected _pluginConfig: ReporterConfig; + protected _reporterConfig: ReporterConfig; protected _dbClient: SqliteClient; protected _imagesInfoSaver: ImagesInfoSaver; protected _testAttemptManager: TestAttemptManager; private _workers?: RegisterWorkers<['saveDiffTo']>; static create( - this: new (htmlReporter: HtmlReporter, pluginConfig: ReporterConfig, options: StaticReportBuilderOptions) => T, - htmlReporter: HtmlReporter, - pluginConfig: ReporterConfig, + this: new (options: StaticReportBuilderOptions) => T, options: StaticReportBuilderOptions ): T { - return new this(htmlReporter, pluginConfig, options); + return new this(options); } - constructor(htmlReporter: HtmlReporter, pluginConfig: ReporterConfig, {dbClient, imagesInfoSaver}: StaticReportBuilderOptions) { + constructor({htmlReporter, reporterConfig, dbClient, imagesInfoSaver}: StaticReportBuilderOptions) { this._htmlReporter = htmlReporter; - this._pluginConfig = pluginConfig; + this._reporterConfig = reporterConfig; this._dbClient = dbClient; @@ -63,10 +63,10 @@ export class StaticReportBuilder { } async saveStaticFiles(): Promise { - const destPath = this._pluginConfig.path; + const destPath = this._reporterConfig.path; await Promise.all([ - saveStaticFilesToReportDir(this._htmlReporter, this._pluginConfig, destPath), + saveStaticFilesToReportDir(this._htmlReporter, this._reporterConfig, destPath), writeDatabaseUrlsFile(destPath, [LOCAL_DATABASE_NAME]) ]); } @@ -103,8 +103,8 @@ export class StaticReportBuilder { testResultWithImagePaths = await this._imagesInfoSaver.save(testResult, this._workers); }); - if (this._pluginConfig.saveErrorDetails && testResult.errorDetails) { - actions.add(async () => saveErrorDetails(testResult, this._pluginConfig.path)); + if (this._reporterConfig.saveErrorDetails && testResult.errorDetails) { + actions.add(async () => saveErrorDetails(testResult, this._reporterConfig.path)); } await actions.onIdle(); @@ -138,7 +138,7 @@ export class StaticReportBuilder { const reportsSaver = this._htmlReporter.reportsSaver; if (reportsSaver) { - const reportDir = this._pluginConfig.path; + const reportDir = this._reporterConfig.path; const src = path.join(reportDir, LOCAL_DATABASE_NAME); const dbPath = await reportsSaver.saveReportData(src, {destPath: LOCAL_DATABASE_NAME, reportDir: reportDir}); await writeDatabaseUrlsFile(reportDir, [dbPath]); diff --git a/lib/test-attempt-manager.ts b/lib/test-attempt-manager.ts index 98ffcf839..cd4c5bf3d 100644 --- a/lib/test-attempt-manager.ts +++ b/lib/test-attempt-manager.ts @@ -34,7 +34,6 @@ export class TestAttemptManager { registerAttempt(testResult: TestSpec, status: TestStatus, index: number | null = null): number { const [hash, data] = this._getData(testResult); - const isManualOverride = index !== null; const isLastStatusTemporary = [IDLE, RUNNING].includes(data.statuses.at(-1) as TestStatus); const shouldReplace = Number(isManualOverride || isLastStatusTemporary); diff --git a/lib/tests-tree-builder/base.ts b/lib/tests-tree-builder/base.ts index f45c45b76..4b72bfea4 100644 --- a/lib/tests-tree-builder/base.ts +++ b/lib/tests-tree-builder/base.ts @@ -1,6 +1,6 @@ import _ from 'lodash'; import {determineFinalStatus} from '../common-utils'; -import {BrowserVersions, PWT_TITLE_DELIMITER, TESTPLANE_TITLE_DELIMITER, TestStatus, ToolName} from '../constants'; +import {BrowserVersions, DEFAULT_TITLE_DELIMITER, TestStatus} from '../constants'; import {ReporterTestResult} from '../adapters/test-result'; import {ErrorDetails, ImageInfoFull} from '../types'; import {TreeTestResultTransformer} from '../adapters/test-result/transformers/tree'; @@ -81,13 +81,11 @@ interface ImagesPayload { } export interface BaseTestsTreeBuilderOptions { - toolName: ToolName; baseHost: string; } export class BaseTestsTreeBuilder { protected _tree: Tree; - protected _toolName: ToolName; protected _transformer: TreeTestResultTransformer; static create( @@ -97,9 +95,8 @@ export class BaseTestsTreeBuilder { return new this(options); } - constructor({toolName, baseHost}: BaseTestsTreeBuilderOptions) { - this._toolName = toolName; - + // TODO: should send Playwright tool Name here + constructor({baseHost}: BaseTestsTreeBuilderOptions) { this._transformer = new TreeTestResultTransformer({baseHost}); this._tree = { @@ -137,6 +134,7 @@ export class BaseTestsTreeBuilder { const suiteId = this._buildId(testPath); const browserId = this._buildId(suiteId, browserName); const testResultId = this._buildId(browserId, attempt.toString()); + const imageIds = imagesInfo .map((image: ImageInfoFull, i: number) => this._buildId(testResultId, (image as {stateName?: string}).stateName || `${image.status}_${i}`)); @@ -150,9 +148,7 @@ export class BaseTestsTreeBuilder { } protected _buildId(parentId: string | string[] = [], name: string | string[] = []): string { - const delimiter = this._toolName === ToolName.Playwright ? PWT_TITLE_DELIMITER : TESTPLANE_TITLE_DELIMITER; - - return ([] as string[]).concat(parentId, name).join(delimiter); + return ([] as string[]).concat(parentId, name).join(DEFAULT_TITLE_DELIMITER); } protected _addSuites(testPath: string[], browserId: string): void { diff --git a/lib/tests-tree-builder/static.ts b/lib/tests-tree-builder/static.ts index 501886680..ffa4678d1 100644 --- a/lib/tests-tree-builder/static.ts +++ b/lib/tests-tree-builder/static.ts @@ -1,9 +1,8 @@ import _ from 'lodash'; import {BaseTestsTreeBuilder, BaseTestsTreeBuilderOptions, Tree} from './base'; -import {BrowserVersions, DB_COLUMN_INDEXES, TestStatus} from '../constants'; +import {BrowserVersions, DB_COLUMN_INDEXES, DEFAULT_TITLE_DELIMITER, TestStatus} from '../constants'; import {ReporterTestResult} from '../adapters/test-result'; import {SqliteTestResultAdapter} from '../adapters/test-result/sqlite'; -import {getTitleDelimiter} from '../common-utils'; import {RawSuitesRow} from '../types'; interface Stats { @@ -70,7 +69,7 @@ export class StaticTestsTreeBuilder extends BaseTestsTreeBuilder { attemptsMap.set(browserId, attemptsMap.has(browserId) ? attemptsMap.get(browserId) as number + 1 : 0); const attempt = attemptsMap.get(browserId) as number; - const formattedResult = new SqliteTestResultAdapter(row, attempt, {titleDelimiter: getTitleDelimiter(this._toolName)}); + const formattedResult = new SqliteTestResultAdapter(row, attempt, {titleDelimiter: DEFAULT_TITLE_DELIMITER}); addBrowserVersion(browsers, formattedResult); diff --git a/package-lock.json b/package-lock.json index 148e195a0..7123447b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "html-reporter", - "version": "10.3.1", + "version": "10.3.2", "license": "MIT", "workspaces": [ "test/func/fixtures/*", @@ -37,6 +37,7 @@ "lodash": "^4.17.4", "looks-same": "^8.2.1", "nested-error-stacks": "^2.1.0", + "npm-which": "^3.0.1", "opener": "^1.4.3", "ora": "^5.4.1", "p-queue": "^5.0.0", @@ -50,7 +51,8 @@ "html-reporter": "bin/html-reporter" }, "devDependencies": { - "@babel/core": "^7.22.5", + "@babel/core": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", "@babel/plugin-transform-runtime": "^7.22.5", "@babel/preset-env": "^7.22.5", "@babel/preset-react": "^7.22.5", @@ -59,9 +61,11 @@ "@gravity-ui/uikit": "^6.20.0", "@playwright/test": "^1.44.1", "@swc/core": "^1.3.64", + "@types/babel__core": "^7.20.5", "@types/better-sqlite3": "^7.6.4", "@types/bluebird": "^3.5.3", "@types/chai": "^4.3.5", + "@types/chai-as-promised": "^7.1.1", "@types/debug": "^4.1.8", "@types/enzyme": "^3.10.13", "@types/escape-html": "^1.0.4", @@ -71,6 +75,7 @@ "@types/json-stringify-safe": "^5.0.2", "@types/lodash": "^4.14.195", "@types/nested-error-stacks": "^2.1.0", + "@types/npm-which": "^3.0.3", "@types/opener": "^1.4.0", "@types/proxyquire": "^1.3.28", "@types/sinon": "^4.3.3", @@ -93,6 +98,7 @@ "css-minimizer-webpack-plugin": "^5.0.1", "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.15.4", + "esbuild": "^0.22.0", "eslint": "^8.43.0", "eslint-config-gemini-testing": "^2.8.0", "eslint-plugin-react": "^7.32.2", @@ -122,6 +128,7 @@ "npm-run-all": "^4.1.5", "nyc": "^14.1.1", "path-browserify": "^1.0.1", + "pirates": "^4.0.6", "prop-types": "^15.6.0", "proxyquire": "^1.7.11", "raf": "^3.4.0", @@ -203,101 +210,48 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", - "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", + "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==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.10", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.6.tgz", - "integrity": "sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", + "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.8.tgz", - "integrity": "sha512-75+KxFB4CZqYRXjx4NlR4J7yGvKumBuZTmV4NV6v09dVXXkuYVYLT68N6HCzLvfJ+fWCxQsntNzKwwIXL4bHnw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", + "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-module-transforms": "^7.22.5", - "@babel/helpers": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.8", - "@babel/types": "^7.22.5", - "@nicolo-ribaudo/semver-v6": "^6.3.3", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helpers": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -307,90 +261,31 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/@babel/generator": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz", - "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core/node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core/node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core/node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } + "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 }, - "node_modules/@babel/core/node_modules/@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", + "node_modules/@babel/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, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@babel/core/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "node_modules/@babel/generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" + "@babel/types": "^7.24.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" @@ -408,20 +303,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-annotate-as-pure/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.5.tgz", @@ -434,37 +315,29 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", + "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" + "@babel/compat-data": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.6.tgz", - "integrity": "sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA==", + "node_modules/@babel/helper-compilation-targets/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, - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-validator-option": "^7.22.5", - "@nicolo-ribaudo/semver-v6": "^6.3.3", - "browserslist": "^4.21.9", - "lru-cache": "^5.1.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "bin": { + "semver": "bin/semver.js" } }, "node_modules/@babel/helper-create-class-features-plugin": { @@ -490,59 +363,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-create-regexp-features-plugin": { "version": "7.22.6", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.6.tgz", @@ -615,35 +435,37 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "node_modules/@babel/helper-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-hoist-variables/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "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", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -661,152 +483,36 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-member-expression-to-functions/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz", - "integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms/node_modules/@babel/generator": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz", - "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms/node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", + "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", "dev": true, "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms/node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms/node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms/node_modules/@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", - "globals": "^11.1.0" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" }, "engines": { "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-optimise-call-expression": { @@ -821,24 +527,10 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-optimise-call-expression/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", + "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", "dev": true, "engines": { "node": ">=6.9.0" @@ -862,20 +554,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-replace-supers": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.5.tgz", @@ -893,116 +571,14 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-replace-supers/node_modules/@babel/generator": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz", - "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-replace-supers/node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-replace-supers/node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-replace-supers/node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-replace-supers/node_modules/@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-replace-supers/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1020,42 +596,40 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", + "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", + "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", "dev": true, "engines": { "node": ">=6.9.0" @@ -1076,207 +650,29 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-wrap-function/node_modules/@babel/generator": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz", - "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function/node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function/node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function/node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function/node_modules/@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helpers": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", - "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", + "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", "dev": true, "dependencies": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.6", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers/node_modules/@babel/generator": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz", - "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers/node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers/node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers/node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers/node_modules/@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", - "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -1323,12 +719,6 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, - "node_modules/@babel/highlight/node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -1342,9 +732,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", - "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -1814,59 +1204,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/plugin-transform-classes/node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/plugin-transform-classes/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", @@ -1883,34 +1220,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-computed-properties/node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/plugin-transform-destructuring": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.5.tgz", @@ -2037,47 +1346,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-function-name/node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/plugin-transform-function-name/node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/plugin-transform-function-name/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/plugin-transform-json-strings": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz", @@ -2157,14 +1425,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz", - "integrity": "sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz", + "integrity": "sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2451,20 +1719,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-jsx/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/plugin-transform-react-pure-annotations": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz", @@ -2792,20 +2046,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/preset-modules": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", @@ -2822,20 +2062,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-modules/node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/preset-react": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.5.tgz", @@ -2897,6 +2123,55 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, + "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==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", + "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@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.7", + "@babel/types": "^7.24.7", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", + "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@bem-react/classname": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@bem-react/classname/-/classname-1.6.0.tgz", @@ -2934,6 +2209,390 @@ "node": ">=10.0.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.22.0.tgz", + "integrity": "sha512-uvQR2crZ/zgzSHDvdygHyNI+ze9zwS8mqz0YtGXotSqvEE0UkYE9s+FZKQNTt1VtT719mfP3vHrUdCpxBNQZhQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.22.0.tgz", + "integrity": "sha512-PBnyP+r8vJE4ifxsWys9l+Mc2UY/yYZOpX82eoyGISXXb3dRr0M21v+s4fgRKWMFPMSf/iyowqPW/u7ScSUkjQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.22.0.tgz", + "integrity": "sha512-UKhPb3o2gAB/bfXcl58ZXTn1q2oVu1rEu/bKrCtmm+Nj5MKUbrOwR5WAixE2v+lk0amWuwPvhnPpBRLIGiq7ig==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.22.0.tgz", + "integrity": "sha512-IjTYtvIrjhR41Ijy2dDPgYjQHWG/x/A4KXYbs1fiU3efpRdoxMChK3oEZV6GPzVEzJqxFgcuBaiX1kwEvWUxSw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.22.0.tgz", + "integrity": "sha512-mqt+Go4y9wRvEz81bhKd9RpHsQR1LwU8Xm6jZRUV/xpM7cIQFbFH6wBCLPTNsdELBvfoHeumud7X78jQQJv2TA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.22.0.tgz", + "integrity": "sha512-vTaTQ9OgYc3VTaWtOE5pSuDT6H3d/qSRFRfSBbnxFfzAvYoB3pqKXA0LEbi/oT8GUOEAutspfRMqPj2ezdFaMw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.22.0.tgz", + "integrity": "sha512-0e1ZgoobJzaGnR4reD7I9rYZ7ttqdh1KPvJWnquUoDJhL0rYwdneeLailBzd2/4g/U5p4e5TIHEWa68NF2hFpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.22.0.tgz", + "integrity": "sha512-BFgyYwlCwRWyPQJtkzqq2p6pJbiiWgp0P9PNf7a5FQ1itKY4czPuOMAlFVItirSmEpRPCeImuwePNScZS0pL5Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.22.0.tgz", + "integrity": "sha512-KEMWiA9aGuPUD4BH5yjlhElLgaRXe+Eri6gKBoDazoPBTo1BXc/e6IW5FcJO9DoL19FBeCxgONyh95hLDNepIg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.22.0.tgz", + "integrity": "sha512-V/K2rctCUgC0PCXpN7AqT4hoazXKgIYugFGu/myk2+pfe6jTW2guz/TBwq4cZ7ESqusR/IzkcQaBkcjquuBWsw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.22.0.tgz", + "integrity": "sha512-r2ZZqkOMOrpUhzNwxI7uLAHIDwkfeqmTnrv1cjpL/rjllPWszgqmprd/om9oviKXUBpMqHbXmppvjAYgISb26Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.22.0.tgz", + "integrity": "sha512-qaowLrV/YOMAL2RfKQ4C/VaDzAuLDuylM2sd/LH+4OFirMl6CuDpRlCq4u49ZBaVV8pkI/Y+hTdiibvQRhojCA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.22.0.tgz", + "integrity": "sha512-hgrezzjQTRxjkQ5k08J6rtZN5PNnkWx/Rz6Kmj9gnsdCAX1I4Dn4ZPqvFRkXo55Q3pnVQJBwbdtrTO7tMGtyVA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.22.0.tgz", + "integrity": "sha512-ewxg6FLLUio883XgSjfULEmDl3VPv/TYNnRprVAS3QeGFLdCYdx1tIudBcd7n9jIdk82v1Ajov4jx87qW7h9+g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.22.0.tgz", + "integrity": "sha512-Az5XbgSJC2lE8XK8pdcutsf9RgdafWdTpUK/+6uaDdfkviw/B4JCwAfh1qVeRWwOohwdsl4ywZrWBNWxwrPLFg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.22.0.tgz", + "integrity": "sha512-8j4a2ChT9+V34NNNY9c/gMldutaJFmfMacTPq4KfNKwv2fitBCLYjee7c+Vxaha2nUhPK7cXcZpJtJ3+Y7ZdVQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.22.0.tgz", + "integrity": "sha512-JUQyOnpbAkkRFOk/AhsEemz5TfWN4FJZxVObUlnlNCbe7QBl61ZNfM4cwBXayQA6laMJMUcqLHaYQHAB6YQ95Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.22.0.tgz", + "integrity": "sha512-11PoCoHXo4HFNbLsXuMB6bpMPWGDiw7xETji6COdJss4SQZLvcgNoeSqWtATRm10Jj1uEHiaIk4N0PiN6x4Fcg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.22.0.tgz", + "integrity": "sha512-Ezlhu/YyITmXwKSB+Zu/QqD7cxrjrpiw85cc0Rbd3AWr2wsgp+dWbWOE8MqHaLW9NKMZvuL0DhbJbvzR7F6Zvg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.22.0.tgz", + "integrity": "sha512-ufjdW5tFJGUjlH9j/5cCE9lrwRffyZh+T4vYvoDKoYsC6IXbwaFeV/ENxeNXcxotF0P8CDzoICXVSbJaGBhkrw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.22.0.tgz", + "integrity": "sha512-zY6ly/AoSmKnmNTowDJsK5ehra153/5ZhqxNLfq9NRsTTltetr+yHHcQ4RW7QDqw4JC8A1uC1YmeSfK9NRcK1w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.22.0.tgz", + "integrity": "sha512-Kml5F7tv/1Maam0pbbCrvkk9vj046dPej30kFzlhXnhuCtYYBP6FGy/cLbc5yUT1lkZznGLf2OvuvmLjscO5rw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.22.0.tgz", + "integrity": "sha512-IOgwn+mYTM3RrcydP4Og5IpXh+ftN8oF+HELTXSmbWBlujuci4Qa3DTeO+LEErceisI7KUSfEIiX+WOUlpELkw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.22.0.tgz", + "integrity": "sha512-4bDHJrk2WHBXJPhy1y80X7/5b5iZTZP3LGcKIlAP1J+KqZ4zQAPMLEzftGyjjfcKbA4JDlPt/+2R/F1ZTeRgrw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -3393,14 +3052,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -3416,9 +3075,9 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "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" @@ -3441,21 +3100,15 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, "node_modules/@nicolo-ribaudo/semver-v6": { "version": "6.3.3", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz", @@ -3980,6 +3633,47 @@ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, "node_modules/@types/better-sqlite3": { "version": "7.6.4", "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.4.tgz", @@ -4023,6 +3717,15 @@ "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", "dev": true }, + "node_modules/@types/chai-as-promised": { + "version": "7.1.8", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz", + "integrity": "sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==", + "dev": true, + "dependencies": { + "@types/chai": "*" + } + }, "node_modules/@types/cheerio": { "version": "0.22.31", "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.31.tgz", @@ -4293,6 +3996,15 @@ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, + "node_modules/@types/npm-which": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/npm-which/-/npm-which-3.0.3.tgz", + "integrity": "sha512-RwK8/EXlY1/Mela2oJAqLcGSti5poulpwo3LnuhHrp1ZUMnrCRruTaw372BTyMTWUidxhe4Tva3dpM2ImBV9Cw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/opener": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@types/opener/-/opener-1.4.0.tgz", @@ -9131,9 +8843,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", + "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", "dev": true, "funding": [ { @@ -9150,10 +8862,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001629", + "electron-to-chromium": "^1.4.796", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.16" }, "bin": { "browserslist": "cli.js" @@ -9428,9 +9140,9 @@ "dev": true }, "node_modules/caniuse-lite": { - "version": "1.0.30001559", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001559.tgz", - "integrity": "sha512-cPiMKZgqgkg5LY3/ntGeLFUpi6tzddBNS58A4tnTgQw1zON7u2sZMU7SzOeVH4tj20++9ggL+V6FDOFMTaFFYA==", + "version": "1.0.30001640", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz", + "integrity": "sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA==", "dev": true, "funding": [ { @@ -13783,9 +13495,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "node_modules/electron-to-chromium": { - "version": "1.4.574", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.574.tgz", - "integrity": "sha512-bg1m8L0n02xRzx4LsTTMbBPiUd9yIR+74iPtS/Ao65CuXvhVZHP0ym1kSdDG3yHFDXqHQQBKujlN1AQ8qZnyFg==", + "version": "1.4.816", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.816.tgz", + "integrity": "sha512-EKH5X5oqC6hLmiS7/vYtZHZFTNdhsYG5NVPRN6Yn0kQHNBlT59+xSM8HBy66P5fxWpKgZbPqb+diC64ng295Jw==", "dev": true }, "node_modules/elliptic": { @@ -14115,10 +13827,49 @@ "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", "dev": true }, + "node_modules/esbuild": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.22.0.tgz", + "integrity": "sha512-zNYA6bFZsVnsU481FnGAQjLDW0Pl/8BGG7EvAp15RzUvGC+ME7hf1q7LvIfStEQBz/iEHuBJCYcOwPmNCf1Tlw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.22.0", + "@esbuild/android-arm": "0.22.0", + "@esbuild/android-arm64": "0.22.0", + "@esbuild/android-x64": "0.22.0", + "@esbuild/darwin-arm64": "0.22.0", + "@esbuild/darwin-x64": "0.22.0", + "@esbuild/freebsd-arm64": "0.22.0", + "@esbuild/freebsd-x64": "0.22.0", + "@esbuild/linux-arm": "0.22.0", + "@esbuild/linux-arm64": "0.22.0", + "@esbuild/linux-ia32": "0.22.0", + "@esbuild/linux-loong64": "0.22.0", + "@esbuild/linux-mips64el": "0.22.0", + "@esbuild/linux-ppc64": "0.22.0", + "@esbuild/linux-riscv64": "0.22.0", + "@esbuild/linux-s390x": "0.22.0", + "@esbuild/linux-x64": "0.22.0", + "@esbuild/netbsd-x64": "0.22.0", + "@esbuild/openbsd-arm64": "0.22.0", + "@esbuild/openbsd-x64": "0.22.0", + "@esbuild/sunos-x64": "0.22.0", + "@esbuild/win32-arm64": "0.22.0", + "@esbuild/win32-ia32": "0.22.0", + "@esbuild/win32-x64": "0.22.0" + } + }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" @@ -18699,8 +18450,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "node_modules/isobject": { "version": "3.0.1", @@ -18760,105 +18510,6 @@ "node": ">=6" } }, - "node_modules/istanbul-lib-instrument/node_modules/@babel/generator": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.0.tgz", - "integrity": "sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/@babel/helper-function-name": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz", - "integrity": "sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog==", - "dev": true, - "dependencies": { - "@babel/helper-get-function-arity": "^7.16.0", - "@babel/template": "^7.16.0", - "@babel/types": "^7.16.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/@babel/helper-get-function-arity": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz", - "integrity": "sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz", - "integrity": "sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/@babel/template": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.0.tgz", - "integrity": "sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.0", - "@babel/parser": "^7.16.0", - "@babel/types": "^7.16.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/@babel/traverse": { - "version": "7.16.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.3.tgz", - "integrity": "sha512-eolumr1vVMjqevCpwVO99yN/LoGL0EyHiLO5I043aYQvwOJ9eR5UsZSClHVCzfhBduMAsSzgA/6AyqPjNayJag==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.0", - "@babel/generator": "^7.16.0", - "@babel/helper-function-name": "^7.16.0", - "@babel/helper-hoist-variables": "^7.16.0", - "@babel/helper-split-export-declaration": "^7.16.0", - "@babel/parser": "^7.16.3", - "@babel/types": "^7.16.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/@babel/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz", - "integrity": "sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.15.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/istanbul-lib-instrument/node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -19187,9 +18838,9 @@ } }, "node_modules/js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "node_modules/js-yaml": { @@ -21211,9 +20862,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/noms": { @@ -21277,6 +20928,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/npm-path": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", + "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", + "dependencies": { + "which": "^1.2.10" + }, + "bin": { + "npm-path": "bin/npm-path" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/npm-run-all": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", @@ -21430,6 +21095,27 @@ "node": ">=4" } }, + "node_modules/npm-which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", + "integrity": "sha512-CM8vMpeFQ7MAPin0U3wzDhSGV0hMHNwHU0wjo402IVizPDrs45jSfSuoC+wThevY88LQti8VvaAnqYAeVy3I1A==", + "dependencies": { + "commander": "^2.9.0", + "npm-path": "^2.0.2", + "which": "^1.2.10" + }, + "bin": { + "npm-which": "bin/npm-which.js" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/npm-which/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, "node_modules/nth-check": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", @@ -22412,9 +22098,9 @@ "dev": true }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, "node_modules/picomatch": { @@ -22470,6 +22156,15 @@ "node": ">=0.10.0" } }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -28932,9 +28627,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.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "dev": true, "funding": [ { @@ -28951,8 +28646,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -31092,7 +30787,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -31706,163 +31400,70 @@ } }, "@babel/code-frame": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", - "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", + "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==", "dev": true, "requires": { - "@babel/highlight": "^7.22.10", - "chalk": "^2.4.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" } }, "@babel/compat-data": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.6.tgz", - "integrity": "sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", + "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", "dev": true }, "@babel/core": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.8.tgz", - "integrity": "sha512-75+KxFB4CZqYRXjx4NlR4J7yGvKumBuZTmV4NV6v09dVXXkuYVYLT68N6HCzLvfJ+fWCxQsntNzKwwIXL4bHnw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", + "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", "dev": true, "requires": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-module-transforms": "^7.22.5", - "@babel/helpers": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.8", - "@babel/types": "^7.22.5", - "@nicolo-ribaudo/semver-v6": "^6.3.3", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helpers": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "dependencies": { - "@babel/generator": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz", - "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "requires": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", - "globals": "^11.1.0" - } + "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 }, - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true } } }, + "@babel/generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", + "dev": true, + "requires": { + "@babel/types": "^7.24.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + } + }, "@babel/helper-annotate-as-pure": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", @@ -31870,19 +31471,6 @@ "dev": true, "requires": { "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/helper-builder-binary-assignment-operator-visitor": { @@ -31892,32 +31480,27 @@ "dev": true, "requires": { "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/helper-compilation-targets": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.6.tgz", - "integrity": "sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", + "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", "dev": true, "requires": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-validator-option": "^7.22.5", - "@nicolo-ribaudo/semver-v6": "^6.3.3", - "browserslist": "^4.21.9", - "lru-cache": "^5.1.1" + "@babel/compat-data": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } } }, "@babel/helper-create-class-features-plugin": { @@ -31935,49 +31518,6 @@ "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", "@nicolo-ribaudo/semver-v6": "^6.3.3" - }, - "dependencies": { - "@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "requires": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/helper-create-regexp-features-plugin": { @@ -32036,31 +31576,31 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", - "dev": true + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "dev": true, + "requires": { + "@babel/types": "^7.24.7" + } + }, + "@babel/helper-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", + "dev": true, + "requires": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" + } }, "@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", "dev": true, "requires": { - "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } + "@babel/types": "^7.24.7" } }, "@babel/helper-member-expression-to-functions": { @@ -32070,130 +31610,29 @@ "dev": true, "requires": { "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dev": true, "requires": { - "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" } }, "@babel/helper-module-transforms": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz", - "integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", + "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/generator": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz", - "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "requires": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" } }, "@babel/helper-optimise-call-expression": { @@ -32203,25 +31642,12 @@ "dev": true, "requires": { "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", + "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", "dev": true }, "@babel/helper-remap-async-to-generator": { @@ -32234,19 +31660,6 @@ "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-wrap-function": "^7.22.5", "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/helper-replace-supers": { @@ -32261,101 +31674,16 @@ "@babel/template": "^7.22.5", "@babel/traverse": "^7.22.5", "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/generator": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz", - "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "requires": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dev": true, "requires": { - "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" } }, "@babel/helper-skip-transparent-expression-wrappers": { @@ -32365,37 +31693,33 @@ "dev": true, "requires": { "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", + "dev": true, + "requires": { + "@babel/types": "^7.24.7" } }, "@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", + "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", "dev": true }, "@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "dev": true }, "@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", + "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", "dev": true }, "@babel/helper-wrap-function": { @@ -32408,174 +31732,28 @@ "@babel/template": "^7.22.5", "@babel/traverse": "^7.22.5", "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/generator": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz", - "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "requires": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/helpers": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", - "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", + "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", "dev": true, "requires": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.6", - "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/generator": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz", - "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "requires": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" } }, "@babel/highlight": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", - "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "dependencies": { "ansi-styles": { @@ -32613,12 +31791,6 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -32631,9 +31803,9 @@ } }, "@babel/parser": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", - "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", "dev": true }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { @@ -32940,49 +32112,6 @@ "@babel/helper-replace-supers": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", "globals": "^11.1.0" - }, - "dependencies": { - "@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "requires": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/plugin-transform-computed-properties": { @@ -32993,30 +32122,6 @@ "requires": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/template": "^7.22.5" - }, - "dependencies": { - "@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/plugin-transform-destructuring": { @@ -33095,40 +32200,6 @@ "@babel/helper-compilation-targets": "^7.22.5", "@babel/helper-function-name": "^7.22.5", "@babel/helper-plugin-utils": "^7.22.5" - }, - "dependencies": { - "@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "requires": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - } - }, - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/plugin-transform-json-strings": { @@ -33180,14 +32251,14 @@ } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz", - "integrity": "sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz", + "integrity": "sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7" } }, "@babel/plugin-transform-modules-systemjs": { @@ -33355,19 +32426,6 @@ "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-jsx": "^7.22.5", "@babel/types": "^7.22.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/plugin-transform-react-jsx-development": { @@ -33616,19 +32674,6 @@ "babel-plugin-polyfill-corejs3": "^0.8.2", "babel-plugin-polyfill-regenerator": "^0.5.1", "core-js-compat": "^3.31.0" - }, - "dependencies": { - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/preset-modules": { @@ -33642,19 +32687,6 @@ "@babel/plugin-transform-dotall-regex": "^7.4.4", "@babel/types": "^7.4.4", "esutils": "^2.0.2" - }, - "dependencies": { - "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/preset-react": { @@ -33705,6 +32737,46 @@ } } }, + "@babel/template": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" + } + }, + "@babel/traverse": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", + "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@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.7", + "@babel/types": "^7.24.7", + "debug": "^4.3.1", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", + "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + } + }, "@bem-react/classname": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@bem-react/classname/-/classname-1.6.0.tgz", @@ -33738,6 +32810,174 @@ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true }, + "@esbuild/aix-ppc64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.22.0.tgz", + "integrity": "sha512-uvQR2crZ/zgzSHDvdygHyNI+ze9zwS8mqz0YtGXotSqvEE0UkYE9s+FZKQNTt1VtT719mfP3vHrUdCpxBNQZhQ==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.22.0.tgz", + "integrity": "sha512-PBnyP+r8vJE4ifxsWys9l+Mc2UY/yYZOpX82eoyGISXXb3dRr0M21v+s4fgRKWMFPMSf/iyowqPW/u7ScSUkjQ==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.22.0.tgz", + "integrity": "sha512-UKhPb3o2gAB/bfXcl58ZXTn1q2oVu1rEu/bKrCtmm+Nj5MKUbrOwR5WAixE2v+lk0amWuwPvhnPpBRLIGiq7ig==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.22.0.tgz", + "integrity": "sha512-IjTYtvIrjhR41Ijy2dDPgYjQHWG/x/A4KXYbs1fiU3efpRdoxMChK3oEZV6GPzVEzJqxFgcuBaiX1kwEvWUxSw==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.22.0.tgz", + "integrity": "sha512-mqt+Go4y9wRvEz81bhKd9RpHsQR1LwU8Xm6jZRUV/xpM7cIQFbFH6wBCLPTNsdELBvfoHeumud7X78jQQJv2TA==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.22.0.tgz", + "integrity": "sha512-vTaTQ9OgYc3VTaWtOE5pSuDT6H3d/qSRFRfSBbnxFfzAvYoB3pqKXA0LEbi/oT8GUOEAutspfRMqPj2ezdFaMw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.22.0.tgz", + "integrity": "sha512-0e1ZgoobJzaGnR4reD7I9rYZ7ttqdh1KPvJWnquUoDJhL0rYwdneeLailBzd2/4g/U5p4e5TIHEWa68NF2hFpQ==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.22.0.tgz", + "integrity": "sha512-BFgyYwlCwRWyPQJtkzqq2p6pJbiiWgp0P9PNf7a5FQ1itKY4czPuOMAlFVItirSmEpRPCeImuwePNScZS0pL5Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.22.0.tgz", + "integrity": "sha512-KEMWiA9aGuPUD4BH5yjlhElLgaRXe+Eri6gKBoDazoPBTo1BXc/e6IW5FcJO9DoL19FBeCxgONyh95hLDNepIg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.22.0.tgz", + "integrity": "sha512-V/K2rctCUgC0PCXpN7AqT4hoazXKgIYugFGu/myk2+pfe6jTW2guz/TBwq4cZ7ESqusR/IzkcQaBkcjquuBWsw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.22.0.tgz", + "integrity": "sha512-r2ZZqkOMOrpUhzNwxI7uLAHIDwkfeqmTnrv1cjpL/rjllPWszgqmprd/om9oviKXUBpMqHbXmppvjAYgISb26Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.22.0.tgz", + "integrity": "sha512-qaowLrV/YOMAL2RfKQ4C/VaDzAuLDuylM2sd/LH+4OFirMl6CuDpRlCq4u49ZBaVV8pkI/Y+hTdiibvQRhojCA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.22.0.tgz", + "integrity": "sha512-hgrezzjQTRxjkQ5k08J6rtZN5PNnkWx/Rz6Kmj9gnsdCAX1I4Dn4ZPqvFRkXo55Q3pnVQJBwbdtrTO7tMGtyVA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.22.0.tgz", + "integrity": "sha512-ewxg6FLLUio883XgSjfULEmDl3VPv/TYNnRprVAS3QeGFLdCYdx1tIudBcd7n9jIdk82v1Ajov4jx87qW7h9+g==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.22.0.tgz", + "integrity": "sha512-Az5XbgSJC2lE8XK8pdcutsf9RgdafWdTpUK/+6uaDdfkviw/B4JCwAfh1qVeRWwOohwdsl4ywZrWBNWxwrPLFg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.22.0.tgz", + "integrity": "sha512-8j4a2ChT9+V34NNNY9c/gMldutaJFmfMacTPq4KfNKwv2fitBCLYjee7c+Vxaha2nUhPK7cXcZpJtJ3+Y7ZdVQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.22.0.tgz", + "integrity": "sha512-JUQyOnpbAkkRFOk/AhsEemz5TfWN4FJZxVObUlnlNCbe7QBl61ZNfM4cwBXayQA6laMJMUcqLHaYQHAB6YQ95Q==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.22.0.tgz", + "integrity": "sha512-11PoCoHXo4HFNbLsXuMB6bpMPWGDiw7xETji6COdJss4SQZLvcgNoeSqWtATRm10Jj1uEHiaIk4N0PiN6x4Fcg==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-arm64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.22.0.tgz", + "integrity": "sha512-Ezlhu/YyITmXwKSB+Zu/QqD7cxrjrpiw85cc0Rbd3AWr2wsgp+dWbWOE8MqHaLW9NKMZvuL0DhbJbvzR7F6Zvg==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.22.0.tgz", + "integrity": "sha512-ufjdW5tFJGUjlH9j/5cCE9lrwRffyZh+T4vYvoDKoYsC6IXbwaFeV/ENxeNXcxotF0P8CDzoICXVSbJaGBhkrw==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.22.0.tgz", + "integrity": "sha512-zY6ly/AoSmKnmNTowDJsK5ehra153/5ZhqxNLfq9NRsTTltetr+yHHcQ4RW7QDqw4JC8A1uC1YmeSfK9NRcK1w==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.22.0.tgz", + "integrity": "sha512-Kml5F7tv/1Maam0pbbCrvkk9vj046dPej30kFzlhXnhuCtYYBP6FGy/cLbc5yUT1lkZznGLf2OvuvmLjscO5rw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.22.0.tgz", + "integrity": "sha512-IOgwn+mYTM3RrcydP4Og5IpXh+ftN8oF+HELTXSmbWBlujuci4Qa3DTeO+LEErceisI7KUSfEIiX+WOUlpELkw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.22.0.tgz", + "integrity": "sha512-4bDHJrk2WHBXJPhy1y80X7/5b5iZTZP3LGcKIlAP1J+KqZ4zQAPMLEzftGyjjfcKbA4JDlPt/+2R/F1ZTeRgrw==", + "dev": true, + "optional": true + }, "@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -34072,14 +33312,14 @@ } }, "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "requires": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" } }, "@jridgewell/resolve-uri": { @@ -34089,9 +33329,9 @@ "dev": true }, "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "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": { @@ -34111,21 +33351,13 @@ "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - }, - "dependencies": { - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - } + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "@nicolo-ribaudo/semver-v6": { @@ -34466,6 +33698,47 @@ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, + "@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "requires": { + "@babel/types": "^7.20.7" + } + }, "@types/better-sqlite3": { "version": "7.6.4", "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.4.tgz", @@ -34509,6 +33782,15 @@ "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", "dev": true }, + "@types/chai-as-promised": { + "version": "7.1.8", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz", + "integrity": "sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==", + "dev": true, + "requires": { + "@types/chai": "*" + } + }, "@types/cheerio": { "version": "0.22.31", "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.31.tgz", @@ -34781,6 +34063,15 @@ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, + "@types/npm-which": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/npm-which/-/npm-which-3.0.3.tgz", + "integrity": "sha512-RwK8/EXlY1/Mela2oJAqLcGSti5poulpwo3LnuhHrp1ZUMnrCRruTaw372BTyMTWUidxhe4Tva3dpM2ImBV9Cw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/opener": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@types/opener/-/opener-1.4.0.tgz", @@ -38492,15 +37783,15 @@ } }, "browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", + "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001629", + "electron-to-chromium": "^1.4.796", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.16" } }, "buffer": { @@ -38713,9 +38004,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001559", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001559.tgz", - "integrity": "sha512-cPiMKZgqgkg5LY3/ntGeLFUpi6tzddBNS58A4tnTgQw1zON7u2sZMU7SzOeVH4tj20++9ggL+V6FDOFMTaFFYA==", + "version": "1.0.30001640", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz", + "integrity": "sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA==", "dev": true }, "center-align": { @@ -42082,9 +41373,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.4.574", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.574.tgz", - "integrity": "sha512-bg1m8L0n02xRzx4LsTTMbBPiUd9yIR+74iPtS/Ao65CuXvhVZHP0ym1kSdDG3yHFDXqHQQBKujlN1AQ8qZnyFg==", + "version": "1.4.816", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.816.tgz", + "integrity": "sha512-EKH5X5oqC6hLmiS7/vYtZHZFTNdhsYG5NVPRN6Yn0kQHNBlT59+xSM8HBy66P5fxWpKgZbPqb+diC64ng295Jw==", "dev": true }, "elliptic": { @@ -42362,10 +41653,42 @@ "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", "dev": true }, + "esbuild": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.22.0.tgz", + "integrity": "sha512-zNYA6bFZsVnsU481FnGAQjLDW0Pl/8BGG7EvAp15RzUvGC+ME7hf1q7LvIfStEQBz/iEHuBJCYcOwPmNCf1Tlw==", + "dev": true, + "requires": { + "@esbuild/aix-ppc64": "0.22.0", + "@esbuild/android-arm": "0.22.0", + "@esbuild/android-arm64": "0.22.0", + "@esbuild/android-x64": "0.22.0", + "@esbuild/darwin-arm64": "0.22.0", + "@esbuild/darwin-x64": "0.22.0", + "@esbuild/freebsd-arm64": "0.22.0", + "@esbuild/freebsd-x64": "0.22.0", + "@esbuild/linux-arm": "0.22.0", + "@esbuild/linux-arm64": "0.22.0", + "@esbuild/linux-ia32": "0.22.0", + "@esbuild/linux-loong64": "0.22.0", + "@esbuild/linux-mips64el": "0.22.0", + "@esbuild/linux-ppc64": "0.22.0", + "@esbuild/linux-riscv64": "0.22.0", + "@esbuild/linux-s390x": "0.22.0", + "@esbuild/linux-x64": "0.22.0", + "@esbuild/netbsd-x64": "0.22.0", + "@esbuild/openbsd-arm64": "0.22.0", + "@esbuild/openbsd-x64": "0.22.0", + "@esbuild/sunos-x64": "0.22.0", + "@esbuild/win32-arm64": "0.22.0", + "@esbuild/win32-ia32": "0.22.0", + "@esbuild/win32-x64": "0.22.0" + } + }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true }, "escape-html": { @@ -45857,8 +45180,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { "version": "3.0.1", @@ -45906,84 +45228,6 @@ "semver": "^6.0.0" }, "dependencies": { - "@babel/generator": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.0.tgz", - "integrity": "sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew==", - "dev": true, - "requires": { - "@babel/types": "^7.16.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-function-name": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz", - "integrity": "sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.16.0", - "@babel/template": "^7.16.0", - "@babel/types": "^7.16.0" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz", - "integrity": "sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ==", - "dev": true, - "requires": { - "@babel/types": "^7.16.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz", - "integrity": "sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw==", - "dev": true, - "requires": { - "@babel/types": "^7.16.0" - } - }, - "@babel/template": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.0.tgz", - "integrity": "sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.0", - "@babel/parser": "^7.16.0", - "@babel/types": "^7.16.0" - } - }, - "@babel/traverse": { - "version": "7.16.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.3.tgz", - "integrity": "sha512-eolumr1vVMjqevCpwVO99yN/LoGL0EyHiLO5I043aYQvwOJ9eR5UsZSClHVCzfhBduMAsSzgA/6AyqPjNayJag==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.0", - "@babel/generator": "^7.16.0", - "@babel/helper-function-name": "^7.16.0", - "@babel/helper-hoist-variables": "^7.16.0", - "@babel/helper-split-export-declaration": "^7.16.0", - "@babel/parser": "^7.16.3", - "@babel/types": "^7.16.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz", - "integrity": "sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.15.7", - "to-fast-properties": "^2.0.0" - } - }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -46233,9 +45477,9 @@ "integrity": "sha512-Gu1wtWzXBzGeye/j9BuyplGHscwqKRZodp/0M1vyBc19RJpblSwKGu099KwwaTx9cRIV+Qupk8xUMfEiGfFqSA==" }, "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "js-yaml": { @@ -47821,9 +47065,9 @@ "dev": true }, "node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "noms": { @@ -47880,6 +47124,14 @@ "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", "dev": true }, + "npm-path": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", + "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", + "requires": { + "which": "^1.2.10" + } + }, "npm-run-all": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", @@ -48000,6 +47252,23 @@ "path-key": "^2.0.0" } }, + "npm-which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", + "integrity": "sha512-CM8vMpeFQ7MAPin0U3wzDhSGV0hMHNwHU0wjo402IVizPDrs45jSfSuoC+wThevY88LQti8VvaAnqYAeVy3I1A==", + "requires": { + "commander": "^2.9.0", + "npm-path": "^2.0.2", + "which": "^1.2.10" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + } + } + }, "nth-check": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", @@ -48769,9 +48038,9 @@ "dev": true }, "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, "picomatch": { @@ -48806,6 +48075,12 @@ "pinkie": "^2.0.0" } }, + "pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true + }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -53881,13 +53156,13 @@ "dev": 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.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "dev": true, "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" } }, "uri-js": { @@ -55526,7 +54801,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, "requires": { "isexe": "^2.0.0" } diff --git a/package.json b/package.json index 5c66a0dd7..b8bf156c9 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,10 @@ "./playwright": "./build/playwright.js" }, "scripts": { - "build": "rimraf build && npm run build:client && npm run build:server", + "build": "rimraf build && npm run build:client && npm run build:server && npm run build-bundle -- --minify", "build:client": "cross-env NODE_ENV=production webpack build --config=webpack.prod.js --progress && npm run copy-static", "build:server": "npx tsc", + "build-bundle": "esbuild ./lib/bundle/index.ts --outdir=./build/lib/bundle --bundle --format=cjs --platform=node --target=ES2021", "copy-static": "copyfiles 'lib/static/icons/*' .npmignore build", "check-types": "tsc --project tsconfig.spec.json", "coverage": "nyc npm run test-unit", @@ -33,9 +34,10 @@ "start": "NODE_ENV=development webpack serve --config=webpack.dev.js --progress", "commitmsg": "conventional-changelog-lint -e", "release": "standard-version", - "watch": "concurrently -c 'auto' -n 'server,client' 'npm:watch:server' 'npm:watch:client'", + "watch": "concurrently -c 'auto' -n 'server,client' 'npm:watch:server' 'npm:watch:client' 'npm:watch:bundle'", "watch:client": "npm run copy-static && NODE_ENV=development webpack watch --config=webpack.dev.js --progress", - "watch:server": "npx tsc --watch" + "watch:server": "npx tsc --watch", + "watch:bundle": "npm run build-bundle -- --watch" }, "workspaces": [ "test/func/fixtures/*", @@ -99,6 +101,7 @@ "lodash": "^4.17.4", "looks-same": "^8.2.1", "nested-error-stacks": "^2.1.0", + "npm-which": "^3.0.1", "opener": "^1.4.3", "ora": "^5.4.1", "p-queue": "^5.0.0", @@ -109,7 +112,8 @@ "worker-farm": "^1.7.0" }, "devDependencies": { - "@babel/core": "^7.22.5", + "@babel/core": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", "@babel/plugin-transform-runtime": "^7.22.5", "@babel/preset-env": "^7.22.5", "@babel/preset-react": "^7.22.5", @@ -118,9 +122,11 @@ "@gravity-ui/uikit": "^6.20.0", "@playwright/test": "^1.44.1", "@swc/core": "^1.3.64", + "@types/babel__core": "^7.20.5", "@types/better-sqlite3": "^7.6.4", "@types/bluebird": "^3.5.3", "@types/chai": "^4.3.5", + "@types/chai-as-promised": "^7.1.1", "@types/debug": "^4.1.8", "@types/enzyme": "^3.10.13", "@types/escape-html": "^1.0.4", @@ -130,6 +136,7 @@ "@types/json-stringify-safe": "^5.0.2", "@types/lodash": "^4.14.195", "@types/nested-error-stacks": "^2.1.0", + "@types/npm-which": "^3.0.3", "@types/opener": "^1.4.0", "@types/proxyquire": "^1.3.28", "@types/sinon": "^4.3.3", @@ -152,6 +159,7 @@ "css-minimizer-webpack-plugin": "^5.0.1", "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.15.4", + "esbuild": "^0.22.0", "eslint": "^8.43.0", "eslint-config-gemini-testing": "^2.8.0", "eslint-plugin-react": "^7.32.2", @@ -181,6 +189,7 @@ "npm-run-all": "^4.1.5", "nyc": "^14.1.1", "path-browserify": "^1.0.1", + "pirates": "^4.0.6", "prop-types": "^15.6.0", "proxyquire": "^1.7.11", "raf": "^3.4.0", diff --git a/playwright.ts b/playwright.ts index 9f7c42e5a..6cd827c4e 100644 --- a/playwright.ts +++ b/playwright.ts @@ -55,7 +55,7 @@ class MyReporter implements Reporter { reportPath: htmlReporter.config.path }); - this._staticReportBuilder = StaticReportBuilder.create(htmlReporter, config, {dbClient, imagesInfoSaver}); + this._staticReportBuilder = StaticReportBuilder.create({htmlReporter, reporterConfig: config, dbClient, imagesInfoSaver}); this._staticReportBuilder.registerWorkers(workers); await this._staticReportBuilder.saveStaticFiles(); diff --git a/test/unit/lib/adapters/config/playwright.ts b/test/unit/lib/adapters/config/playwright.ts new file mode 100644 index 000000000..6e25893bf --- /dev/null +++ b/test/unit/lib/adapters/config/playwright.ts @@ -0,0 +1,208 @@ +import path from 'node:path'; +import sinon from 'sinon'; + +import {PlaywrightConfigAdapter, DEFAULT_BROWSER_ID, type PwtConfig, type PwtProject} from '../../../../../lib/adapters/config/playwright'; +import {PlaywrightTestAdapter, type PwtRawTest} from '../../../../../lib/adapters/test/playwright'; + +describe('lib/adapters/config/testplane', () => { + const sandbox = sinon.createSandbox(); + + afterEach(() => sandbox.restore()); + + describe('original', () => { + it('should return original config', () => { + const config = {} as PwtConfig; + + assert.equal(PlaywrightConfigAdapter.create(config).original, config); + }); + }); + + describe('tolerance', () => { + it('should return default value', () => { + assert.equal(PlaywrightConfigAdapter.create({} as PwtConfig).tolerance, 2.3); + }); + }); + + describe('antialiasingTolerance', () => { + it('should return default value', () => { + assert.equal(PlaywrightConfigAdapter.create({} as PwtConfig).antialiasingTolerance, 4); + }); + }); + + describe('getBrowserIds', () => { + it('should return browsers from "projects" field', () => { + const config = { + projects: [ + {name: 'yabro1'}, + {name: 'yabro2'} + ] + } as PwtConfig; + + assert.deepEqual(PlaywrightConfigAdapter.create(config).getBrowserIds(), ['yabro1', 'yabro2']); + }); + + it('should return default browser if "projects" are not specified', () => { + assert.deepEqual(PlaywrightConfigAdapter.create({} as PwtConfig).getBrowserIds(), [DEFAULT_BROWSER_ID]); + }); + }); + + describe('getScreenshotPath', () => { + const mkConfig_ = ({cfg, prjCfg}: {cfg?: Partial, prjCfg?: Partial} = {cfg: {}, prjCfg: {}}): PwtConfig => ({ + snapshotPathTemplate: 'cfg_{testDir}/{snapshotDir}/{snapshotSuffix}/{testFileDir}/{platform}/{projectName}/{testName}/{testFileName}/{testFilePath}/{arg}/{ext}', + testDir: './cfg_tests', + snapshotDir: './cfg_snapshots', + ...cfg, + projects: [{ + name: 'prj_bro', + snapshotPathTemplate: 'prj_{testDir}/{snapshotDir}/{snapshotSuffix}/{testFileDir}/{platform}/{projectName}/{testName}/{testFileName}/{testFilePath}/{arg}/{ext}', + testDir: './prj_tests', + snapshotDir: './prj_snapshots', + ...prjCfg + }] + } as PwtConfig); + + const mkTestAdapter_ = (opts: Partial = {}): PlaywrightTestAdapter => { + const test = { + file: 'default-path.ts', + browserName: 'default-bro', + title: 'suite test', + titlePath: ['suite', 'test'], + ...opts + }; + + return PlaywrightTestAdapter.create(test); + }; + + describe('use options from project config', () => { + it('should return screenshot path with "testDir"', () => { + const config = mkConfig_({prjCfg: { + name: 'yabro', + snapshotPathTemplate: '{testDir}', + testDir: './tests' + }}); + const testAdapter = mkTestAdapter_({browserName: 'yabro'}); + const configAdapter = PlaywrightConfigAdapter.create(config); + + assert.equal(configAdapter.getScreenshotPath(testAdapter, 'plain'), path.resolve('./tests')); + }); + + it('should return screenshot path with "snapshotDir"', () => { + const config = mkConfig_({prjCfg: { + name: 'yabro', + snapshotPathTemplate: '{snapshotDir}', + snapshotDir: './snapshots' + }}); + const testAdapter = mkTestAdapter_({browserName: 'yabro'}); + const configAdapter = PlaywrightConfigAdapter.create(config); + + assert.equal(configAdapter.getScreenshotPath(testAdapter, 'plain'), path.resolve('./snapshots')); + }); + + ['snapshotSuffix', 'platform'].forEach(fieldName => { + it(`should return screenshot path with "${fieldName}"`, () => { + const config = mkConfig_({prjCfg: { + name: 'yabro', + snapshotPathTemplate: `{${fieldName}}` + }}); + const testAdapter = mkTestAdapter_({browserName: 'yabro'}); + const configAdapter = PlaywrightConfigAdapter.create(config); + + assert.equal(configAdapter.getScreenshotPath(testAdapter, 'plain'), path.resolve(process.platform)); + }); + }); + + it('should return screenshot path with "testFileDir"', () => { + const config = mkConfig_({prjCfg: { + name: 'yabro', + snapshotPathTemplate: '{testFileDir}' + }}); + const testAdapter = mkTestAdapter_({browserName: 'yabro', file: './dir/file.test.ts'}); + const configAdapter = PlaywrightConfigAdapter.create(config); + + assert.equal(configAdapter.getScreenshotPath(testAdapter, 'plain'), path.resolve('./dir')); + }); + + it('should return screenshot path with "projectName"', () => { + const config = mkConfig_({prjCfg: { + name: 'yabro/123', + snapshotPathTemplate: '{projectName}' + }}); + const testAdapter = mkTestAdapter_({browserName: 'yabro/123'}); + const configAdapter = PlaywrightConfigAdapter.create(config); + + assert.equal(configAdapter.getScreenshotPath(testAdapter, 'plain'), path.resolve('yabro-123')); + }); + + it('should return screenshot path with "testName"', () => { + const config = mkConfig_({prjCfg: { + name: 'yabro', + snapshotPathTemplate: '{testName}' + }}); + const testAdapter = mkTestAdapter_({browserName: 'yabro', titlePath: ['foo', 'bar']}); + const configAdapter = PlaywrightConfigAdapter.create(config); + + assert.equal(configAdapter.getScreenshotPath(testAdapter, 'plain'), path.resolve('foo-bar')); + }); + + it('should return screenshot path with "testFileName"', () => { + const config = mkConfig_({prjCfg: { + name: 'yabro', + snapshotPathTemplate: '{testFileName}' + }}); + const testAdapter = mkTestAdapter_({browserName: 'yabro', file: './dir/file.test.ts'}); + const configAdapter = PlaywrightConfigAdapter.create(config); + + assert.equal(configAdapter.getScreenshotPath(testAdapter, 'plain'), path.resolve('file.test.ts')); + }); + + it('should return screenshot path with "testFilePath"', () => { + const config = mkConfig_({prjCfg: { + name: 'yabro', + snapshotPathTemplate: '{testFilePath}' + }}); + const testAdapter = mkTestAdapter_({browserName: 'yabro', file: './dir/file.test.ts'}); + const configAdapter = PlaywrightConfigAdapter.create(config); + + assert.equal(configAdapter.getScreenshotPath(testAdapter, 'plain'), path.resolve('./dir/file.test.ts')); + }); + + it('should return screenshot path with "arg"', () => { + const config = mkConfig_({prjCfg: { + name: 'yabro', + snapshotPathTemplate: '{arg}' + }}); + const testAdapter = mkTestAdapter_({browserName: 'yabro'}); + const configAdapter = PlaywrightConfigAdapter.create(config); + + assert.equal(configAdapter.getScreenshotPath(testAdapter, 'first/plain'), path.resolve('first/plain')); + }); + + it('should return screenshot path with "ext"', () => { + const config = mkConfig_({prjCfg: { + name: 'yabro', + snapshotPathTemplate: '{ext}' + }}); + const testAdapter = mkTestAdapter_({browserName: 'yabro'}); + const configAdapter = PlaywrightConfigAdapter.create(config); + + assert.equal(configAdapter.getScreenshotPath(testAdapter, 'plain'), path.resolve('.png')); + }); + }); + + it('should return screenshot path with options from main config', () => { + const config = mkConfig_({cfg: { + snapshotPathTemplate: '{testDir}/{snapshotDir}/{snapshotSuffix}/{testFileDir}/{platform}/{projectName}/{testName}/{testFileName}/{testFilePath}/{arg}/{ext}', + testDir: './tests', + snapshotDir: './snapshots' + }}); + const testAdapter = mkTestAdapter_({browserName: 'yabro/123', file: './dir/file.test.ts', titlePath: ['foo', 'bar']}); + const configAdapter = PlaywrightConfigAdapter.create(config); + + assert.equal( + configAdapter.getScreenshotPath(testAdapter, 'first/plain'), + `${path.resolve('./tests')}${path.resolve('./snapshots')}/${process.platform}/dir/` + + `${process.platform}/yabro-123/foo-bar/file.test.ts/dir/file.test.ts/first/plain/.png` + ); + }); + }); +}); diff --git a/test/unit/lib/adapters/test-collection/playwright.ts b/test/unit/lib/adapters/test-collection/playwright.ts new file mode 100644 index 000000000..8afe54eb8 --- /dev/null +++ b/test/unit/lib/adapters/test-collection/playwright.ts @@ -0,0 +1,39 @@ +import sinon from 'sinon'; +import {PlaywrightTestCollectionAdapter} from '../../../../../lib/adapters/test-collection/playwright'; +import {PlaywrightTestAdapter, type PwtRawTest} from '../../../../../lib/adapters/test/playwright'; + +describe('lib/adapters/test-collection/playwright', () => { + const sandbox = sinon.createSandbox(); + + const mkTest_ = (opts: Partial = {}): PwtRawTest => ({ + file: 'default-path.ts', + browserName: 'default-bro', + title: 'suite test', + titlePath: ['suite', 'test'], + ...opts + }); + + afterEach(() => sandbox.restore()); + + describe('eachTest', () => { + it('should call passed callback with test adapter and browserId', () => { + const test1 = mkTest_({browserName: 'yabro1'}); + const testAdapter1 = {} as PlaywrightTestAdapter; + const test2 = mkTest_({browserName: 'yabro2'}); + const testAdapter2 = {} as PlaywrightTestAdapter; + + sandbox.stub(PlaywrightTestAdapter, 'create') + .withArgs(test1).returns(testAdapter1) + .withArgs(test2).returns(testAdapter2); + + const testCollectionAdapter = PlaywrightTestCollectionAdapter.create([test1, test2]); + + const cb = sinon.stub(); + testCollectionAdapter.eachTest(cb); + + assert.calledTwice(cb); + assert.calledWith(cb.firstCall, testAdapter1, 'yabro1'); + assert.calledWith(cb.secondCall, testAdapter2, 'yabro2'); + }); + }); +}); diff --git a/test/unit/lib/adapters/test-result/playwright.ts b/test/unit/lib/adapters/test-result/playwright.ts index 139d72880..c7f3567ad 100644 --- a/test/unit/lib/adapters/test-result/playwright.ts +++ b/test/unit/lib/adapters/test-result/playwright.ts @@ -141,7 +141,7 @@ describe('PlaywrightTestResultAdapter', () => { it('should return fullName', () => { const adapter = new PlaywrightTestResultAdapter(mkTestCase(), mkTestResult(), UNKNOWN_ATTEMPT); - assert.strictEqual(adapter.fullName, 'describe › test'); + assert.strictEqual(adapter.fullName, 'describe test'); }); }); @@ -170,7 +170,7 @@ describe('PlaywrightTestResultAdapter', () => { it('should return imageDir', () => { const adapter = new PlaywrightTestResultAdapter(mkTestCase(), mkTestResult(), UNKNOWN_ATTEMPT); - assert.strictEqual(adapter.imageDir, '4050de5'); + assert.strictEqual(adapter.imageDir, '75bcb6c'); }); }); diff --git a/test/unit/lib/adapters/test/playwright.ts b/test/unit/lib/adapters/test/playwright.ts new file mode 100644 index 000000000..2b1dec1b0 --- /dev/null +++ b/test/unit/lib/adapters/test/playwright.ts @@ -0,0 +1,273 @@ +import sinon, {type SinonStub} from 'sinon'; +import type {TestCase, TestResult, FullProject} from '@playwright/test/reporter'; + +import {PlaywrightTestAdapter, type PwtRawTest} from '../../../../../lib/adapters/test/playwright'; +import {PlaywrightTestResultAdapter, type PlaywrightAttachment} from '../../../../../lib/adapters/test-result/playwright'; +import {TestStatus, UNKNOWN_ATTEMPT} from '../../../../../lib/constants'; +import type {ImageDiffError} from '../../../../../lib/errors'; + +describe('lib/adapters/test/playwright', () => { + const sandbox = sinon.createSandbox(); + + const mkTest_ = (opts: Partial = {}): PwtRawTest => ({ + file: 'default-path.ts', + browserName: 'default-bro', + title: 'suite test', + titlePath: ['suite', 'test'], + ...opts + }); + + afterEach(() => sandbox.restore()); + + describe('originalTest', () => { + it('shoult return original test instance', () => { + const test = mkTest_(); + + assert.equal(PlaywrightTestAdapter.create(test).originalTest, test); + }); + }); + + describe('id', () => { + it('should return title as "id" from original test', () => { + const test = mkTest_({title: 'title'}); + + assert.equal(PlaywrightTestAdapter.create(test).id, 'title'); + }); + }); + + describe('file', () => { + it('should return file from original test', () => { + const test = mkTest_({file: 'some-file.ts'}); + + assert.equal(PlaywrightTestAdapter.create(test).file, 'some-file.ts'); + }); + }); + + describe('title', () => { + it('should return title from original test', () => { + const test = mkTest_({title: 'title'}); + + assert.equal(PlaywrightTestAdapter.create(test).title, 'title'); + }); + }); + + describe('titlePath', () => { + it('should return titlePath from original test', () => { + const test = mkTest_({titlePath: ['suite', 'test']}); + + assert.deepEqual(PlaywrightTestAdapter.create(test).titlePath, ['suite', 'test']); + }); + }); + + (['pending', 'disabled', 'silentSkip'] as const).forEach(fieldName => { + describe(fieldName, () => { + it('should return false by default', () => { + assert.isFalse(PlaywrightTestAdapter.create(mkTest_())[fieldName]); + }); + }); + }); + + (['skipReason', 'browserVersion'] as const).forEach(fieldName => { + describe(fieldName, () => { + it('should return empty line by default', () => { + assert.equal(PlaywrightTestAdapter.create(mkTest_())[fieldName], ''); + }); + }); + }); + + describe('browserId', () => { + it('should return browser name from original test', () => { + const test = mkTest_({browserName: 'yabro'}); + + assert.equal(PlaywrightTestAdapter.create(test).browserId, 'yabro'); + }); + }); + + describe('fullTitle', () => { + it('should return title from original test', () => { + const test = mkTest_({title: 'title'}); + + assert.equal(PlaywrightTestAdapter.create(test).fullTitle(), 'title'); + }); + }); + + describe('clone', () => { + it('should create new pwt test with deeply clone original test', () => { + const test = mkTest_({title: 'first'}); + const pwtTestAdapter = PlaywrightTestAdapter.create(test); + + const clonedPwtTestAdapter = pwtTestAdapter.clone(); + test.title = 'second'; + + assert.notDeepEqual(clonedPwtTestAdapter.originalTest, test); + assert.equal(clonedPwtTestAdapter.originalTest.title, 'first'); + }); + }); + + describe('isSilentlySkipped', () => { + it('should return false by default', () => { + assert.isFalse(PlaywrightTestAdapter.create(mkTest_()).isSilentlySkipped()); + }); + }); + + describe('createTestResult', () => { + beforeEach(() => { + sandbox.stub(PlaywrightTestResultAdapter, 'create').returns({}); + }); + + it('should create test result adapter with generated test case', () => { + const test = mkTest_({ + file: 'some-path.ts', + browserName: 'yabro', + title: 'suite test', + titlePath: ['suite', 'test'] + }); + const testAdapter = PlaywrightTestAdapter.create(test); + + testAdapter.createTestResult({status: TestStatus.SUCCESS}); + const testCase = (PlaywrightTestResultAdapter.create as SinonStub).args[0][0] as unknown as TestCase; + + assert.calledOnceWith(PlaywrightTestResultAdapter.create as SinonStub, { + titlePath: sinon.match.func, + title: 'suite test', + annotations: [], + location: { + file: 'some-path.ts' + }, + parent: { + project: sinon.match.func + } + }, sinon.match.any, UNKNOWN_ATTEMPT); + assert.deepEqual(testCase.titlePath(), ['', 'yabro', 'some-path.ts', 'suite', 'test']); + assert.deepEqual(testCase.parent.project(), {name: 'yabro'} as FullProject); + }); + + describe('generate test result', () => { + it('should create test result adapter with generated test result', () => { + const testAdapter = PlaywrightTestAdapter.create(mkTest_()); + + testAdapter.createTestResult({status: TestStatus.SUCCESS, attempt: 100500}); + + assert.calledOnceWith(PlaywrightTestResultAdapter.create as SinonStub, sinon.match.any, { + attachments: [], + status: TestStatus.SUCCESS, + steps: [], + startTime: sinon.match.date + }, 100500); + }); + + describe('correctly handle attachments', () => { + const refImg = { + path: '/root/images/ref.png', + relativePath: 'images/ref.png', + size: { + width: 100, + height: 200 + } + }; + + it('should create test result with expected attachment', () => { + const testAdapter = PlaywrightTestAdapter.create(mkTest_()); + const assertViewResult = { + stateName: 'plain', + refImg, + isUpdated: true + }; + + testAdapter.createTestResult({status: TestStatus.UPDATED, assertViewResults: [assertViewResult]}); + const testResult = (PlaywrightTestResultAdapter.create as SinonStub).args[0][1] as unknown as TestResult; + + assert.deepEqual(testResult.attachments as PlaywrightAttachment[], [{ + name: 'plain-expected.png', + path: '/root/images/ref.png', + relativePath: 'images/ref.png', + contentType: 'image/png', + size: {width: 100, height: 200}, + isUpdated: true + }]); + }); + + it('should create test result with actual attachment', () => { + const testAdapter = PlaywrightTestAdapter.create(mkTest_()); + const assertViewResult = { + stateName: 'plain', + refImg, + currImg: { + path: '/root/images/actual.png', + size: { + width: 100, + height: 200 + } + }, + isUpdated: false + } as unknown as ImageDiffError; + + testAdapter.createTestResult({status: TestStatus.FAIL, assertViewResults: [assertViewResult]}); + const testResult = (PlaywrightTestResultAdapter.create as SinonStub).args[0][1] as unknown as TestResult; + + assert.deepEqual(testResult.attachments[1] as PlaywrightAttachment, { + name: 'plain-actual.png', + path: '/root/images/actual.png', + contentType: 'image/png', + size: {width: 100, height: 200}, + isUpdated: false + }); + }); + + it('should create test result with actual attachment', () => { + const testAdapter = PlaywrightTestAdapter.create(mkTest_()); + const assertViewResult = { + stateName: 'plain', + refImg, + currImg: { + path: '/root/images/actual.png', + size: { + width: 100, + height: 200 + } + }, + isUpdated: false + } as unknown as ImageDiffError; + + testAdapter.createTestResult({status: TestStatus.FAIL, assertViewResults: [assertViewResult]}); + const testResult = (PlaywrightTestResultAdapter.create as SinonStub).args[0][1] as unknown as TestResult; + + assert.deepEqual(testResult.attachments[1] as PlaywrightAttachment, { + name: 'plain-actual.png', + path: '/root/images/actual.png', + contentType: 'image/png', + size: {width: 100, height: 200}, + isUpdated: false + }); + }); + + it('should create test result with diff attachment', () => { + const testAdapter = PlaywrightTestAdapter.create(mkTest_()); + const assertViewResult = { + stateName: 'plain', + refImg, + diffImg: { + path: '/root/images/diff.png', + size: { + width: 100, + height: 200 + } + }, + isUpdated: false + } as unknown as ImageDiffError; + + testAdapter.createTestResult({status: TestStatus.FAIL, assertViewResults: [assertViewResult]}); + const testResult = (PlaywrightTestResultAdapter.create as SinonStub).args[0][1] as unknown as TestResult; + + assert.deepEqual(testResult.attachments[1] as PlaywrightAttachment, { + name: 'plain-diff.png', + path: '/root/images/diff.png', + contentType: 'image/png', + size: {width: 100, height: 200}, + isUpdated: false + }); + }); + }); + }); + }); +}); diff --git a/test/unit/lib/adapters/test/testplane.ts b/test/unit/lib/adapters/test/testplane.ts index 9ec47c4a8..f63cf30d7 100644 --- a/test/unit/lib/adapters/test/testplane.ts +++ b/test/unit/lib/adapters/test/testplane.ts @@ -104,18 +104,19 @@ describe('lib/adapters/test/testplane', () => { }); }); - describe('formatTestResult', () => { - it('shoult return testplane test result adapter', () => { + describe('createTestResult', () => { + it('should return testplane test result adapter', () => { const testResultAdapter = {} as unknown as TestplaneTestResultAdapter; - const test = mkState() as unknown as Test; + const clonedTest = mkState(); + const test = mkState({clone: () => clonedTest}) as unknown as Test; const status = TestStatus.SUCCESS; const attempt = 0; - sandbox.stub(TestplaneTestResultAdapter, 'create').withArgs(test, {status, attempt}).returns(testResultAdapter); + sandbox.stub(TestplaneTestResultAdapter, 'create').withArgs(clonedTest, {status, attempt}).returns(testResultAdapter); - const formattedTestResult = TestplaneTestAdapter.create(test).formatTestResult(status, attempt); + const formattedTestResult = TestplaneTestAdapter.create(test).createTestResult({status, attempt}); assert.equal(formattedTestResult, testResultAdapter); - assert.calledOnceWith(TestplaneTestResultAdapter.create as SinonStub, test, {status, attempt}); + assert.calledOnceWith(TestplaneTestResultAdapter.create as SinonStub, clonedTest, {status, attempt}); }); }); }); diff --git a/test/unit/lib/adapters/tool/playwright/index.ts b/test/unit/lib/adapters/tool/playwright/index.ts new file mode 100644 index 000000000..a41ce6db3 --- /dev/null +++ b/test/unit/lib/adapters/tool/playwright/index.ts @@ -0,0 +1,544 @@ +import path from 'node:path'; +import childProcess, {type ChildProcessWithoutNullStreams} from 'node:child_process'; +import {EventEmitter} from 'node:events'; +import type {Readable} from 'node:stream'; + +import P from 'bluebird'; +import {FullConfig} from '@playwright/test/reporter'; +import proxyquire from 'proxyquire'; +import sinon, {SinonStub} from 'sinon'; +import npmWhich from 'npm-which'; + +import {DEFAULT_CONFIG_PATHS, type PlaywrightToolAdapter} from '../../../../../../lib/adapters/tool/playwright'; +import {PlaywrightTestCollectionAdapter} from '../../../../../../lib/adapters/test-collection/playwright'; +import {PlaywrightTestResultAdapter} from '../../../../../../lib/adapters/test-result/playwright'; +import {DEFAULT_BROWSER_ID} from '../../../../../../lib/adapters/config/playwright'; +import {HtmlReporter} from '../../../../../../lib/plugin-api'; +import {ToolName, UNKNOWN_ATTEMPT, TestStatus} from '../../../../../../lib/constants'; +import {ClientEvents} from '../../../../../../lib/gui/constants'; + +import type {ReporterConfig} from '../../../../../../lib/types'; +import type {TestSpec} from '../../../../../../lib/adapters/tool/types'; +import type {ToolAdapterOptionsFromCli} from '../../../../../../lib/adapters/tool'; +import type {GuiReportBuilder} from '../../../../../../lib/report-builder/gui'; +import type {EventSource} from '../../../../../../lib/gui/event-source'; + +describe('lib/adapters/tool/playwright/index', () => { + const sandbox = sinon.sandbox.create(); + + let PlaywrightToolAdapter: typeof import('../../../../../../lib/adapters/tool/playwright').PlaywrightToolAdapter; + let parseConfigStub: SinonStub; + let setupTransformHookStub: SinonStub; + let ipcStub: EventEmitter; + + const proxyquirePwtToolAdapter = (stubs: Record = {}): typeof PlaywrightToolAdapter => { + return proxyquire.noCallThru().load('../../../../../../lib/adapters/tool/playwright', { + '../../../config': {parseConfig: parseConfigStub}, + './transformer': {setupTransformHook: setupTransformHookStub}, + './ipc': ipcStub, + ...stubs + }).PlaywrightToolAdapter; + }; + + const createPwtToolAdapter = (opts: ToolAdapterOptionsFromCli, config: FullConfig = {} as FullConfig): PlaywrightToolAdapter => { + PlaywrightToolAdapter = proxyquirePwtToolAdapter(opts.configPath ? {[path.resolve(opts.configPath)]: config} : {}); + + return PlaywrightToolAdapter.create(opts); + }; + + const mkSpawnInstance_ = (): ChildProcessWithoutNullStreams => { + const instance = new EventEmitter() as ChildProcessWithoutNullStreams; + instance.stdout = new EventEmitter() as Readable; + instance.stderr = new EventEmitter() as Readable; + + return instance; + }; + + beforeEach(() => { + sandbox.stub(HtmlReporter, 'create').returns({}); + sandbox.stub(PlaywrightTestCollectionAdapter, 'create').returns({}); + sandbox.stub(PlaywrightTestResultAdapter, 'create').returns({}); + sandbox.stub(npmWhich, 'sync').returns('/default/node_modules/.bin/playwright'); + sandbox.stub(childProcess, 'spawn').returns(mkSpawnInstance_()); + + ipcStub = new EventEmitter(); + parseConfigStub = sandbox.stub(); + setupTransformHookStub = sandbox.stub().returns(sinon.stub()); + }); + + afterEach(() => sandbox.restore()); + + describe('constructor', () => { + describe('should read config', () => { + it('passed by user', () => { + const configPath = './pwt.config.ts'; + + const toolAdapter = createPwtToolAdapter({toolName: ToolName.Playwright, configPath}); + + assert.equal(toolAdapter.configPath, path.resolve(configPath)); + }); + + DEFAULT_CONFIG_PATHS.forEach(configPath => { + it(`from "${configPath}" by default`, () => { + const stubs = {[path.resolve(configPath)]: {}}; + const PlaywrightToolAdapter = proxyquirePwtToolAdapter(stubs); + + const toolAdapter = PlaywrightToolAdapter.create({toolName: ToolName.Playwright}); + + assert.equal(toolAdapter.configPath, path.resolve(configPath)); + }); + }); + }); + + it('should throw error if config file is not found', () => { + assert.throws( + () => createPwtToolAdapter({toolName: ToolName.Playwright}), + `Unable to read config from paths: ${DEFAULT_CONFIG_PATHS.join(', ')}` + ); + }); + + describe('parse options from "html-reporter/playwright" reporter', () => { + describe('should call parser with empty opts if "reporter" option', () => { + it('does not exists in config', () => { + const config = {} as unknown as FullConfig; + + createPwtToolAdapter({toolName: ToolName.Playwright, configPath: './pwt.config.ts'}, config); + + assert.calledOnceWith(parseConfigStub, {}); + }); + + it('specified as string', () => { + const config = {reporter: 'html-reporter/playwright'} as unknown as FullConfig; + + createPwtToolAdapter({toolName: ToolName.Playwright, configPath: './pwt.config.ts'}, config); + + assert.calledOnceWith(parseConfigStub, {}); + }); + + it('specified as string inside array', () => { + const config = {reporter: [['line'], ['html-reporter/playwright']]} as unknown as FullConfig; + + createPwtToolAdapter({toolName: ToolName.Playwright, configPath: './pwt.config.ts'}, config); + + assert.calledOnceWith(parseConfigStub, {}); + }); + }); + + it('should call parser with specified opts', () => { + const pluginOpts = { + enabled: true, + path: 'playwright-report' + }; + const config = {reporter: [['html-reporter/playwright', pluginOpts]]} as unknown as FullConfig; + + createPwtToolAdapter({toolName: ToolName.Playwright, configPath: './pwt.config.ts'}, config); + + assert.calledOnceWith(parseConfigStub, pluginOpts); + }); + }); + + it('should init htmlReporter instance with parsed reporter config', () => { + const reporterConfig = {path: 'some/path'} as ReporterConfig; + parseConfigStub.returns(reporterConfig); + + createPwtToolAdapter({toolName: ToolName.Playwright, configPath: './pwt.config.ts'}); + + assert.calledOnceWith(HtmlReporter.create as SinonStub, reporterConfig, {toolName: ToolName.Playwright}); + }); + + it('should find pwt binary file', async () => { + createPwtToolAdapter({toolName: ToolName.Playwright, configPath: './pwt.config.ts'}); + + (npmWhich.sync as SinonStub).calledOnceWith(ToolName.Playwright, {cwd: process.cwd()}); + }); + }); + + describe('readTests', () => { + const pwtBinaryPath = '/node_modules/.bin/playwright'; + const configPath = './default-pwt.config.ts'; + let spawnProc: ChildProcessWithoutNullStreams; + + const readTests_ = async (config: FullConfig = {} as FullConfig): Promise => { + const toolAdapter = createPwtToolAdapter({toolName: ToolName.Playwright, configPath}, config); + + return toolAdapter.readTests(); + }; + + beforeEach(() => { + (npmWhich.sync as SinonStub).withArgs(ToolName.Playwright, {cwd: process.cwd()}).returns(pwtBinaryPath); + + spawnProc = mkSpawnInstance_(); + (childProcess.spawn as SinonStub).returns(spawnProc); + }); + + describe('should run pwt binary with correct arguments', () => { + it('if "projects" field is specified', async () => { + const config = { + projects: [ + {name: 'chrome'} + ] + } as unknown as FullConfig; + + P.delay(10).then(() => spawnProc.emit('exit', 0)); + await readTests_(config); + + assert.calledOnceWith(childProcess.spawn as SinonStub, pwtBinaryPath, ['test', '--list', '--reporter', 'list', '--config', path.resolve(configPath)]); + }); + + it('if "projects" field is not specified', async () => { + const config = {} as unknown as FullConfig; + + P.delay(10).then(() => spawnProc.emit('exit', 0)); + await readTests_(config); + + assert.calledOnceWith( + childProcess.spawn as SinonStub, + pwtBinaryPath, + ['test', '--list', '--reporter', 'list', '--config', path.resolve(configPath), '--browser', DEFAULT_BROWSER_ID]); + }); + }); + + it('should create test collection with empty tests if process did not write anything to stdout', async () => { + P.delay(10).then(() => spawnProc.emit('exit', 0)); + await readTests_(); + + assert.calledOnceWith(PlaywrightTestCollectionAdapter.create as SinonStub, []); + }); + + it('should create test collection with read tests if process did not write anything to stdout', async () => { + const browserName = 'yabro'; + const file = 'example.spec.ts'; + + P.delay(10).then(() => { + spawnProc.stdout.emit('data', 'Listing tests:\n'); + spawnProc.stdout.emit('data', ` [${browserName}] › ${file}:4:5 › suite › test #1\n`); + spawnProc.stdout.emit('data', ` [${browserName}] › ${file}:16:5 › suite › test #2\n`); + spawnProc.stdout.emit('data', 'Total: 2 tests in 1 file'); + + spawnProc.emit('exit', 0); + }); + await readTests_(); + + assert.calledOnceWith(PlaywrightTestCollectionAdapter.create as SinonStub, [ + { + browserName, + file, + title: 'suite test #1', + titlePath: ['suite', 'test #1'] + }, + { + browserName, + file, + title: 'suite test #2', + titlePath: ['suite', 'test #2'] + } + ]); + }); + + it('should return test collection adapter', async () => { + const testCollectionAdapter = {}; + (PlaywrightTestCollectionAdapter.create as SinonStub).withArgs([]).returns(testCollectionAdapter); + + P.delay(10).then(() => spawnProc.emit('exit', 0)); + const res = await readTests_(); + + assert.deepEqual(res, testCollectionAdapter); + }); + + it('should throw error if read tests process emit "error" event', async () => { + const error = new Error('o.O'); + + P.delay(10).then(() => spawnProc.emit('error', error)); + + await assert.isRejected( + readTests_(), + error + ); + }); + + it('should throw error if process exited with code greater than zero', async () => { + const stderr = 'o.O'; + const code = 1; + + P.delay(10).then(() => { + spawnProc.stderr.emit('data', stderr); + spawnProc.emit('exit', code); + }); + + await assert.isRejected( + readTests_(), + `Playwright process with reading tests exited with code: ${code}, stderr: ${stderr}` + ); + }); + }); + + describe('run', () => { + const pwtBinaryPath = '/node_modules/.bin/playwright'; + const configPath = './default-pwt.config.ts'; + let spawnProc: ChildProcessWithoutNullStreams; + let eventSource: EventSource; + + const mkReportBuilder_ = (): GuiReportBuilder => ({ + addTestResult: sinon.stub().resolves({}), + getTestBranch: sinon.stub().returns({}) + } as unknown as GuiReportBuilder); + + const run_ = async (opts: {tests?: TestSpec[], config?: FullConfig, reportBuilder?: GuiReportBuilder} = {}): Promise => { + const {tests = [], config = {} as FullConfig, reportBuilder = mkReportBuilder_()} = opts; + const toolAdapter = createPwtToolAdapter({toolName: ToolName.Playwright, configPath}, config); + + toolAdapter.handleTestResults(reportBuilder, eventSource); + + return toolAdapter.run(PlaywrightTestCollectionAdapter.create([]), tests); + }; + + beforeEach(() => { + (npmWhich.sync as SinonStub).withArgs(ToolName.Playwright, {cwd: process.cwd()}).returns(pwtBinaryPath); + + eventSource = {emit: sinon.stub()} as unknown as EventSource; + + spawnProc = mkSpawnInstance_(); + (childProcess.spawn as SinonStub).returns(spawnProc); + }); + + it('should throw if "reportBuilder" and "eventSource" instances are not specified', async () => { + const toolAdapter = createPwtToolAdapter({toolName: ToolName.Playwright, configPath}); + + await assert.isRejected( + toolAdapter.run(PlaywrightTestCollectionAdapter.create([]), []), + '"reportBuilder" and "eventSource" instances must be initialize before run tests' + ); + }); + + describe('should run pwt binary with correct arguments', () => { + it('if "projects" field is specified in config, but tests not passed', async () => { + const config = { + projects: [ + {name: 'chrome'} + ] + } as unknown as FullConfig; + + P.delay(10).then(() => spawnProc.emit('exit', 0)); + await run_({config}); + + assert.calledOnceWith( + childProcess.spawn as SinonStub, + pwtBinaryPath, + [ + 'test', + '--reporter', path.resolve('./lib/adapters/tool/playwright/reporter'), + '--config', path.resolve(configPath) + ], + { + stdio: ['inherit', 'inherit', 'inherit', 'ipc'] + } + ); + }); + + it('if "projects" field is specified in config and tests passed', async () => { + const config = { + projects: [ + {name: 'chrome'}, + {name: 'firefox'} + ] + } as unknown as FullConfig; + const tests = [ + {testName: 'foo', browserName: 'chrome'}, + {testName: 'bar', browserName: 'firefox'} + ]; + + P.delay(10).then(() => spawnProc.emit('exit', 0)); + await run_({tests, config}); + + assert.calledOnceWith( + childProcess.spawn as SinonStub, + pwtBinaryPath, + [ + 'test', + '--reporter', path.resolve('./lib/adapters/tool/playwright/reporter'), + '--config', path.resolve(configPath), + '--grep', 'foo|bar', + '--retries', '0', + '--project', 'chrome', + '--project', 'firefox' + ], + { + stdio: ['inherit', 'inherit', 'inherit', 'ipc'] + } + ); + }); + + it('if "projects" field not specified in config and tests not passed', async () => { + P.delay(10).then(() => spawnProc.emit('exit', 0)); + await run_(); + + assert.calledOnceWith( + childProcess.spawn as SinonStub, + pwtBinaryPath, + [ + 'test', + '--reporter', path.resolve('./lib/adapters/tool/playwright/reporter'), + '--config', path.resolve(configPath), + '--browser', DEFAULT_BROWSER_ID + ], + { + stdio: ['inherit', 'inherit', 'inherit', 'ipc'] + } + ); + }); + + it('if "projects" field not specified in config, but tests passed', async () => { + const tests = [ + {testName: 'foo', browserName: DEFAULT_BROWSER_ID} + ]; + + P.delay(10).then(() => spawnProc.emit('exit', 0)); + await run_({tests}); + + assert.calledOnceWith( + childProcess.spawn as SinonStub, + pwtBinaryPath, + [ + 'test', + '--reporter', path.resolve('./lib/adapters/tool/playwright/reporter'), + '--config', path.resolve(configPath), + '--grep', 'foo', + '--retries', '0', + '--browser', DEFAULT_BROWSER_ID + ], + { + stdio: ['inherit', 'inherit', 'inherit', 'ipc'] + } + ); + }); + }); + + ([ClientEvents.BEGIN_STATE, ClientEvents.TEST_RESULT] as const).forEach((eventName) => { + describe(`"${eventName}" event`, () => { + it('should create test result adapter', async () => { + const timestamp = Date.now(); + + P.delay(10).then(() => { + ipcStub.emit(eventName, { + test: { + foo: 1, + parent: { + baz: 2 + } + }, + result: { + baz: 3, + startTime: timestamp + }, + browserName: 'yabro', + titlePath: ['suite', 'test'], + event: eventName + }); + spawnProc.emit('exit', 0); + }); + await run_(); + + const testCase = (PlaywrightTestResultAdapter.create as SinonStub).lastCall.args[0]; + + assert.calledOnceWith( + PlaywrightTestResultAdapter.create as SinonStub, + { + foo: 1, + parent: { + baz: 2, + project: sinon.match.func + }, + titlePath: sinon.match.func + }, + { + baz: 3, + startTime: new Date(timestamp), + ...(eventName === ClientEvents.BEGIN_STATE ? {status: TestStatus.RUNNING} : {}) + }, + UNKNOWN_ATTEMPT + ); + assert.deepEqual(testCase.titlePath(), ['suite', 'test']); + assert.deepEqual(testCase.parent.project(), {name: 'yabro'}); + }); + + it('should add test result to report builder', async () => { + const reportBuilder = mkReportBuilder_(); + const testResultAdapter = {}; + (PlaywrightTestResultAdapter.create as SinonStub).returns(testResultAdapter); + + P.delay(10).then(() => { + ipcStub.emit(eventName, { + test: {}, result: {}, browserName: '', titlePath: [], event: eventName + }); + spawnProc.emit('exit', 0); + }); + await run_({reportBuilder}); + + assert.calledOnceWith(reportBuilder.addTestResult as SinonStub, testResultAdapter); + }); + + it('should emit event for client with correct data', async () => { + const reportBuilder = mkReportBuilder_(); + const testBranch = {}; + (reportBuilder.addTestResult as SinonStub).resolves({id: 'foo'}); + (reportBuilder.getTestBranch as SinonStub).withArgs('foo').returns(testBranch); + + P.delay(10).then(() => { + ipcStub.emit(eventName, { + test: {}, result: {}, browserName: '', titlePath: [], event: eventName + }); + spawnProc.emit('exit', 0); + }); + await run_({reportBuilder}); + + assert.calledOnceWith(eventSource.emit as SinonStub, eventName, testBranch); + }); + }); + }); + + describe(`"${ClientEvents.END}" event`, () => { + it('should emit event for client with correct data', async () => { + const reportBuilder = mkReportBuilder_(); + + P.delay(10).then(() => { + ipcStub.emit(ClientEvents.END, {event: ClientEvents.END}); + spawnProc.emit('exit', 0); + }); + await run_({reportBuilder}); + + assert.calledOnceWith(eventSource.emit as SinonStub, ClientEvents.END); + }); + }); + + it('should throw error if run tests process emit "error" event', async () => { + const error = new Error('o.O'); + + P.delay(10).then(() => spawnProc.emit('error', error)); + + await assert.isRejected( + run_(), + error + ); + }); + + describe('should resolve run tests with', () => { + it('"true" if exit code = 0', async () => { + const code = 0; + + P.delay(10).then(() => spawnProc.emit('exit', code)); + const result = await run_(); + + assert.isTrue(result); + }); + + it('"false" if exit code != 0', async () => { + const code = 123; + + P.delay(10).then(() => spawnProc.emit('exit', code)); + const result = await run_(); + + assert.isFalse(result); + }); + }); + }); +}); diff --git a/test/unit/lib/gui/tool-runner/index.js b/test/unit/lib/gui/tool-runner/index.js index d905079d5..717da8bfa 100644 --- a/test/unit/lib/gui/tool-runner/index.js +++ b/test/unit/lib/gui/tool-runner/index.js @@ -36,7 +36,8 @@ describe('lib/gui/tool-runner/index', () => { const stubTest_ = (opts = {}) => { return mkState(_.defaults(opts, { id: () => 'default-id', - fullTitle: () => 'some-title' + fullTitle: () => 'some-title', + clone: () => stubTest_(opts) })); }; @@ -250,7 +251,8 @@ describe('lib/gui/tool-runner/index', () => { browsers: {yabro: {getScreenshotPath}} })); - const testCollection = mkTestCollection_({'some-title.yabro': mkTestAdapter_(testRefUpdateData[0])}); + const testAdapter = mkTestAdapter_({...testRefUpdateData[0], clone: () => testRefUpdateData[0]}); + const testCollection = mkTestCollection_({'some-title.yabro': testAdapter}); const toolAdapter = stubToolAdapter({config, testCollection}); const gui = initGuiReporter({toolAdapter}); @@ -299,7 +301,8 @@ describe('lib/gui/tool-runner/index', () => { browsers: {yabro: {getScreenshotPath}} })); - const testCollection = mkTestCollection_({'some-title.yabro': mkTestAdapter_(tests[0])}); + const testAdapter = mkTestAdapter_({...tests[0], clone: () => tests[0]}); + const testCollection = mkTestCollection_({'some-title.yabro': testAdapter}); const toolAdapter = stubToolAdapter({config, testCollection}); const gui = initGuiReporter({toolAdapter}); @@ -336,11 +339,12 @@ describe('lib/gui/tool-runner/index', () => { }]; const getScreenshotPath = sandbox.stub().returns('/ref/path1'); - const config = stubConfig({ + const config = mkConfigAdapter_(stubConfig({ browsers: {yabro: {getScreenshotPath}} - }); + })); - const testCollection = mkTestCollection_({'some-title.yabro': testRefUpdateData[0]}); + const testAdapter = mkTestAdapter_({...testRefUpdateData[0], clone: () => testRefUpdateData[0]}); + const testCollection = mkTestCollection_({'some-title.yabro': testAdapter}); const toolAdapter = stubToolAdapter({config, testCollection}); reportBuilder.getLatestAttempt.withArgs({fullName: 'some-title', browserId: 'yabro'}).returns(100500); @@ -389,7 +393,8 @@ describe('lib/gui/tool-runner/index', () => { browsers: {yabro: {getScreenshotPath}} })); - const testCollection = mkTestCollection_({'some-title.yabro': mkTestAdapter_(tests[0])}); + const testAdapter = mkTestAdapter_({...tests[0], clone: () => tests[0]}); + const testCollection = mkTestCollection_({'some-title.yabro': testAdapter}); const toolAdapter = stubToolAdapter({config, testCollection}); const gui = initGuiReporter({toolAdapter}); diff --git a/test/unit/lib/report-builder/gui.js b/test/unit/lib/report-builder/gui.js index 1ad578f0f..0a7db856e 100644 --- a/test/unit/lib/report-builder/gui.js +++ b/test/unit/lib/report-builder/gui.js @@ -21,9 +21,9 @@ describe('GuiReportBuilder', () => { const sandbox = sinon.sandbox.create(); let hasImage, deleteFile, GuiReportBuilder, dbClient, copyAndUpdate, imagesInfoSaver; - const mkGuiReportBuilder_ = async ({toolConfig, pluginConfig} = {}) => { + const mkGuiReportBuilder_ = async ({toolConfig, reporterConfig} = {}) => { toolConfig = _.defaults(toolConfig || {}, {getAbsoluteUrl: _.noop}); - pluginConfig = _.defaults(pluginConfig || {}, {baseHost: '', path: TEST_REPORT_PATH, baseTestPath: ''}); + reporterConfig = _.defaults(reporterConfig || {}, {baseHost: '', path: TEST_REPORT_PATH, baseTestPath: ''}); const htmlReporter = HtmlReporter.create({baseHost: ''}); @@ -39,7 +39,7 @@ describe('GuiReportBuilder', () => { imagesInfoSaver = sinon.createStubInstance(ImagesInfoSaver); imagesInfoSaver.save.callsFake(_.identity); - const reportBuilder = GuiReportBuilder.create(testplane.htmlReporter, pluginConfig, {dbClient, imagesInfoSaver}); + const reportBuilder = GuiReportBuilder.create({htmlReporter: testplane.htmlReporter, reporterConfig, dbClient, imagesInfoSaver}); const workers = {saveDiffTo: () => {}}; reportBuilder.registerWorkers(workers); @@ -226,7 +226,7 @@ describe('GuiReportBuilder', () => { }); it('should add base host to result with value from plugin parameter "baseHost"', async () => { - const reportBuilder = await mkGuiReportBuilder_({pluginConfig: {baseHost: 'some-host'}}); + const reportBuilder = await mkGuiReportBuilder_({reporterConfig: {baseHost: 'some-host'}}); assert.equal(reportBuilder.getResult().config.baseHost, 'some-host'); }); diff --git a/test/unit/lib/report-builder/static.js b/test/unit/lib/report-builder/static.js index 0f3326f5e..67efd7dad 100644 --- a/test/unit/lib/report-builder/static.js +++ b/test/unit/lib/report-builder/static.js @@ -34,8 +34,8 @@ describe('StaticReportBuilder', () => { './server-utils': utils }); - const mkStaticReportBuilder_ = async ({pluginConfig} = {}) => { - pluginConfig = _.defaults(pluginConfig, {baseHost: '', path: TEST_REPORT_PATH, baseTestPath: ''}); + const mkStaticReportBuilder_ = async ({reporterConfig} = {}) => { + reporterConfig = _.defaults(reporterConfig, {baseHost: '', path: TEST_REPORT_PATH, baseTestPath: ''}); htmlReporter = _.extend(HtmlReporter.create({baseHost: ''}), { reportsSaver: { @@ -49,7 +49,7 @@ describe('StaticReportBuilder', () => { imagesInfoSaver.save.callsFake(_.identity); - const reportBuilder = StaticReportBuilder.create(htmlReporter, pluginConfig, {dbClient, imagesInfoSaver}); + const reportBuilder = StaticReportBuilder.create({htmlReporter, reporterConfig, dbClient, imagesInfoSaver}); workers = {saveDiffTo: sinon.stub()}; reportBuilder.registerWorkers(workers); @@ -143,7 +143,7 @@ describe('StaticReportBuilder', () => { it('should not save error details if turned off', async () => { const reportBuilder = await mkStaticReportBuilder_({ - pluginConfig: {saveErrorDetails: false, path: TEST_REPORT_PATH} + reporterConfig: {saveErrorDetails: false, path: TEST_REPORT_PATH} }); const testResult = stubTest_({errorDetails: {filePath: 'some-path'}}); @@ -154,7 +154,7 @@ describe('StaticReportBuilder', () => { it('should use server-utils to save error details if needed', async () => { const reportBuilder = await mkStaticReportBuilder_({ - pluginConfig: {saveErrorDetails: true, path: TEST_REPORT_PATH} + reporterConfig: {saveErrorDetails: true, path: TEST_REPORT_PATH} }); const testResult = stubTest_({errorDetails: {filePath: 'some-path'}}); diff --git a/testplane.ts b/testplane.ts index de8c88543..fa282cd4f 100644 --- a/testplane.ts +++ b/testplane.ts @@ -73,7 +73,12 @@ export default (testplane: Testplane, opts: Partial): void => { reportPath: htmlReporter.config.path }); - staticReportBuilder = StaticReportBuilder.create(htmlReporter, config, {dbClient, imagesInfoSaver}); + staticReportBuilder = StaticReportBuilder.create({ + htmlReporter: toolAdapter.htmlReporter, + reporterConfig: config, + dbClient, + imagesInfoSaver + }); handlingTestResults = Promise.all([ staticReportBuilder.saveStaticFiles(), diff --git a/tsconfig.json b/tsconfig.json index c4f394184..5671b377f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "./tsconfig.common.json", "include": ["lib", "testplane.ts", "hermione.ts", "gemini.js", "playwright.ts"], - "exclude": ["lib/static",], + "exclude": ["lib/static", "lib/bundle"], "compilerOptions": { "outDir": "build", },