From 484dc5a50a5a59ddfd510f8c048a6aacfb080a46 Mon Sep 17 00:00:00 2001 From: Battlesquid <25509915+Battlesquid@users.noreply.github.com> Date: Wed, 26 Mar 2025 15:35:14 -0700 Subject: [PATCH 1/7] feat: bundle scraper and strategies --- .prettierignore | 4 - .prettierrc.json | 6 - biome.json | 30 + eslint.config.mjs | 12 - package.json | 76 +- packages/scraper-strategies/package.json | 34 + .../src/curl_impersonate_client.ts | 77 + .../scraper-strategies/src/cycletls_client.ts | 71 + packages/scraper-strategies/src/index.ts | 2 + packages/scraper-strategies/src/utils.ts | 5 + packages/scraper-strategies/tsconfig.json | 14 + packages/scraper/package.json | 41 + packages/scraper/src/clients/defaults.ts | 19 + packages/scraper/src/clients/fetch_client.ts | 85 + packages/scraper/src/clients/got_client.ts | 136 + .../scraper/src}/clients/index.ts | 0 {src => packages/scraper/src}/index.ts | 0 packages/scraper/src/modules/constants.ts | 42 + packages/scraper/src/modules/extractors.ts | 117 + packages/scraper/src/modules/fetchers.ts | 434 ++ packages/scraper/src/modules/generators.ts | 118 + .../scraper/src}/modules/index.ts | 0 packages/scraper/src/modules/parsing.ts | 59 + packages/scraper/src/modules/query.ts | 95 + packages/scraper/src/modules/rules.ts | 46 + packages/scraper/src/selectors.ts | 12 + packages/scraper/src/types.ts | 87 + packages/scraper/src/util/attempt.ts | 42 + {src => packages/scraper/src}/util/index.ts | 0 {src => packages/scraper/src}/util/timing.ts | 6 +- .../scraper/tests}/data/judging_home_page.ts | 10 +- packages/scraper/tests/data/test_questions.ts | 449 ++ .../scraper/tests}/data/v5rc_home_page.ts | 10 +- .../tests}/data/v5rc_non_readonly_page.ts | 12 +- .../scraper/tests}/data/v5rc_question_page.ts | 10 +- .../tests/data/v5rc_question_page_json.ts | 22 + .../scraper/tests}/data/vurc_home_page.ts | 10 +- packages/scraper/tests/extractors.test.ts | 57 + packages/scraper/tests/parsing.test.ts | 77 + packages/scraper/tests/query.test.ts | 37 + packages/scraper/tests/rules.test.ts | 12 + packages/scraper/tsconfig.json | 9 + packages/typescript-config/base.json | 15 + packages/typescript-config/package.json | 7 + pnpm-lock.yaml | 6334 +++++++++-------- pnpm-workspace.yaml | 9 + src/clients/defaults.ts | 15 - src/clients/fetch_client.ts | 85 - src/clients/got_client.ts | 125 - src/modules/constants.ts | 40 - src/modules/extractors.ts | 95 - src/modules/fetchers.ts | 357 - src/modules/generators.ts | 100 - src/modules/parsing.ts | 58 - src/modules/query.ts | 67 - src/modules/rules.ts | 38 - src/selectors.json | 12 - src/types.ts | 87 - src/util/attempt.ts | 40 - tests/data/test_questions.ts | 449 -- tests/data/v5rc_question_page_json.ts | 18 - tests/extractors.test.ts | 52 - tests/parsing.test.ts | 51 - tests/query.test.ts | 25 - tests/rules.test.ts | 11 - tsconfig.json | 26 +- 66 files changed, 5537 insertions(+), 4964 deletions(-) delete mode 100644 .prettierignore delete mode 100644 .prettierrc.json create mode 100644 biome.json delete mode 100644 eslint.config.mjs create mode 100644 packages/scraper-strategies/package.json create mode 100644 packages/scraper-strategies/src/curl_impersonate_client.ts create mode 100644 packages/scraper-strategies/src/cycletls_client.ts create mode 100644 packages/scraper-strategies/src/index.ts create mode 100644 packages/scraper-strategies/src/utils.ts create mode 100644 packages/scraper-strategies/tsconfig.json create mode 100644 packages/scraper/package.json create mode 100644 packages/scraper/src/clients/defaults.ts create mode 100644 packages/scraper/src/clients/fetch_client.ts create mode 100644 packages/scraper/src/clients/got_client.ts rename {src => packages/scraper/src}/clients/index.ts (100%) rename {src => packages/scraper/src}/index.ts (100%) create mode 100644 packages/scraper/src/modules/constants.ts create mode 100644 packages/scraper/src/modules/extractors.ts create mode 100644 packages/scraper/src/modules/fetchers.ts create mode 100644 packages/scraper/src/modules/generators.ts rename {src => packages/scraper/src}/modules/index.ts (100%) create mode 100644 packages/scraper/src/modules/parsing.ts create mode 100644 packages/scraper/src/modules/query.ts create mode 100644 packages/scraper/src/modules/rules.ts create mode 100644 packages/scraper/src/selectors.ts create mode 100644 packages/scraper/src/types.ts create mode 100644 packages/scraper/src/util/attempt.ts rename {src => packages/scraper/src}/util/index.ts (100%) rename {src => packages/scraper/src}/util/timing.ts (51%) rename {tests => packages/scraper/tests}/data/judging_home_page.ts (99%) create mode 100644 packages/scraper/tests/data/test_questions.ts rename {tests => packages/scraper/tests}/data/v5rc_home_page.ts (99%) rename {tests => packages/scraper/tests}/data/v5rc_non_readonly_page.ts (99%) rename {tests => packages/scraper/tests}/data/v5rc_question_page.ts (99%) create mode 100644 packages/scraper/tests/data/v5rc_question_page_json.ts rename {tests => packages/scraper/tests}/data/vurc_home_page.ts (99%) create mode 100644 packages/scraper/tests/extractors.test.ts create mode 100644 packages/scraper/tests/parsing.test.ts create mode 100644 packages/scraper/tests/query.test.ts create mode 100644 packages/scraper/tests/rules.test.ts create mode 100644 packages/scraper/tsconfig.json create mode 100644 packages/typescript-config/base.json create mode 100644 packages/typescript-config/package.json create mode 100644 pnpm-workspace.yaml delete mode 100644 src/clients/defaults.ts delete mode 100644 src/clients/fetch_client.ts delete mode 100644 src/clients/got_client.ts delete mode 100644 src/modules/constants.ts delete mode 100644 src/modules/extractors.ts delete mode 100644 src/modules/fetchers.ts delete mode 100644 src/modules/generators.ts delete mode 100644 src/modules/parsing.ts delete mode 100644 src/modules/query.ts delete mode 100644 src/modules/rules.ts delete mode 100644 src/selectors.json delete mode 100644 src/types.ts delete mode 100644 src/util/attempt.ts delete mode 100644 tests/data/test_questions.ts delete mode 100644 tests/data/v5rc_question_page_json.ts delete mode 100644 tests/extractors.test.ts delete mode 100644 tests/parsing.test.ts delete mode 100644 tests/query.test.ts delete mode 100644 tests/rules.test.ts diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index f8e45ff..0000000 --- a/.prettierignore +++ /dev/null @@ -1,4 +0,0 @@ -dist -tests -coverage -README.md \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index a5359ad..0000000 --- a/.prettierrc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "printWidth": 150, - "tabWidth": 4, - "trailingComma": "none", - "singleQuote": false -} diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..431b074 --- /dev/null +++ b/biome.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "vcs": { + "enabled": false, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": false, + "ignore": [".turbo", "dist", "node_modules", "coverage"] + }, + "formatter": { + "enabled": true, + "indentStyle": "tab" + }, + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + }, + "javascript": { + "formatter": { + "quoteStyle": "double" + } + } +} diff --git a/eslint.config.mjs b/eslint.config.mjs deleted file mode 100644 index 87a1461..0000000 --- a/eslint.config.mjs +++ /dev/null @@ -1,12 +0,0 @@ -import eslint from "@eslint/js"; -import tseslint from "typescript-eslint"; - -export default tseslint.config(eslint.configs.recommended, ...tseslint.configs.recommended, { - rules: { - semi: "error", - curly: "error", - quotes: ["error", "double", { allowTemplateLiterals: true }], - "@typescript-eslint/explicit-function-return-type": "error" - }, - ignores: ["node_modules", "dist"] -}); diff --git a/package.json b/package.json index 88cae10..8e94ee5 100644 --- a/package.json +++ b/package.json @@ -1,53 +1,27 @@ { - "name": "@qnaplus/scraper", - "version": "3.0.0", - "description": "Utility package to scrape questions from the VEX Robotics Q&A.", - "main": "dist/index.js", - "repository": { - "url": "git+ssh://git@github.com/qnaplus/scraper.git" - }, - "author": "Battlesquid <25509915+Battlesquid@users.noreply.github.com>", - "license": "GPL-3.0", - "scripts": { - "build": "tsc", - "build:clean": "pnpm clean && pnpm build", - "test": "vitest", - "clean": "rimraf dist", - "reset": "pnpm clean && rimraf node_modules", - "lint": "eslint src/**", - "lint:fix": "pnpm lint --fix", - "neat": "pnpm lint:fix && pnpm pretty", - "pretty": "prettier . --write", - "pretty:check": "prettier . --check" - }, - "dependencies": { - "@crawlee/core": "^3.11.5", - "cheerio": "^1.0.0", - "got-scraping": "^4.0.6", - "node-pdf-parser": "^1.0.3", - "pino": "^9.4.0" - }, - "devDependencies": { - "@eslint/js": "^9.12.0", - "eslint": "^9.12.0", - "pino-pretty": "^11.2.2", - "prettier": "^3.3.3", - "rimraf": "^6.0.1", - "typescript": "5.5.4", - "typescript-eslint": "^8.9.0", - "vitest": "^3.0.8" - }, - "volta": { - "node": "22.14.0", - "pnpm": "10.6.2" - }, - "files": [ - "dist" - ], - "pnpm": { - "onlyBuiltDependencies": [ - "canvas", - "esbuild" - ] - } + "name": "scraper", + "version": "1.0.0", + "description": "", + "private": true, + "author": "battlesqui_d", + "license": "GPL-3.0", + "devDependencies": { + "@biomejs/biome": "1.9.4", + "rimraf": "^6.0.1", + "syncpack": "^13.0.2", + "typescript": "5.5.4" + }, + "scripts": { + "build": "tsc --build", + "clean": "pnpm -r clean", + "reset": "pnpm -r reset && rimraf node_modules", + "neat": "biome check .", + "neat:fix": "biome check . --write", + "test:scraper": "pnpm --filter=@qnaplus/scraper run test" + }, + "volta": { + "pnpm": "10.5.2", + "node": "22.14.0" + }, + "packageManager": "pnpm@10.5.2" } diff --git a/packages/scraper-strategies/package.json b/packages/scraper-strategies/package.json new file mode 100644 index 0000000..59dfac9 --- /dev/null +++ b/packages/scraper-strategies/package.json @@ -0,0 +1,34 @@ +{ + "name": "@qnaplus/scraper-strategies", + "version": "3.0.0", + "description": "Request stategies for @qnaplus/scraper", + "main": "dist/index.js", + "repository": { + "url": "git+ssh://git@github.com/qnaplus/scraper-strategies.git" + }, + "author": "Battlesquid <25509915+Battlesquid@users.noreply.github.com>", + "license": "GPL-3.0", + "scripts": { + "build": "tsc", + "build:clean": "pnpm clean && pnpm build", + "clean": "rimraf dist tsconfig.tsbuildinfo", + "reset": "pnpm clean && rimraf node_modules" + }, + "dependencies": { + "@qnaplus/node-curl-impersonate": "^1.0.0", + "@qnaplus/scraper": "workspace:*", + "cycletls": "^1.0.27", + "form-data": "^4.0.1", + "header-generator": "^2.1.62", + "pino": "catalog:" + }, + "devDependencies": { + "@qnaplus/typescript-config": "workspace:1.0.0", + "pino-pretty": "catalog:" + }, + "volta": { + "node": "22.14.0", + "pnpm": "10.6.2" + }, + "files": ["dist"] +} diff --git a/packages/scraper-strategies/src/curl_impersonate_client.ts b/packages/scraper-strategies/src/curl_impersonate_client.ts new file mode 100644 index 0000000..df4c617 --- /dev/null +++ b/packages/scraper-strategies/src/curl_impersonate_client.ts @@ -0,0 +1,77 @@ +import { + BrowserPresets, + type BrowserType, + type ChromePresetVersion, + type CurlResultOk, + type FirefoxPresetVersion, + RequestBuilder, + type RequestPreset, + type SafariPresetVersion, + getCompatibleBrowsers, +} from "@qnaplus/node-curl-impersonate"; +import { FetchClient, type FetchClientResponse } from "@qnaplus/scraper"; + +export class CurlImpersonateScrapingClient extends FetchClient { + async fetch(url: string): Promise { + const browsers = getCompatibleBrowsers(); + const badStatusCodes = [403]; + let latestResponse: FetchClientResponse = { + ok: false, + body: "", + status: -1, + url: "", + }; + + // TODO: when a bad status code is not recieved, cache the preset that was used. + // Continue using that preset until failure, then search again for another working preset. + for (const browser of browsers) { + for (const version of Object.keys(BrowserPresets[browser.name])) { + const { response, details } = await this.doPresetRequest(url, { + name: browser.name, + version: version as + | ChromePresetVersion + | FirefoxPresetVersion + | SafariPresetVersion, + }); + latestResponse = { + body: response, + ok: details.response_code === 200, + url: details.url_effective, + status: details.response_code, + }; + if (!badStatusCodes.includes(details.response_code)) { + return latestResponse; + } + this.logger?.trace( + `Request did not return an accepted response code (preset: ${browser.name} v${version})`, + ); + } + } + this.logger?.trace( + `All presets failed (latest response: ${latestResponse}`, + ); + return latestResponse; + } + + async buffer(): Promise { + // TODO: implement reading response buffer + return null; + } + + teardown(): Promise | void {} + + private async doPresetRequest( + url: string, + preset: RequestPreset, + ): Promise { + const response = await new RequestBuilder() + .url(url) + .preset(preset) + .follow() + .send(); + if (response.stderr !== undefined) { + throw new Error(response.stderr); // TODO figure out how to handle this + } + return response; + } +} diff --git a/packages/scraper-strategies/src/cycletls_client.ts b/packages/scraper-strategies/src/cycletls_client.ts new file mode 100644 index 0000000..f54b5c2 --- /dev/null +++ b/packages/scraper-strategies/src/cycletls_client.ts @@ -0,0 +1,71 @@ +import { FetchClient, type FetchClientResponse } from "@qnaplus/scraper"; +import initCycleTLS, { type CycleTLSClient } from "cycletls"; +import { HeaderGenerator } from "header-generator"; +import type { Logger } from "pino"; + +export type CycleTLSResponse = FetchClientResponse; + +export class CycleTLSScrapingClient extends FetchClient { + private static instance: CycleTLSScrapingClient | null = null; + private static logger?: Logger; + private static client: CycleTLSClient; + private static initialized = false; + + private constructor(logger?: Logger) { + super(logger); + } + + async fetch(url: string): Promise { + const response = await this.getResponse(url); + return { + body: response.body as string, + ok: response.status === 200, + url: response.finalUrl, + status: response.status, + }; + } + + async buffer(): Promise { + // TODO: implement reading response buffer + return null; + } + + static async initialize(logger?: Logger): Promise { + if (CycleTLSScrapingClient.initialized) { + return; + } + CycleTLSScrapingClient.logger = logger; + CycleTLSScrapingClient.client = await initCycleTLS(); + CycleTLSScrapingClient.initialized = true; + } + + static getInstance(): CycleTLSScrapingClient { + if (!CycleTLSScrapingClient.initialized) { + throw Error("Initialize was not called on CycleTLSScrapingClient."); + } + if (CycleTLSScrapingClient.instance === null) { + CycleTLSScrapingClient.instance = new CycleTLSScrapingClient( + CycleTLSScrapingClient.logger, + ); + } + return CycleTLSScrapingClient.instance; + } + + teardown(): Promise | void { + CycleTLSScrapingClient.logger?.trace("Tearing down CycleTLS"); + return CycleTLSScrapingClient.client.exit().then(() => { + CycleTLSScrapingClient.initialized = false; + }); + } + + private async getResponse(url: string) { + const client = CycleTLSScrapingClient.client; + const headerGenerator = new HeaderGenerator(); + const options = { + headers: headerGenerator.getHeaders(), + ja3: "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-51-57-47-53-10,0-23-65281-10-11-35-16-5-51-43-13-45-28-21,29-23-24-25-256-257,0", + }; + const response = await client.get(url, options); + return response; + } +} diff --git a/packages/scraper-strategies/src/index.ts b/packages/scraper-strategies/src/index.ts new file mode 100644 index 0000000..3cb09d4 --- /dev/null +++ b/packages/scraper-strategies/src/index.ts @@ -0,0 +1,2 @@ +export * from "./cycletls_client"; +export * from "./curl_impersonate_client"; diff --git a/packages/scraper-strategies/src/utils.ts b/packages/scraper-strategies/src/utils.ts new file mode 100644 index 0000000..3c6a85e --- /dev/null +++ b/packages/scraper-strategies/src/utils.ts @@ -0,0 +1,5 @@ +// https://bugs.chromium.org/p/v8/issues/detail?id=2869 +export const unleak = (str: string | undefined | null): string => { + // biome-ignore lint: style/useTemplate + return (" " + (str ?? "")).slice(1); +}; diff --git a/packages/scraper-strategies/tsconfig.json b/packages/scraper-strategies/tsconfig.json new file mode 100644 index 0000000..d421252 --- /dev/null +++ b/packages/scraper-strategies/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "@qnaplus/typescript-config/base.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist" + }, + "references": [ + { + "path": "../scraper" + } + ], + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/packages/scraper/package.json b/packages/scraper/package.json new file mode 100644 index 0000000..2e373f2 --- /dev/null +++ b/packages/scraper/package.json @@ -0,0 +1,41 @@ +{ + "name": "@qnaplus/scraper", + "version": "3.0.0", + "description": "Utility package to scrape questions from the VEX Robotics Q&A.", + "main": "dist/index.js", + "repository": { + "url": "git+ssh://git@github.com/qnaplus/scraper.git" + }, + "author": "Battlesquid <25509915+Battlesquid@users.noreply.github.com>", + "license": "GPL-3.0", + "scripts": { + "build": "tsc", + "build:clean": "pnpm clean && pnpm build", + "test": "vitest", + "clean": "rimraf dist tsconfig.tsbuildinfo", + "reset": "pnpm clean && rimraf node_modules" + }, + "dependencies": { + "@crawlee/core": "^3.11.5", + "cheerio": "^1.0.0", + "got-scraping": "^4.0.6", + "node-pdf-parser": "^1.0.3", + "pino": "catalog:" + }, + "devDependencies": { + "@qnaplus/typescript-config": "workspace:1.0.0", + "pino-pretty": "catalog:", + "vitest": "^3.0.8" + }, + "volta": { + "node": "22.14.0", + "pnpm": "10.6.2" + }, + "files": ["dist"], + "exports": { + ".": { + "default": "./dist/index.js", + "types": "./dist/index.d.ts" + } + } +} diff --git a/packages/scraper/src/clients/defaults.ts b/packages/scraper/src/clients/defaults.ts new file mode 100644 index 0000000..d537f31 --- /dev/null +++ b/packages/scraper/src/clients/defaults.ts @@ -0,0 +1,19 @@ +import type { Logger } from "pino"; +import type { FetcherOptions } from "../modules/fetchers"; +import { GotScrapingClient } from "./got_client"; + +export const getPreferredClient = async ( + logger?: Logger, +): Promise => { + return new GotScrapingClient(logger, true); +}; + +export const getDefaultFetcherOptions = async ( + options?: FetcherOptions, +): Promise< + Required> & Pick +> => { + const client = options?.client ?? (await getPreferredClient(options?.logger)); + const teardown = options?.teardown ?? true; + return { client, teardown, logger: options?.logger }; +}; diff --git a/packages/scraper/src/clients/fetch_client.ts b/packages/scraper/src/clients/fetch_client.ts new file mode 100644 index 0000000..ef2873e --- /dev/null +++ b/packages/scraper/src/clients/fetch_client.ts @@ -0,0 +1,85 @@ +import type { Logger } from "pino"; +import { unleak } from "../modules/extractors"; + +export interface FetchClientOptions { + /** + * Optional logger to include + */ + logger?: Logger; +} + +export type FetchClientResponse = { + /** + * Whether the request was successful + */ + ok: boolean; + + /** + * The status of the request + */ + status: number; + + /** + * The response body + */ + body: string; + + /** + * The final url resolved for the request (e.g., redirect urls) + */ + url: string; +}; + +export type FetchHtmlResponse = { + /** + * The HTML obtained from a request + */ + html: string; + + /** + * The final url resolved for the request. + */ + url: string; +}; + +export abstract class FetchClient { + constructor(protected logger?: Logger) {} + + abstract fetch(url: string): Promise; + abstract buffer(url: string): Promise; + abstract teardown(): Promise | void; + + /** + * Utility method for checking if a page exists + * @param url The url to ping + * @returns boolean indicating whether the response was ok + */ + async ping(url: string): Promise { + const response = await this.fetch(url); + return response.ok; + } + /** + * + * @param url The url to get + * @returns The html for the given url + */ + async getHtml(url: string): Promise { + this.logger?.trace(`Fetching HTML from ${url}.`); + + const response = await this.fetch(url); + this.logger?.trace( + { + url, + status: response.status, + }, + `Fetch for ${url} returned ${response.status}`, + ); + if (!response.ok) { + return null; + } + return { + url: response.url, + html: unleak(response.body), + }; + } +} diff --git a/packages/scraper/src/clients/got_client.ts b/packages/scraper/src/clients/got_client.ts new file mode 100644 index 0000000..daae5a1 --- /dev/null +++ b/packages/scraper/src/clients/got_client.ts @@ -0,0 +1,136 @@ +import { SessionPool } from "@crawlee/core"; +/* eslint-disable @typescript-eslint/ban-ts-comment */ +// @ts-ignore Okay because we only import a type. +import type { GotScraping, Response } from "got-scraping"; +import type { Logger } from "pino"; +import { + FetchClient, + type FetchClientOptions, + type FetchClientResponse, +} from "./fetch_client"; + +export type BaseGotClientFetchResponse = { + readonly response: Response; +}; + +type InternalGotClientFetchResponse = BaseGotClientFetchResponse & { + badSession: boolean; +}; + +export type GotClientFetchOptions = FetchClientOptions & { + /** + * If a session fails, retry once with a new session before giving up. + */ + trySessionRefresh?: boolean; +}; + +export type GotClientFetchResponse = BaseGotClientFetchResponse & + FetchClientResponse; + +// from @crawlee/util +let gotScraping = (async (...args: Parameters) => { + ({ gotScraping } = await import("got-scraping")); + return gotScraping(...args); +}) as GotScraping; + +export class GotScrapingClient extends FetchClient { + private sessionPool: SessionPool | null = null; + + constructor( + logger?: Logger, + private doSessionRefresh?: boolean, + ) { + super(logger); + } + + async fetch(url: string): Promise { + const logger = this.logger?.child({ label: "gotScrapingClientFetch" }); + const pool = await this.getSessionPool(); + + const response = await this.getResponse(url, pool); + if (response.badSession && this.doSessionRefresh) { + logger?.info("Retrying request with new session."); + const retry = await this.getResponse(url, pool); + return { + body: retry.response.body, + status: retry.response.statusCode, + ok: retry.response.ok, + response: retry.response, + url: retry.response.url, + }; + } + + return { + body: response.response.body, + status: response.response.statusCode, + ok: response.response.ok, + response: response.response, + url: response.response.url, + }; + } + + async buffer(url: string, attempts = 0): Promise { + const pool = await this.getSessionPool(); + const { response, badSession } = await this.getResponse(url, pool); + if (badSession && attempts === 0) { + return this.buffer(url, attempts + 1); + } + return response.rawBody.buffer; + } + + teardown(): Promise | void {} + + private async getSessionPool(): Promise { + this.sessionPool ??= await SessionPool.open({ + maxPoolSize: 100, + sessionOptions: { + maxUsageCount: 5, + }, + }); + return this.sessionPool; + } + + private async getResponse( + url: string, + pool: SessionPool, + logger?: Logger, + ): Promise { + const session = await pool.getSession(); + let response: Response; + try { + response = await gotScraping(url, { + sessionToken: session, + useHeaderGenerator: true, + headerGeneratorOptions: { + browsersListQuery: "> 5%, not dead", + operatingSystems: ["windows", "linux"], + }, + responseType: "text", + retry: { + limit: 3, + statusCodes: [403], + }, + cookieJar: { + getCookieString: async (url: string) => session.getCookieString(url), + setCookie: async (rawCookie: string, url: string) => + session.setCookie(rawCookie, url), + }, + }); + } catch (e) { + logger?.trace(`Error fetching ${url}, marking session as bad`); + session.markBad(); + throw e; + } + + logger?.trace(`Got ${response.statusCode} on ${url}`); + const hadBadStatus = session.retireOnBlockedStatusCodes( + response.statusCode, + ); + if (hadBadStatus) { + logger?.warn(`Warning: Bad status on ${url}, retiring`); + return { response, badSession: true }; + } + session.setCookiesFromResponse(response); + return { response, badSession: false }; + } +} diff --git a/src/clients/index.ts b/packages/scraper/src/clients/index.ts similarity index 100% rename from src/clients/index.ts rename to packages/scraper/src/clients/index.ts diff --git a/src/index.ts b/packages/scraper/src/index.ts similarity index 100% rename from src/index.ts rename to packages/scraper/src/index.ts diff --git a/packages/scraper/src/modules/constants.ts b/packages/scraper/src/modules/constants.ts new file mode 100644 index 0000000..18a5441 --- /dev/null +++ b/packages/scraper/src/modules/constants.ts @@ -0,0 +1,42 @@ +import type { Question, Season } from "../types"; + +export interface IConstants { + DEFAULT_SEASONS: Season[]; + START_YEAR: number; + CURRENT_YEAR: number; + QUESTION_PROPERTIES: readonly (keyof Question)[]; + DEFAULT_PROGRAMS: ["V5RC", "VURC", "VIQRC", "Judging"]; +} + +export const Constants: IConstants = { + START_YEAR: 2018, + CURRENT_YEAR: new Date(Date.now()).getFullYear(), + get DEFAULT_SEASONS() { + return Array(this.CURRENT_YEAR - this.START_YEAR + 1) + .fill(0) + .map( + (_, i) => `${this.START_YEAR + i}-${this.START_YEAR + i + 1}`, + ); + }, + get QUESTION_PROPERTIES() { + return [ + "id", + "url", + "author", + "program", + "title", + "question", + "questionRaw", + "answer", + "answerRaw", + "season", + "askedTimestamp", + "askedTimestampMs", + "answeredTimestamp", + "answeredTimestampMs", + "answered", + "tags", + ] satisfies readonly (keyof Question)[]; + }, + DEFAULT_PROGRAMS: ["V5RC", "VURC", "VIQRC", "Judging"], +}; diff --git a/packages/scraper/src/modules/extractors.ts b/packages/scraper/src/modules/extractors.ts new file mode 100644 index 0000000..946be80 --- /dev/null +++ b/packages/scraper/src/modules/extractors.ts @@ -0,0 +1,117 @@ +import * as cheerio from "cheerio"; +import SELECTORS from "../selectors"; +import type { Question } from "../types"; +import { + type QnaHomeUrl, + type QnaIdUrl, + type QnaPageUrl, + parseQnaUrlWithId, +} from "./parsing"; + +export interface ScrapedPage { + url: U; + html: string; +} + +const unformat = (str: string | undefined | null): string => { + return (str ?? "") + .split(/\n/g) + .map((n) => n.trim()) + .filter(Boolean) + .join(""); +}; + +// https://bugs.chromium.org/p/v8/issues/detail?id=2869 +export const unleak = (str: string | undefined | null): string => { + // biome-ignore lint: style/useTemplate + return (" " + (str ?? "")).slice(1); +}; + +type HtmlPresenceRequired = "Required"; +type HtmlPresenceOptional = "Optional"; +type HtmlPresence = HtmlPresenceRequired | HtmlPresenceOptional; +type SelectHtml = T extends HtmlPresenceRequired + ? string + : string | null; + +const selectHtml = ( + $: cheerio.CheerioAPI, + selector: Parameters[0], +): SelectHtml => { + const text = unleak(unformat($(selector).text())); + return (text.trim() === "" ? null : text) as SelectHtml; +}; + +const selectRawHtml = ( + $: cheerio.CheerioAPI, + selector: Parameters[0], +): SelectHtml => { + const html = unleak(unformat($(selector).html())); + return (html.trim() === "" ? null : html) as SelectHtml; +}; + +export const extractPageQuestions = ({ + html, +}: ScrapedPage): QnaIdUrl[] => { + const $ = cheerio.load(html); + return $(SELECTORS.URLS) + .toArray() + .map((el) => $(el).attr("href")) + .filter((s): s is QnaIdUrl => s !== undefined); +}; + +export const extractPageCount = ({ html }: ScrapedPage): number => { + const $ = cheerio.load(html); + const el = $(SELECTORS.PAGE_COUNT); + return Number.isNaN(Number.parseInt(el.text())) + ? 1 + : Number.parseInt(el.text()); +}; + +export const extractQuestion = ({ + html, + url, +}: ScrapedPage): Question => { + const $ = cheerio.load(html); + + const { id, program, season } = parseQnaUrlWithId(url); + const author = selectHtml<"Required">($, SELECTORS.AUTHOR); + const title = selectHtml<"Required">($, SELECTORS.TITLE); + const question = selectHtml<"Required">($, SELECTORS.QUESTION); + const questionRaw = selectRawHtml<"Required">($, SELECTORS.QUESTION); + const answer = selectHtml($, SELECTORS.ANSWER); + const answerRaw = selectRawHtml($, SELECTORS.ANSWER); + const askedTimestamp = selectHtml<"Required">($, SELECTORS.ASKED_TIMESTAMP); + const askedTimestampMs = new Date(askedTimestamp).getTime(); + const answeredTimestamp = selectHtml($, SELECTORS.ANSWERED_TIMESTAMP); + const answeredTimestampMs = + answeredTimestamp !== null ? new Date(answeredTimestamp).getTime() : null; + const answered = answer !== null; + const tags = $(SELECTORS.TAGS) + .map((_i, el) => unleak($(el).text().trim())) + .get(); + + return { + id, + url, + program, + season, + author, + title, + question, + questionRaw, + answer, + answerRaw, + askedTimestamp, + askedTimestampMs, + answeredTimestamp, + answeredTimestampMs, + answered, + tags, + }; +}; + +export const extractReadOnly = ({ html }: ScrapedPage): boolean => { + const $ = cheerio.load(html); + return selectHtml($, SELECTORS.READONLY) !== null; +}; diff --git a/packages/scraper/src/modules/fetchers.ts b/packages/scraper/src/modules/fetchers.ts new file mode 100644 index 0000000..f0333c8 --- /dev/null +++ b/packages/scraper/src/modules/fetchers.ts @@ -0,0 +1,434 @@ +import type { Logger } from "pino"; +import { + type FetchClient, + type FetchClientOptions, + type FetchClientResponse, + getDefaultFetcherOptions, +} from "../clients"; +import type { Question, Season } from "../types"; +import { type AttemptResult, attempt, nsToMsElapsed, sleep } from "../util"; +import { Constants } from "./constants"; +import { + extractPageCount, + extractPageQuestions, + extractQuestion, + extractReadOnly, +} from "./extractors"; +import { + type QnaHomeUrl, + type QnaIdUrl, + type QnaPageUrl, + buildHomeQnaUrl, + buildQnaUrlWithId, + buildQnaUrlWithPage, +} from "./parsing"; + +export interface FetcherOptions< + T extends FetchClientResponse = FetchClientResponse, +> { + client?: FetchClient; + logger?: Logger; + teardown?: boolean; +} + +/** + * Fetches the page count for the given Q&A + * @param url The Q&A to fetch the page count from + * @param logger Optional {@link Logger} + * @returns The page count for the given Q&A + */ +export const fetchPageCount = async ( + url: QnaHomeUrl, + options?: FetcherOptions, +): Promise => { + const { client, teardown } = await getDefaultFetcherOptions(options); + const html = await client.getHtml(url); + if (html === null) { + return null; + } + const pageCount = extractPageCount({ + url, + html: html.html, + }); + options?.logger?.trace( + { + label: "fetchPageCount", + pageCount, + url, + }, + `Page count for ${url}: ${pageCount}`, + ); + if (teardown) { + await client.teardown(); + } + return pageCount; +}; + +/** + * Checks whether a Q&A for a given program and seasons exists + * @param program The program of the Q&A to ping + * @param season The season of the Q&A to ping + * @param logger Optional {@link Logger} + * @returns true if the Q&A exists, false if it does not + */ +export const pingQna = async ( + program: string, + season: string, + options?: FetcherOptions, +): Promise => { + const { client, teardown } = await getDefaultFetcherOptions(options); + const url = buildHomeQnaUrl({ program, season }); + const ok = client.ping(url); + options?.logger?.trace({ + exists: ok, + label: "pingQna", + program, + season, + }); + if (teardown) { + await client.teardown(); + } + return ok; +}; + +/** + * Fetches data for a given Q&A + * @param url The url of the Q&A + * @param logger Optional {@link Logger} + * @returns The Q&A data from the page + */ +export const fetchQuestion = async ( + url: QnaIdUrl, + options?: FetcherOptions, +): Promise => { + const { client, teardown } = await getDefaultFetcherOptions(options); + const html = await client.getHtml(url); + if (html === null) { + if (teardown) { + await client.teardown(); + } + return null; + } + if (teardown) { + await client.teardown(); + } + return extractQuestion({ url, html: html.html }); +}; + +/** + * Fetches the current season. + * @param logger Optional {@link Logger} + * @returns The current season + */ +export const fetchCurrentSeason = async ( + options?: FetcherOptions, +): Promise => { + const newSeason = await pingQna( + "V5RC", + `${Constants.CURRENT_YEAR}-${Constants.CURRENT_YEAR + 1}`, + options, + ); + const currentSeason: Season = newSeason + ? `${Constants.CURRENT_YEAR}-${Constants.CURRENT_YEAR + 1}` + : `${Constants.CURRENT_YEAR - 1}-${Constants.CURRENT_YEAR}`; + options?.logger?.trace( + { + label: "fetchCurrentSeason", + currentSeason, + }, + `Current season: ${currentSeason}`, + ); + return currentSeason; +}; + +/** + * Generates a list of all seasons to date + * @param logger Optional {@link Logger} + * @returns A list of all seasons to date + */ +export const fetchAllSeasons = async ( + options?: FetcherOptions, +): Promise => { + const allSeasons: Season[] = []; + const [start] = (await fetchCurrentSeason(options)).split("-"); + const startYear = Number.parseInt(start); + for (let year = 2018; year <= startYear; year++) { + allSeasons.push(`${year}-${year + 1}`); + } + options?.logger?.trace({ allSeasons }, "Fetched all seasons"); + return allSeasons; +}; + +/** + * Generates a list of urls with the given program and list of seasons + * @param program The program to generate pages with + * @param seasons The seasons to generate pages with + * @param logger Optional {@link Logger} + * @returns A list of urls corresponding to the given program and seasons + */ +export const fetchPagesForSeasons = async ( + program: string, + seasons: Season[], + options?: FetchClientOptions, +): Promise => { + const urls: QnaPageUrl[] = []; + for (const season of seasons) { + const url = buildHomeQnaUrl({ program, season }); + const pageCount = await fetchPageCount(url, options); + if (pageCount === null) { + options?.logger?.warn( + `Warning: unable to retrieve page count for ${url}`, + ); + continue; + } + for (let page = 1; page <= pageCount; page++) { + urls.push(buildQnaUrlWithPage({ program, season, page })); + } + } + return urls; +}; + +export type PageQuestionsResults = [Question[], string[]]; + +/** + * Fetches Q&A data from the given url + * @param url The Q&A page url to extract data from + * @param logger Optional {@link Logger} + * @returns Q&A data from the given page + */ +export const fetchQuestionsFromPage = async ( + url: QnaPageUrl, + options?: FetcherOptions, +): Promise => { + const { client, teardown } = await getDefaultFetcherOptions(options); + const html = await client.getHtml(url); + if (html === null) { + return null; + } + const urls = extractPageQuestions({ url, html: html.html }); + options?.logger?.trace({ urls }, `Extracted ${urls.length} urls from ${url}`); + const results = await Promise.allSettled( + urls.map((u) => fetchQuestion(u, options)), + ); + const passed: Question[] = []; + const failed: QnaIdUrl[] = []; + results.forEach((result, i) => { + if (result.status === "fulfilled" && result.value !== null) { + passed.push(result.value); + } else { + failed.push(urls[i]); + } + }); + if (teardown) { + await client.teardown(); + } + return [passed, failed]; +}; + +type Job = { + name: string; + job: T; +}; + +/** + * Fetches Q&A data from a list of urls + * @param urls The urls to fetch Q&A data from + * @param logger Optional {@link Logger} + * @param interval Time in milliseconds to wait in between requests + * @returns All Q&A data from the specified pages + */ +export const fetchQuestionsFromPages = async ( + urls: QnaPageUrl[], + options?: FetcherOptions, + interval = 1500, +): Promise => { + const { client, teardown } = await getDefaultFetcherOptions(options); + const jobs: Job>>[] = []; + const startTime = process.hrtime.bigint(); + + for (const url of urls) { + const job = { + name: url, + job: attempt({ + attempts: 3, + callback: () => + fetchQuestionsFromPage(url, { client, teardown: false }), + logger: options?.logger, + }), + }; + jobs.push(job); + await sleep(interval); + } + + const jobResults = await Promise.all(jobs.map((j) => j.job)); + const elapsed = new Date(nsToMsElapsed(startTime)); + const success: Question[] = []; + const failedQuestions: string[] = []; + const failedPages: string[] = []; + jobResults.forEach((job, i) => { + if (job.status === "success" && job.value !== null) { + const [passed, failed] = job.value; + success.push(...passed); + failedQuestions.push(...failed); + } else { + failedPages.push(jobs[i].name); + } + }); + + options?.logger?.info( + { + failedQuestions, + failedPages, + }, + `${success.length} succeeded, ${failedQuestions.length} questions failed, ${failedPages.length} question pages failed.`, + ); + options?.logger?.info( + `Completed in ${elapsed.getMinutes()}min ${elapsed.getSeconds()}s ${elapsed.getMilliseconds()}ms`, + ); + if (teardown) { + await client.teardown(); + } + return success; +}; + +export const fetchQuestionRange = async ( + ids: number[], + options?: FetcherOptions, +): Promise => { + const { client, teardown } = await getDefaultFetcherOptions(options); + const range = ids.map(async (id) => { + const url = buildQnaUrlWithId({ + program: "V5RC", + season: "2020-2021", + id: `${id}`, + }); + const page = await client.getHtml(url); + if (page === null) { + return null; + } + + return extractQuestion({ + html: page.html, + url: page.url as QnaIdUrl, + }); + }); + const results = await Promise.allSettled(range); + if (teardown) { + await client.teardown(); + } + return handleIterativeBatch(ids, results); +}; + +export const ITERATIVE_BATCH_COUNT = 10; +export const ITERATIVE_INTERVAL = 10; + +export type IterativeFetchResult = { + /** + * The list of questions fetched + */ + questions: Question[]; + + /** + * The ids of the questions that could not be retrieved + */ + failures: string[]; +}; + +export type IterativeFetchOptions = FetcherOptions & { + /** + * The ID to start scraping questions from + */ + start?: number; +}; + +export type IterativeBatchResult = { + questions: Question[]; + failed: boolean; + failures: string[]; +}; + +export const handleIterativeBatch = ( + range: number[], + results: PromiseSettledResult[], +): IterativeBatchResult => { + const questions: Question[] = []; + const failures: string[] = []; + for (let i = 0; i < results.length; i++) { + const result = results[i]; + if (result.status === "rejected" || result.value === null) { + failures.push(`${range[i]}`); + continue; + } + questions.push(result.value); + } + return { questions, failed: failures.length === results.length, failures }; +}; + +/** + * Fetches questions iteratively. Instead of generating a list of urls to scrape, we iterate through IDs in batches + * until a batch fails, resulting in faster scraping. Best for when you want a dump of all Q&As. + * @param options Options for defining an optional logger and start point + * @returns Object containing the fecthed Q&As, plus some additional utility data + */ +export const fetchQuestionsIterative = async ( + options?: IterativeFetchOptions, +): Promise => { + const { client, teardown } = await getDefaultFetcherOptions(options); + const start = options?.start !== undefined ? Math.max(options.start, 1) : 1; + let batchFailed = false; + let range = [...Array(ITERATIVE_BATCH_COUNT).keys()].map((n) => start + n); + + const questions: Question[] = []; + const failures: string[] = []; + const startTime = process.hrtime.bigint(); + + while (!batchFailed) { + options?.logger?.trace( + `Scraping question range ${range[0]}-${range.at(-1)}`, + ); + const { + questions: batchQuestions, + failed, + failures: batchFailures, + } = await fetchQuestionRange(range, { client, teardown: false }); + questions.push(...batchQuestions); + if (failed) { + options?.logger?.info( + `Batch failed for range ${range[0]}-${range.at(-1)}, exiting`, + ); + batchFailed = true; + } else { + failures.push(...batchFailures); + range = range.map((n) => n + ITERATIVE_INTERVAL); + await sleep(1500); + } + } + + const elapsed = new Date(nsToMsElapsed(startTime)); + options?.logger?.info(`Scraped ${questions.length} questions`); + options?.logger?.info(`Failed getting ${failures.length} questions`); + options?.logger?.info( + `Completed in ${elapsed.getMinutes()}min ${elapsed.getSeconds()}s ${elapsed.getMilliseconds()}ms`, + ); + + if (teardown) { + await client.teardown(); + } + return { questions, failures }; +}; + +export const checkIfReadOnly = async ( + program: string, + season: Season, + options?: FetcherOptions, +): Promise => { + const { client, teardown } = await getDefaultFetcherOptions(options); + const html = await client.getHtml(buildHomeQnaUrl({ program, season })); + if (html === null) { + return null; + } + if (teardown) { + await client.teardown(); + } + return extractReadOnly({ url: html.url as QnaHomeUrl, html: html.html }); +}; diff --git a/packages/scraper/src/modules/generators.ts b/packages/scraper/src/modules/generators.ts new file mode 100644 index 0000000..61b57ba --- /dev/null +++ b/packages/scraper/src/modules/generators.ts @@ -0,0 +1,118 @@ +import type { Logger } from "pino"; +import type { Program, Season } from "../types"; +import { Constants } from "./constants"; +import { fetchPagesForSeasons, pingQna } from "./fetchers"; +import type { QnaPageUrl } from "./parsing"; + +const unique = (arr: T[]): T[] => arr.filter((a, i) => arr.indexOf(a) === i); + +export type YearFilters = Season[]; +export type ProgramFilters = { + [k in Program]?: Season[]; +}; +export type QnaFilters = ProgramFilters | YearFilters; + +export interface GeneratorOptions { + logger?: Logger; +} + +/** + * Verifies that a Q&A exists, actually validating that the program and season is valid before calling {@link pingQna} + * @param program The program of the Q&A to check + * @param season The season of the Q&A to check + */ +export const verifyQnaExists = async ( + program: string, + season: Season, +): Promise => { + const match = season.match(/(?\d{4})-(?\d{4})/); + if (!match?.groups) { + throw Error(`${season} does not match the format '{year}-{year}'.`); + } + + if ( + Number.parseInt(match.groups.end) - Number.parseInt(match.groups.start) !== + 1 + ) { + throw Error(`${season} does not match the format '{year}-{year + 1}'`); + } + + const exists = await pingQna(program, season); + if (!exists) { + throw Error(`Unable to find a ${program} Q&A for the ${season} season`); + } +}; + +const verifyQnasExist = async ( + program: string, + seasons: Season[], +): Promise => { + await Promise.all(seasons.map((s) => verifyQnaExists(program, s))); +}; + +const processFilters = async ( + filters?: QnaFilters, + logger?: Pick, +): Promise<[string[], Season[][]]> => { + const programs: string[] = []; + const seasons: Season[][] = []; + + if (!filters) { + logger?.trace("No filters provided."); + return [[], []]; + } + + if (Array.isArray(filters)) { + const uniqueSeasons = unique(filters); + for (const program of Constants.DEFAULT_PROGRAMS) { + await verifyQnasExist(program, uniqueSeasons); + if (program === "Judging") { + programs.push(program); + seasons.push([uniqueSeasons[0]]); + } else { + programs.push(program); + seasons.push(uniqueSeasons); + } + } + return [programs, seasons]; + } + + const entries = Object.entries(filters); + for (const [program, entrySeasons] of entries) { + const uniqueSeasons = unique(entrySeasons); + await verifyQnasExist(program, uniqueSeasons); + if (program === "Judging") { + programs.push(program); + seasons.push([uniqueSeasons[0]]); + } else { + programs.push(program); + seasons.push(uniqueSeasons); + } + } + + return [programs, seasons]; +}; + +/** + * Generate a list of urls to scrape based on the given filters + * @param filters The filters to apply + * @returns A list of urls to scrape that match the given filters + */ +export const getScrapingUrls = async ( + filters?: QnaFilters, + options?: GeneratorOptions, +): Promise => { + const [programs, seasons] = await processFilters(filters, options?.logger); + const urls: QnaPageUrl[] = []; + for (let ci = 0; ci < programs.length; ci++) { + const program = programs[ci]; + const seasonList = seasons[ci]; + const pages = await fetchPagesForSeasons(program, seasonList, options); + urls.push(...pages); + } + options?.logger?.trace( + { urls }, + `Created ${urls.length} urls that satisfy the provided filters.`, + ); + return urls; +}; diff --git a/src/modules/index.ts b/packages/scraper/src/modules/index.ts similarity index 100% rename from src/modules/index.ts rename to packages/scraper/src/modules/index.ts diff --git a/packages/scraper/src/modules/parsing.ts b/packages/scraper/src/modules/parsing.ts new file mode 100644 index 0000000..e2d1d22 --- /dev/null +++ b/packages/scraper/src/modules/parsing.ts @@ -0,0 +1,59 @@ +interface BaseQnaUrlParams { + program: string; + season: string; +} + +interface QnaUrlIdParams extends BaseQnaUrlParams { + id: string; +} + +interface QnaUrlPageParams extends BaseQnaUrlParams { + page: number; +} + +export type QnaHomeUrl = `https://www.robotevents.com/${string}/${string}/QA`; +export type QnaPageUrl = `${QnaHomeUrl}?page=${string}`; +export type QnaIdUrl = `${QnaHomeUrl}/${string}`; + +export const validateQnaUrl = (url: string): Record => { + const regex = + /^https:\/\/www\.robotevents\.com\/(?\w+)\/(?\d{4}-\d{4})\/QA(?:\/(?\d+))?(?:\?page=(?\d+))?$/; + const match = url.match(regex); + if (!match?.groups) { + throw Error(`${url} in unrecognized format.`); + } + return match.groups; +}; + +export const parseQnaUrlWithId = (url: QnaIdUrl): QnaUrlIdParams => { + const parsed = validateQnaUrl(url); + return { + program: parsed.program, + season: parsed.season, + id: parsed.id, + }; +}; + +export const parseQnaUrlWithPage = (url: QnaPageUrl): QnaUrlPageParams => { + const parsed = validateQnaUrl(url); + return { + program: parsed.program, + season: parsed.season, + page: Number.parseInt(parsed.page), + }; +}; + +export const buildHomeQnaUrl = (params: BaseQnaUrlParams): QnaHomeUrl => { + const { program, season } = params; + return `https://www.robotevents.com/${program}/${season}/QA`; +}; + +export const buildQnaUrlWithId = (params: QnaUrlIdParams): QnaIdUrl => { + const { program, season, id } = params; + return `https://www.robotevents.com/${program}/${season}/QA/${id}`; +}; + +export const buildQnaUrlWithPage = (params: QnaUrlPageParams): QnaPageUrl => { + const { program, season, page } = params; + return `https://www.robotevents.com/${program}/${season}/QA?page=${page}`; +}; diff --git a/packages/scraper/src/modules/query.ts b/packages/scraper/src/modules/query.ts new file mode 100644 index 0000000..a9c77cd --- /dev/null +++ b/packages/scraper/src/modules/query.ts @@ -0,0 +1,95 @@ +import type { Question, Season } from "../types"; +import { + type FetcherOptions, + type IterativeFetchOptions, + type IterativeFetchResult, + fetchCurrentSeason, + fetchQuestionsFromPages, + fetchQuestionsIterative, +} from "./fetchers"; +import { type QnaFilters, getScrapingUrls } from "./generators"; + +/** + * Utility wrapper around {@link getQuestions} that gets unanswered questions for the current season. + * @param logger Optional {@link Logger} + * @returns All questions that have not been answered. + */ +export const getUnansweredQuestions = async ( + options?: FetcherOptions, +): Promise => { + const questions = await getQuestions(undefined, options); + return questions.filter((q) => !q.answered); +}; + +/** + * Get questions with an optional filter. + * @param filters Optional filters to limit the results retreived. Defaults to filtering by current season. + * @param logger Optional {@link Logger} + * @returns All questions that passed the filter. + */ +export const getQuestions = async ( + filters?: QnaFilters, + options?: FetcherOptions, +): Promise => { + const finalFilters = filters ?? [await fetchCurrentSeason(options)]; + const urls = await getScrapingUrls(finalFilters, options); + return fetchQuestionsFromPages(urls, options); +}; + +/** + * Gets all questions. Includes questions that may not be shown on the Q&A homepage. + * @param logger Optional {@link Logger} + * @returns All questions from every season + */ +export const getAllQuestions = async ( + options?: IterativeFetchOptions, +): Promise => { + return await fetchQuestionsIterative(options); +}; + +/** + * Gets the oldest unanswered question for a given season. + * @param questions The questions to operate on + * @param season The season in which to search in + * @returns The oldest question asked for the given season, if any + */ +export const getOldestUnansweredQuestion = ( + questions: Question[], + season: Season, +): Question | undefined => { + const data = [...questions]; + data.sort( + (q1, q2) => + q1.askedTimestampMs - + q2.askedTimestampMs + + (Number.parseInt(q1.id) - Number.parseInt(q2.id)), + ); + return data.find( + (q) => + q.answered === false && + q.season === season && + !q.title.startsWith("[archived]"), + ); +}; + +/** + * Gets the oldest unanswered question for a given season. + * @param questions The questions to operate on + * @param season The season in which to search in + * @returns The oldest question asked for the given season, if any + */ +export const getOldestQuestion = ( + questions: Question[], + season: Season, +): Question | undefined => { + const data = [...questions]; + data.sort( + (q1, q2) => + q1.askedTimestampMs - + q2.askedTimestampMs + + (Number.parseInt(q1.id) - Number.parseInt(q2.id)), + ); + return data.find( + (q) => q.season === season && !q.title.startsWith("[archived]"), + ); +}; diff --git a/packages/scraper/src/modules/rules.ts b/packages/scraper/src/modules/rules.ts new file mode 100644 index 0000000..2e2543e --- /dev/null +++ b/packages/scraper/src/modules/rules.ts @@ -0,0 +1,46 @@ +import { parsepdf } from "node-pdf-parser"; +import { getDefaultFetcherOptions } from "../clients"; +import type { FetcherOptions } from "./fetchers"; + +export const RULE_TABLE_PATTERN = + /(?<[A-Z]+\d+>) (?[A-Z](?:.+\.?))+?/g; + +export interface Rule { + name: string; + summary: string; +} + +export const extractRules = async ( + url: string, + options?: FetcherOptions, +): Promise => { + const logger = options?.logger?.child({ label: "extractRules" }); + const { client, teardown } = await getDefaultFetcherOptions(options); + const buffer = await client.buffer(url); + if (buffer === null) { + return null; + } + const content = await parsepdf(buffer); + const text = content.pages.join("\n"); + const matches = Array.from(text.matchAll(RULE_TABLE_PATTERN)); + const rules: Rule[] = []; + for (const match of matches) { + const name = match.groups?.name; + const summary = match.groups?.summary; + if ( + name === undefined || + summary === undefined || + rules.find((r) => r.name === name) + ) { + logger?.trace(`Already added rule ${name}, skipping.`); + continue; + } + logger?.debug("Adding new rule: ", name); + rules.push({ name, summary }); + } + if (teardown) { + await client.teardown(); + } + logger?.debug(`Found ${rules.length} rules.`); + return rules; +}; diff --git a/packages/scraper/src/selectors.ts b/packages/scraper/src/selectors.ts new file mode 100644 index 0000000..dde2bf4 --- /dev/null +++ b/packages/scraper/src/selectors.ts @@ -0,0 +1,12 @@ +export default { + URLS: "div.card-body h4.title > a", + AUTHOR: "div.author", + TITLE: "div.question > h4", + QUESTION: "div.content-body:nth-child(4)", + ANSWER: "div.answer.approved .content-body", + ASKED_TIMESTAMP: "div.details:nth-child(3) > div:nth-child(2)", + ANSWERED_TIMESTAMP: "div.pull-right", + TAGS: "div.tags a", + PAGE_COUNT: "nav ul.pagination li:nth-last-child(2)", + READONLY: "div.alert-warning", +}; diff --git a/packages/scraper/src/types.ts b/packages/scraper/src/types.ts new file mode 100644 index 0000000..70f1cc5 --- /dev/null +++ b/packages/scraper/src/types.ts @@ -0,0 +1,87 @@ +import type { Constants } from "./modules/constants"; + +export interface Question { + /** + * The question's numerical ID. + */ + id: string; + + /** + * The url of the question. + */ + url: string; + + /** + * The person who asked the question. + */ + author: string; + + /** + * The program this question was asked in (e.g., V5RC, VURC, etc). + */ + program: string; + + /** + * The title of the question. + */ + title: string; + + /** + * The question content. + */ + question: string; + + /** + * The question content as raw html + */ + questionRaw: string; + + /** + * The answer to the question. + */ + answer: string | null; + + /** + * The answer content as raw html + */ + answerRaw: string | null; + + /** + * The season this question was asked in (e.g., 2022-2023). + */ + season: string; + + /** + * When this question was asked (in the format DD-Mon-YYYY). + */ + askedTimestamp: string; + + /** + * {@link askedTimestamp} in milliseconds. + */ + askedTimestampMs: number; + + /** + * When this question was answered (in the format DD-Mon-YYYY). + */ + answeredTimestamp: string | null; + + /** + * {@link answeredTimestamp} in milliseconds. + */ + answeredTimestampMs: number | null; + + /** + * Whether the question was answered. + */ + answered: boolean; + + /** + * Tags added to this question. + */ + tags: string[]; +} + +export type Season = `${number}-${number}`; + +export type Program = (typeof Constants.DEFAULT_PROGRAMS)[number]; diff --git a/packages/scraper/src/util/attempt.ts b/packages/scraper/src/util/attempt.ts new file mode 100644 index 0000000..1470fc8 --- /dev/null +++ b/packages/scraper/src/util/attempt.ts @@ -0,0 +1,42 @@ +import type { Logger } from "pino"; + +export interface AttemptOptions { + callback: () => T | Promise; + onRetry?: (attempts: number) => void; + logger?: Pick; + attempts: number; +} + +export interface AttemptSuccess { + status: "success"; + value: T; +} + +export interface AttemptFailure { + status: "failure"; +} + +export type AttemptResult = AttemptSuccess | AttemptFailure; + +export const attempt = async ( + options: AttemptOptions, +): Promise> => { + let result: T | undefined = undefined; + + for (let i = 0; i < options.attempts; i++) { + try { + result = await options.callback(); + return { + status: "success", + value: result, + }; + } catch (e) { + options.logger?.error(e); + options.onRetry?.(i); + } + } + + return { + status: "failure", + }; +}; diff --git a/src/util/index.ts b/packages/scraper/src/util/index.ts similarity index 100% rename from src/util/index.ts rename to packages/scraper/src/util/index.ts diff --git a/src/util/timing.ts b/packages/scraper/src/util/timing.ts similarity index 51% rename from src/util/timing.ts rename to packages/scraper/src/util/timing.ts index f2e11da..6b24433 100644 --- a/src/util/timing.ts +++ b/packages/scraper/src/util/timing.ts @@ -1,11 +1,11 @@ export const nsToMsElapsed = (start: bigint): number => { - return nsToMs(process.hrtime.bigint() - start); + return nsToMs(process.hrtime.bigint() - start); }; export const nsToMs = (ns: bigint): number => { - return Number((Number(ns) / 1e6).toFixed(3)); + return Number((Number(ns) / 1e6).toFixed(3)); }; export const sleep = (ms: number): Promise => { - return new Promise((resolve) => setTimeout(resolve, ms)); + return new Promise((resolve) => setTimeout(resolve, ms)); }; diff --git a/tests/data/judging_home_page.ts b/packages/scraper/tests/data/judging_home_page.ts similarity index 99% rename from tests/data/judging_home_page.ts rename to packages/scraper/tests/data/judging_home_page.ts index 4a03fd3..d1fdce1 100644 --- a/tests/data/judging_home_page.ts +++ b/packages/scraper/tests/data/judging_home_page.ts @@ -1,9 +1,9 @@ -import { ScrapedPage } from "../../src/modules/extractors"; -import { QnaHomeUrl } from "../../src/modules/parsing"; +import type { ScrapedPage } from "../../src/modules/extractors"; +import type { QnaHomeUrl } from "../../src/modules/parsing"; export default { - url: "https://www.robotevents.com/judging/2023-2024/QA", - html: ` + url: "https://www.robotevents.com/judging/2023-2024/QA", + html: ` @@ -588,5 +588,5 @@ export default { -` +`, } satisfies ScrapedPage; diff --git a/packages/scraper/tests/data/test_questions.ts b/packages/scraper/tests/data/test_questions.ts new file mode 100644 index 0000000..fe5d3d8 --- /dev/null +++ b/packages/scraper/tests/data/test_questions.ts @@ -0,0 +1,449 @@ +/* eslint-dsiable sonarjs/no-duplicate-string */ + +import type { Question } from "../../src"; + +export const TEST_SEASON = "2024-2025"; + +export const OLDEST_TEST_QUESTION_UNIQUE_DATES: Question = { + id: "2059", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2059", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "21-Jul-2024", + askedTimestampMs: 1721545200000, + answeredTimestamp: null, + answeredTimestampMs: null, + answered: false, + tags: ["SG1"], +}; + +export const TEST_QUESTIONS_UNIQUE_DATES: Question[] = [ + { + id: "2057", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2057", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "19-Jul-2024", + askedTimestampMs: 1721372400000, + answeredTimestamp: "19-Jul-2024", + answeredTimestampMs: 1721372400000, + answered: true, + tags: ["SG1"], + }, + { + id: "2058", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2058", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "20-Jul-2024", + askedTimestampMs: 1721458800000, + answeredTimestamp: "20-Jul-2024", + answeredTimestampMs: 1721458800000, + answered: true, + tags: ["SG1"], + }, + { + id: "2059", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2059", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "21-Jul-2024", + askedTimestampMs: 1721545200000, + answeredTimestamp: null, + answeredTimestampMs: null, + answered: false, + tags: ["SG1"], + }, + { + id: "2060", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2060", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "22-Jul-2024", + askedTimestampMs: 1721631600000, + answeredTimestamp: "22-Jul-2024", + answeredTimestampMs: 1721631600000, + answered: true, + tags: ["SG1"], + }, + { + id: "2061", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2061", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "23-Jul-2024", + askedTimestampMs: 1721718000000, + answeredTimestamp: null, + answeredTimestampMs: null, + answered: false, + tags: ["SG1"], + }, + { + id: "2062", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2062", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "24-Jul-2024", + askedTimestampMs: 1721804400000, + answeredTimestamp: null, + answeredTimestampMs: null, + answered: false, + tags: ["SG1"], + }, + { + id: "2063", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2063", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "25-Jul-2024", + askedTimestampMs: 1721890800000, + answeredTimestamp: "25-Jul-2024", + answeredTimestampMs: 1721890800000, + answered: true, + tags: ["SG1"], + }, +]; + +export const OLDEST_TEST_QUESTIONS_OVERLAPPING_DATES: Question = { + id: "2058", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2058", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "20-Jul-2024", + askedTimestampMs: 1721458800000, + answeredTimestamp: null, + answeredTimestampMs: null, + answered: false, + tags: ["SG1"], +}; + +export const TEST_QUESTIONS_OVERLAPPING_DATES: Question[] = [ + { + id: "2057", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2057", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "19-Jul-2024", + askedTimestampMs: 1721372400000, + answeredTimestamp: "19-Jul-2024", + answeredTimestampMs: 1721372400000, + answered: true, + tags: ["SG1"], + }, + { + id: "2060", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2060", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "22-Jul-2024", + askedTimestampMs: 1721631600000, + answeredTimestamp: "22-Jul-2024", + answeredTimestampMs: 1721631600000, + answered: true, + tags: ["SG1"], + }, + { + id: "2061", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2061", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "23-Jul-2024", + askedTimestampMs: 1721718000000, + answeredTimestamp: null, + answeredTimestampMs: null, + answered: false, + tags: ["SG1"], + }, + { + id: "2059", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2059", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "20-Jul-2024", + askedTimestampMs: 1721458800000, + answeredTimestamp: null, + answeredTimestampMs: null, + answered: false, + tags: ["SG1"], + }, + { + id: "2058", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2058", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "20-Jul-2024", + askedTimestampMs: 1721458800000, + answeredTimestamp: null, + answeredTimestampMs: null, + answered: false, + tags: ["SG1"], + }, + { + id: "2062", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2062", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "24-Jul-2024", + askedTimestampMs: 1721804400000, + answeredTimestamp: null, + answeredTimestampMs: null, + answered: false, + tags: ["SG1"], + }, + { + id: "2063", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2063", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "24-Jul-2024", + askedTimestampMs: 1721804400000, + answeredTimestamp: null, + answeredTimestampMs: null, + answered: false, + tags: ["SG1"], + }, +]; + +export const OLDEST_TEST_QUESTIONS_MIXED_OVERLAPPING_DATES: Question = { + id: "2061", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2061", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "23-Jul-2024", + askedTimestampMs: 1721718000000, + answeredTimestamp: null, + answeredTimestampMs: null, + answered: false, + tags: ["SG1"], +}; + +export const TEST_QUESTIONS_MIXED_OVERLAPPING_DATES: Question[] = [ + { + id: "2059", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2059", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "20-Jul-2024", + askedTimestampMs: 1721458800000, + answeredTimestamp: "20-Jul-2024", + answeredTimestampMs: 1721458800000, + answered: true, + tags: ["SG1"], + }, + { + id: "2058", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2058", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "20-Jul-2024", + askedTimestampMs: 1721458800000, + answeredTimestamp: "20-Jul-2024", + answeredTimestampMs: 1721458800000, + answered: true, + tags: ["SG1"], + }, + { + id: "2063", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2063", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "24-Jul-2024", + askedTimestampMs: 1721804400000, + answeredTimestamp: null, + answeredTimestampMs: null, + answered: false, + tags: ["SG1"], + }, + { + id: "2060", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2060", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "22-Jul-2024", + askedTimestampMs: 1721631600000, + answeredTimestamp: "22-Jul-2024", + answeredTimestampMs: 1721631600000, + answered: true, + tags: ["SG1"], + }, + { + id: "2062", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2062", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "23-Jul-2024", + askedTimestampMs: 1721718000000, + answeredTimestamp: null, + answeredTimestampMs: null, + answered: false, + tags: ["SG1"], + }, + { + id: "2057", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2057", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "19-Jul-2024", + askedTimestampMs: 1721372400000, + answeredTimestamp: "19-Jul-2024", + answeredTimestampMs: 1721372400000, + answered: true, + tags: ["SG1"], + }, + { + id: "2061", + url: "https://www.robotevents.com/V5RC/2024-2025/QA/2061", + program: "V5RC", + season: "2024-2025", + author: "", + title: "Test 1", + question: "", + questionRaw: "", + answer: "", + answerRaw: "", + askedTimestamp: "23-Jul-2024", + askedTimestampMs: 1721718000000, + answeredTimestamp: null, + answeredTimestampMs: null, + answered: false, + tags: ["SG1"], + }, +]; diff --git a/tests/data/v5rc_home_page.ts b/packages/scraper/tests/data/v5rc_home_page.ts similarity index 99% rename from tests/data/v5rc_home_page.ts rename to packages/scraper/tests/data/v5rc_home_page.ts index 91954ba..61fc06d 100644 --- a/tests/data/v5rc_home_page.ts +++ b/packages/scraper/tests/data/v5rc_home_page.ts @@ -1,9 +1,9 @@ -import { ScrapedPage } from "../../src/modules/extractors"; -import { QnaHomeUrl } from "../../src/modules/parsing"; +import type { ScrapedPage } from "../../src/modules/extractors"; +import type { QnaHomeUrl } from "../../src/modules/parsing"; export default { - url: "https://www.robotevents.com/V5RC/2023-2024/QA", - html: ` + url: "https://www.robotevents.com/V5RC/2023-2024/QA", + html: ` @@ -862,5 +862,5 @@ export default { -` +`, } satisfies ScrapedPage; diff --git a/tests/data/v5rc_non_readonly_page.ts b/packages/scraper/tests/data/v5rc_non_readonly_page.ts similarity index 99% rename from tests/data/v5rc_non_readonly_page.ts rename to packages/scraper/tests/data/v5rc_non_readonly_page.ts index cc518f2..8dae504 100644 --- a/tests/data/v5rc_non_readonly_page.ts +++ b/packages/scraper/tests/data/v5rc_non_readonly_page.ts @@ -1,9 +1,9 @@ -import { ScrapedPage } from "../../src/modules/extractors"; -import { QnaHomeUrl } from "../../src/modules/parsing"; +import type { ScrapedPage } from "../../src/modules/extractors"; +import type { QnaHomeUrl } from "../../src/modules/parsing"; export default { - url: "https://www.robotevents.com/V5RC/2023-2024/QA", - html: ` + url: "https://www.robotevents.com/V5RC/2023-2024/QA", + html: ` @@ -863,5 +863,5 @@ export default { -` -} satisfies ScrapedPage; \ No newline at end of file +`, +} satisfies ScrapedPage; diff --git a/tests/data/v5rc_question_page.ts b/packages/scraper/tests/data/v5rc_question_page.ts similarity index 99% rename from tests/data/v5rc_question_page.ts rename to packages/scraper/tests/data/v5rc_question_page.ts index 62105eb..258e748 100644 --- a/tests/data/v5rc_question_page.ts +++ b/packages/scraper/tests/data/v5rc_question_page.ts @@ -1,9 +1,9 @@ -import { ScrapedPage } from "../../src/modules/extractors"; -import { QnaIdUrl } from "../../src/modules/parsing"; +import type { ScrapedPage } from "../../src/modules/extractors"; +import type { QnaIdUrl } from "../../src/modules/parsing"; export default { - url: "https://www.robotevents.com/V5RC/2023-2024/QA/1591", - html: ` + url: "https://www.robotevents.com/V5RC/2023-2024/QA/1591", + html: ` @@ -532,5 +532,5 @@ export default { -` +`, } satisfies ScrapedPage; diff --git a/packages/scraper/tests/data/v5rc_question_page_json.ts b/packages/scraper/tests/data/v5rc_question_page_json.ts new file mode 100644 index 0000000..904f28a --- /dev/null +++ b/packages/scraper/tests/data/v5rc_question_page_json.ts @@ -0,0 +1,22 @@ +export default { + id: "1591", + url: "https://www.robotevents.com/V5RC/2023-2024/QA/1591", + program: "V5RC", + season: "2023-2024", + author: "14316A", + title: "The position of triballs in Match Load Zone", + question: + "Note: The Triballs which start in each Match Load Zone must be contacting the Match Load Zone at the start of the Match. However, they may be repositioned during pre-Match setup by the Team whose Robot is using the Starting Tiles adjacent to that Match Load Zone. For example, in Figure 26, Red Robot 1 would be permitted to reposition the Triball in the lower-left red Match Load Zone.Is it legal to place the triball which starts in the Match Load Zone as in the photo?", + questionRaw: + '

<SG1>Note: The Triballs which start in each Match Load Zone must be contacting the Match Load Zone at the start of the Match. However, they may be repositioned during pre-Match setup by the Team whose Robot is using the Starting Tiles adjacent to that Match Load Zone. For example, in Figure 26, Red Robot 1 would be permitted to reposition the Triball in the lower-left red Match Load Zone.

Is it legal to place the triball which starts in the Match Load Zone as in the photo?img

', + answer: + 'The Match Load Zone is defined as "The portion of the floor tile bordered by a Match Load Bar and an inside corner of the Field Perimeter." The example you provided--and any other position that meets the requirement of the note in (contacting the Match Load Zone)--is legal for a Triball that begins the Match within a Match Load Zone.', + answerRaw: + '

The Match Load Zone is defined as "The portion of the floor tile bordered by a Match Load Bar and an inside corner of the Field Perimeter." The example you provided--and any other position that meets the requirement of the note in <SG1> (contacting the Match Load Zone)--is legal for a Triball that begins the Match within a Match Load Zone.

', + askedTimestamp: "18-Jul-2023", + askedTimestampMs: new Date("18-Jul-2023").getTime(), + answeredTimestamp: "24-Jul-2023", + answeredTimestampMs: new Date("24-Jul-2023").getTime(), + answered: true, + tags: ["SG1"], +}; diff --git a/tests/data/vurc_home_page.ts b/packages/scraper/tests/data/vurc_home_page.ts similarity index 99% rename from tests/data/vurc_home_page.ts rename to packages/scraper/tests/data/vurc_home_page.ts index 53714e8..99426c0 100644 --- a/tests/data/vurc_home_page.ts +++ b/packages/scraper/tests/data/vurc_home_page.ts @@ -1,9 +1,9 @@ -import { ScrapedPage } from "../../src/modules/extractors"; -import { QnaPageUrl } from "../../src/modules/parsing"; +import type { ScrapedPage } from "../../src/modules/extractors"; +import type { QnaPageUrl } from "../../src/modules/parsing"; export default { - url: "https://www.robotevents.com/vexu/2023-2024/QA?page=1", - html: ` + url: "https://www.robotevents.com/vexu/2023-2024/QA?page=1", + html: ` @@ -789,5 +789,5 @@ export default { -` +`, } satisfies ScrapedPage; diff --git a/packages/scraper/tests/extractors.test.ts b/packages/scraper/tests/extractors.test.ts new file mode 100644 index 0000000..ed3b710 --- /dev/null +++ b/packages/scraper/tests/extractors.test.ts @@ -0,0 +1,57 @@ +import { describe, expect, it, test } from "vitest"; +import { + extractPageCount, + extractPageQuestions, + extractQuestion, + extractReadOnly, +} from "../src/modules/extractors"; +import judging_home_page from "./data/judging_home_page"; +import v5rc_home_page from "./data/v5rc_home_page"; +import v5rc_non_readonly_page from "./data/v5rc_non_readonly_page"; +import v5rc_question_page from "./data/v5rc_question_page"; +import v5rc_question_page_json from "./data/v5rc_question_page_json"; +import vurc_home_page from "./data/vurc_home_page"; + +describe("extractPageCount", () => { + it("shall return the correct page number when the pagination element is present", () => { + const data = extractPageCount(v5rc_home_page); + expect(data).toEqual(28); + }); + + it("shall return '1' when no pagination element is present", () => { + const data = extractPageCount(judging_home_page); + expect(data).toEqual(1); + }); +}); + +describe("extractQuestionData", () => { + it("shall correctly extract data from a question page", () => { + const data = extractQuestion(v5rc_question_page); + expect(data).toStrictEqual(v5rc_question_page_json); + }); +}); + +describe("extractPageQuestions", () => { + it("shall extract questions from a Q&A page", () => { + const data = extractPageQuestions(vurc_home_page); + expect(data).toEqual([ + "https://www.robotevents.com/VURC/2023-2024/QA/1969", + "https://www.robotevents.com/VURC/2023-2024/QA/1946", + "https://www.robotevents.com/VURC/2023-2024/QA/1945", + "https://www.robotevents.com/VURC/2023-2024/QA/1942", + "https://www.robotevents.com/VURC/2023-2024/QA/1932", + "https://www.robotevents.com/VURC/2023-2024/QA/1927", + "https://www.robotevents.com/VURC/2023-2024/QA/1925", + "https://www.robotevents.com/VURC/2023-2024/QA/1924", + "https://www.robotevents.com/VURC/2023-2024/QA/1923", + "https://www.robotevents.com/VURC/2023-2024/QA/1922", + ]); + }); +}); + +describe("extractReadOnly", () => { + it("shall extract the readonly status from a Q&A page", () => { + expect(extractReadOnly(v5rc_home_page)).toBe(true); + expect(extractReadOnly(v5rc_non_readonly_page)).toBe(false); + }); +}); diff --git a/packages/scraper/tests/parsing.test.ts b/packages/scraper/tests/parsing.test.ts new file mode 100644 index 0000000..c33ea87 --- /dev/null +++ b/packages/scraper/tests/parsing.test.ts @@ -0,0 +1,77 @@ +import { describe, expect, it, test } from "vitest"; +import { + type QnaHomeUrl, + type QnaIdUrl, + type QnaPageUrl, + buildHomeQnaUrl, + buildQnaUrlWithId, + buildQnaUrlWithPage, + parseQnaUrlWithId, + parseQnaUrlWithPage, + validateQnaUrl, +} from "../src/modules/parsing"; + +const TEST_SEASON = "2023-2024"; +const TEST_PROGRAM = "V5RC"; +const TEST_QUESTION_ID = "1591"; +const TEST_PAGE_NUM = 1; + +const VALID_HOME_URL: QnaHomeUrl = `https://www.robotevents.com/${TEST_PROGRAM}/${TEST_SEASON}/QA`; +const VALID_QUESTION_URL: QnaIdUrl = `https://www.robotevents.com/${TEST_PROGRAM}/${TEST_SEASON}/QA/${TEST_QUESTION_ID}`; +const VALID_PAGINATED_URL: QnaPageUrl = `https://www.robotevents.com/${TEST_PROGRAM}/${TEST_SEASON}/QA?page=${TEST_PAGE_NUM}`; +const INVALID_URL = "INVALID_URL"; + +describe("validateQnaUrl", () => { + it("shall throw when the url is in an invalid format", () => { + expect(() => validateQnaUrl(INVALID_URL)).toThrow(); + }); + it("shall returned the url as a parsed object when the url is valid", () => { + const parsed = validateQnaUrl(VALID_HOME_URL); + expect(parsed).toEqual({ program: TEST_PROGRAM, season: TEST_SEASON }); + }); +}); + +describe("Parsing Functions", () => { + it("shall parse question page urls", () => { + const parsed = parseQnaUrlWithId(VALID_QUESTION_URL); + expect(parsed).toEqual({ + program: TEST_PROGRAM, + season: TEST_SEASON, + id: TEST_QUESTION_ID, + }); + }); + + it("shall parse paginated Q&A urls", () => { + const parsed = parseQnaUrlWithPage(VALID_PAGINATED_URL); + expect(parsed).toEqual({ + program: TEST_PROGRAM, + season: TEST_SEASON, + page: TEST_PAGE_NUM, + }); + }); +}); + +describe("Builder Functions", () => { + it("shall build the correct home url", () => { + const url = buildHomeQnaUrl({ program: TEST_PROGRAM, season: TEST_SEASON }); + expect(url).toEqual(VALID_HOME_URL); + }); + + it("shall build the correct id url", () => { + const url = buildQnaUrlWithId({ + program: TEST_PROGRAM, + season: TEST_SEASON, + id: TEST_QUESTION_ID, + }); + expect(url).toEqual(VALID_QUESTION_URL); + }); + + it("shall build the correct paginated url", () => { + const url = buildQnaUrlWithPage({ + program: TEST_PROGRAM, + season: TEST_SEASON, + page: TEST_PAGE_NUM, + }); + expect(url).toEqual(VALID_PAGINATED_URL); + }); +}); diff --git a/packages/scraper/tests/query.test.ts b/packages/scraper/tests/query.test.ts new file mode 100644 index 0000000..2398351 --- /dev/null +++ b/packages/scraper/tests/query.test.ts @@ -0,0 +1,37 @@ +import { describe, expect, it, test } from "vitest"; +import { getOldestUnansweredQuestion } from "../src/modules/query"; +import { + OLDEST_TEST_QUESTIONS_MIXED_OVERLAPPING_DATES, + OLDEST_TEST_QUESTIONS_OVERLAPPING_DATES, + OLDEST_TEST_QUESTION_UNIQUE_DATES, + TEST_QUESTIONS_MIXED_OVERLAPPING_DATES, + TEST_QUESTIONS_OVERLAPPING_DATES, + TEST_QUESTIONS_UNIQUE_DATES, + TEST_SEASON, +} from "./data/test_questions"; + +describe("getOldestUnansweredQuestion", () => { + it("should get the oldest unanswered question when dates are unique", () => { + expect( + getOldestUnansweredQuestion(TEST_QUESTIONS_UNIQUE_DATES, TEST_SEASON), + ).toEqual(OLDEST_TEST_QUESTION_UNIQUE_DATES); + }); + + it("should get the oldest unanswered question when dates overlap", () => { + expect( + getOldestUnansweredQuestion( + TEST_QUESTIONS_OVERLAPPING_DATES, + TEST_SEASON, + ), + ).toEqual(OLDEST_TEST_QUESTIONS_OVERLAPPING_DATES); + }); + + it("should get the oldest unanswered question when the list of questions is out of order", () => { + expect( + getOldestUnansweredQuestion( + TEST_QUESTIONS_MIXED_OVERLAPPING_DATES, + TEST_SEASON, + ), + ).toEqual(OLDEST_TEST_QUESTIONS_MIXED_OVERLAPPING_DATES); + }); +}); diff --git a/packages/scraper/tests/rules.test.ts b/packages/scraper/tests/rules.test.ts new file mode 100644 index 0000000..38dc1a2 --- /dev/null +++ b/packages/scraper/tests/rules.test.ts @@ -0,0 +1,12 @@ +import { describe, expect, it } from "vitest"; +import { extractRules } from "../src/modules/rules"; + +const MANUAL_URL = + "https://content.vexrobotics.com/docs/23-24/vrc-overunder/VRC-Manual-2023-24-4.0.pdf"; + +describe("extractRules", () => { + it("shall extract all the rules from the game manual", async () => { + const rules = await extractRules(MANUAL_URL); + expect(rules).not.toHaveLength(0); + }); +}); diff --git a/packages/scraper/tsconfig.json b/packages/scraper/tsconfig.json new file mode 100644 index 0000000..3579756 --- /dev/null +++ b/packages/scraper/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "@qnaplus/typescript-config/base.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist" + }, + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/packages/typescript-config/base.json b/packages/typescript-config/base.json new file mode 100644 index 0000000..3f05969 --- /dev/null +++ b/packages/typescript-config/base.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "compilerOptions": { + "lib": ["es2023"], + "target": "ES2022", + "module": "Node16", + "strict": true, + "outDir": "dist", + "resolveJsonModule": true, + "esModuleInterop": true, + "skipLibCheck": true, + "moduleResolution": "node16", + "composite": true + } +} diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json new file mode 100644 index 0000000..c9692d9 --- /dev/null +++ b/packages/typescript-config/package.json @@ -0,0 +1,7 @@ +{ + "name": "@qnaplus/typescript-config", + "version": "1.0.0", + "description": "", + "author": "battlesqui_d", + "license": "GPL-3.0" +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8d6ee21..4a311be 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,3666 +1,3766 @@ -lockfileVersion: "9.0" +lockfileVersion: '9.0' settings: - autoInstallPeers: true - excludeLinksFromLockfile: false + autoInstallPeers: true + excludeLinksFromLockfile: false + +catalogs: + default: + pino: + specifier: ^9.6.0 + version: 9.6.0 + pino-pretty: + specifier: ^11.2.2 + version: 11.3.0 importers: - .: - dependencies: - "@crawlee/core": - specifier: ^3.11.5 - version: 3.13.0 - cheerio: - specifier: ^1.0.0 - version: 1.0.0 - got-scraping: - specifier: ^4.0.6 - version: 4.1.1 - node-pdf-parser: - specifier: ^1.0.3 - version: 1.0.3 - pino: - specifier: ^9.4.0 - version: 9.6.0 - devDependencies: - "@eslint/js": - specifier: ^9.12.0 - version: 9.22.0 - eslint: - specifier: ^9.12.0 - version: 9.22.0 - pino-pretty: - specifier: ^11.2.2 - version: 11.3.0 - prettier: - specifier: ^3.3.3 - version: 3.5.3 - rimraf: - specifier: ^6.0.1 - version: 6.0.1 - typescript: - specifier: 5.5.4 - version: 5.5.4 - typescript-eslint: - specifier: ^8.9.0 - version: 8.26.1(eslint@9.22.0)(typescript@5.5.4) - vitest: - specifier: ^3.0.8 - version: 3.0.8(@types/node@22.13.10) + + .: + devDependencies: + '@biomejs/biome': + specifier: 1.9.4 + version: 1.9.4 + rimraf: + specifier: ^6.0.1 + version: 6.0.1 + syncpack: + specifier: ^13.0.2 + version: 13.0.3(typescript@5.5.4) + typescript: + specifier: 5.5.4 + version: 5.5.4 + + packages/scraper: + dependencies: + '@crawlee/core': + specifier: ^3.11.5 + version: 3.13.0 + cheerio: + specifier: ^1.0.0 + version: 1.0.0 + got-scraping: + specifier: ^4.0.6 + version: 4.1.1 + node-pdf-parser: + specifier: ^1.0.3 + version: 1.0.3 + pino: + specifier: 'catalog:' + version: 9.6.0 + devDependencies: + '@qnaplus/typescript-config': + specifier: workspace:1.0.0 + version: link:../typescript-config + pino-pretty: + specifier: 'catalog:' + version: 11.3.0 + vitest: + specifier: ^3.0.8 + version: 3.0.8(@types/node@22.13.10) + + packages/scraper-strategies: + dependencies: + '@qnaplus/node-curl-impersonate': + specifier: ^1.0.0 + version: 1.0.1 + '@qnaplus/scraper': + specifier: workspace:* + version: link:../scraper + cycletls: + specifier: ^1.0.27 + version: 1.0.27 + form-data: + specifier: ^4.0.1 + version: 4.0.2 + header-generator: + specifier: ^2.1.62 + version: 2.1.62 + pino: + specifier: 'catalog:' + version: 9.6.0 + devDependencies: + '@qnaplus/typescript-config': + specifier: workspace:1.0.0 + version: link:../typescript-config + pino-pretty: + specifier: 'catalog:' + version: 11.3.0 + + packages/typescript-config: {} packages: - "@apify/consts@2.38.0": - resolution: { integrity: sha512-pP/sNuW+6ekdBZHLBy1alyzrxzcSc4xEhVgHx8Rwoyc7Q8nAA6Oybi7ChZv3KLToPITYCpSoSmopDoqrajld0A== } - - "@apify/datastructures@2.0.2": - resolution: { integrity: sha512-IN9A0s2SCHoZZE1tf4xKgk4fxHM5/0I/UrXhWbn/rSv7E5sA2o0NyHdwcMY2Go9f5qd+E7VAbX6WnESTE6GLeA== } - - "@apify/log@2.5.14": - resolution: { integrity: sha512-s5cjADcGiqSql6szGkM3EkdiHXPo9Ea6lGiXb3Gew2XxQKYMrOpX9ZEEIeQfQPW5nhKcUwxREkptfEsxES3MDQ== } - - "@apify/ps-tree@1.2.0": - resolution: { integrity: sha512-VHIswI7rD/R4bToeIDuJ9WJXt+qr5SdhfoZ9RzdjmCs9mgy7l0P4RugQEUCcU+WB4sfImbd4CKwzXcn0uYx1yw== } - engines: { node: ">= 0.10" } - hasBin: true - - "@apify/pseudo_url@2.0.55": - resolution: { integrity: sha512-E3vubybRuCC1paw4DTPgAgpG9yoEK0WyUeYfj51Ef2eBHG6soM986WikNbDCUACrjub3EFBVztZepbzTc18oNQ== } - - "@apify/timeout@0.3.1": - resolution: { integrity: sha512-sLIuOqfySki/7AXiQ1yZoCI07vX6aYFLgP6YaJ8e8YLn8CFsRERma/Crxcz0zyCaxhc7C7EPgcs1O+p/djZchw== } - - "@apify/utilities@2.15.1": - resolution: { integrity: sha512-QY1pK2c1fDxmPmvZy33y4JOsNGmqhVKl+Cf0bzamhUCq5EECTPZoAvwUtg91/nCqCt/LrgTJoeiK8Ia+9J9tkA== } - - "@crawlee/core@3.13.0": - resolution: { integrity: sha512-oDP1tumieNPcKORQfTtolVP6fkOQovTKT4LISAJ/P02iu4bBBfWMxno4uJncskgw6eMUW5xUAhAdPJi52qa6uQ== } - engines: { node: ">=16.0.0" } - - "@crawlee/memory-storage@3.13.0": - resolution: { integrity: sha512-WC+zG2yucSL7lstrijwzm/ZkX0f/iN42x79wDkTG11ZOEGJyCFR3dmPGuNiyhK2fdGIZapLJiUolJnGOAsNtxg== } - engines: { node: ">= 16" } - - "@crawlee/types@3.13.0": - resolution: { integrity: sha512-CdUecVRN2TkqwmVqJ+DiiKBj/jBBlUzsIaCZYDaRwAYEZmzVmWQ7GkcQju6YYbqtRTS+3HLyxW4bgTZdRQW98g== } - engines: { node: ">=16.0.0" } - - "@crawlee/utils@3.13.0": - resolution: { integrity: sha512-hiL+VrJ7jrExwuMHVm28EvfloonrZshhzIaV3MnocURM9B/ByILdEjuYr2bb+lRlsuk3czuhkprYbE+AsEXT9A== } - engines: { node: ">=16.0.0" } - - "@esbuild/aix-ppc64@0.25.1": - resolution: { integrity: sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ== } - engines: { node: ">=18" } - cpu: [ppc64] - os: [aix] - - "@esbuild/android-arm64@0.25.1": - resolution: { integrity: sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA== } - engines: { node: ">=18" } - cpu: [arm64] - os: [android] - - "@esbuild/android-arm@0.25.1": - resolution: { integrity: sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q== } - engines: { node: ">=18" } - cpu: [arm] - os: [android] - - "@esbuild/android-x64@0.25.1": - resolution: { integrity: sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw== } - engines: { node: ">=18" } - cpu: [x64] - os: [android] - - "@esbuild/darwin-arm64@0.25.1": - resolution: { integrity: sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ== } - engines: { node: ">=18" } - cpu: [arm64] - os: [darwin] - - "@esbuild/darwin-x64@0.25.1": - resolution: { integrity: sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA== } - engines: { node: ">=18" } - cpu: [x64] - os: [darwin] - - "@esbuild/freebsd-arm64@0.25.1": - resolution: { integrity: sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A== } - engines: { node: ">=18" } - cpu: [arm64] - os: [freebsd] - - "@esbuild/freebsd-x64@0.25.1": - resolution: { integrity: sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww== } - engines: { node: ">=18" } - cpu: [x64] - os: [freebsd] - - "@esbuild/linux-arm64@0.25.1": - resolution: { integrity: sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ== } - engines: { node: ">=18" } - cpu: [arm64] - os: [linux] - - "@esbuild/linux-arm@0.25.1": - resolution: { integrity: sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ== } - engines: { node: ">=18" } - cpu: [arm] - os: [linux] - - "@esbuild/linux-ia32@0.25.1": - resolution: { integrity: sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ== } - engines: { node: ">=18" } - cpu: [ia32] - os: [linux] - - "@esbuild/linux-loong64@0.25.1": - resolution: { integrity: sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg== } - engines: { node: ">=18" } - cpu: [loong64] - os: [linux] - - "@esbuild/linux-mips64el@0.25.1": - resolution: { integrity: sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg== } - engines: { node: ">=18" } - cpu: [mips64el] - os: [linux] - - "@esbuild/linux-ppc64@0.25.1": - resolution: { integrity: sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg== } - engines: { node: ">=18" } - cpu: [ppc64] - os: [linux] - - "@esbuild/linux-riscv64@0.25.1": - resolution: { integrity: sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ== } - engines: { node: ">=18" } - cpu: [riscv64] - os: [linux] - - "@esbuild/linux-s390x@0.25.1": - resolution: { integrity: sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ== } - engines: { node: ">=18" } - cpu: [s390x] - os: [linux] - - "@esbuild/linux-x64@0.25.1": - resolution: { integrity: sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA== } - engines: { node: ">=18" } - cpu: [x64] - os: [linux] - - "@esbuild/netbsd-arm64@0.25.1": - resolution: { integrity: sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g== } - engines: { node: ">=18" } - cpu: [arm64] - os: [netbsd] - - "@esbuild/netbsd-x64@0.25.1": - resolution: { integrity: sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA== } - engines: { node: ">=18" } - cpu: [x64] - os: [netbsd] - - "@esbuild/openbsd-arm64@0.25.1": - resolution: { integrity: sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg== } - engines: { node: ">=18" } - cpu: [arm64] - os: [openbsd] - - "@esbuild/openbsd-x64@0.25.1": - resolution: { integrity: sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw== } - engines: { node: ">=18" } - cpu: [x64] - os: [openbsd] - - "@esbuild/sunos-x64@0.25.1": - resolution: { integrity: sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg== } - engines: { node: ">=18" } - cpu: [x64] - os: [sunos] - - "@esbuild/win32-arm64@0.25.1": - resolution: { integrity: sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ== } - engines: { node: ">=18" } - cpu: [arm64] - os: [win32] - - "@esbuild/win32-ia32@0.25.1": - resolution: { integrity: sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A== } - engines: { node: ">=18" } - cpu: [ia32] - os: [win32] - - "@esbuild/win32-x64@0.25.1": - resolution: { integrity: sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg== } - engines: { node: ">=18" } - cpu: [x64] - os: [win32] - - "@eslint-community/eslint-utils@4.5.0": - resolution: { integrity: sha512-RoV8Xs9eNwiDvhv7M+xcL4PWyRyIXRY/FLp3buU4h1EYfdF7unWUy3dOjPqb3C7rMUewIcqwW850PgS8h1o1yg== } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - - "@eslint-community/regexpp@4.12.1": - resolution: { integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== } - engines: { node: ^12.0.0 || ^14.0.0 || >=16.0.0 } - - "@eslint/config-array@0.19.2": - resolution: { integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@eslint/config-helpers@0.1.0": - resolution: { integrity: sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@eslint/core@0.12.0": - resolution: { integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@eslint/eslintrc@3.3.0": - resolution: { integrity: sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@eslint/js@9.22.0": - resolution: { integrity: sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@eslint/object-schema@2.1.6": - resolution: { integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@eslint/plugin-kit@0.2.7": - resolution: { integrity: sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@humanfs/core@0.19.1": - resolution: { integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== } - engines: { node: ">=18.18.0" } - - "@humanfs/node@0.16.6": - resolution: { integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw== } - engines: { node: ">=18.18.0" } - - "@humanwhocodes/module-importer@1.0.1": - resolution: { integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== } - engines: { node: ">=12.22" } - - "@humanwhocodes/retry@0.3.1": - resolution: { integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== } - engines: { node: ">=18.18" } - - "@humanwhocodes/retry@0.4.2": - resolution: { integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ== } - engines: { node: ">=18.18" } - - "@isaacs/cliui@8.0.2": - resolution: { integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== } - engines: { node: ">=12" } - - "@jridgewell/sourcemap-codec@1.5.0": - resolution: { integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== } - - "@mapbox/node-pre-gyp@1.0.11": - resolution: { integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ== } - hasBin: true - - "@nodelib/fs.scandir@2.1.5": - resolution: { integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== } - engines: { node: ">= 8" } - - "@nodelib/fs.stat@2.0.5": - resolution: { integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== } - engines: { node: ">= 8" } - - "@nodelib/fs.walk@1.2.8": - resolution: { integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== } - engines: { node: ">= 8" } - - "@rollup/rollup-android-arm-eabi@4.35.0": - resolution: { integrity: sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ== } - cpu: [arm] - os: [android] - - "@rollup/rollup-android-arm64@4.35.0": - resolution: { integrity: sha512-FtKddj9XZudurLhdJnBl9fl6BwCJ3ky8riCXjEw3/UIbjmIY58ppWwPEvU3fNu+W7FUsAsB1CdH+7EQE6CXAPA== } - cpu: [arm64] - os: [android] - - "@rollup/rollup-darwin-arm64@4.35.0": - resolution: { integrity: sha512-Uk+GjOJR6CY844/q6r5DR/6lkPFOw0hjfOIzVx22THJXMxktXG6CbejseJFznU8vHcEBLpiXKY3/6xc+cBm65Q== } - cpu: [arm64] - os: [darwin] - - "@rollup/rollup-darwin-x64@4.35.0": - resolution: { integrity: sha512-3IrHjfAS6Vkp+5bISNQnPogRAW5GAV1n+bNCrDwXmfMHbPl5EhTmWtfmwlJxFRUCBZ+tZ/OxDyU08aF6NI/N5Q== } - cpu: [x64] - os: [darwin] - - "@rollup/rollup-freebsd-arm64@4.35.0": - resolution: { integrity: sha512-sxjoD/6F9cDLSELuLNnY0fOrM9WA0KrM0vWm57XhrIMf5FGiN8D0l7fn+bpUeBSU7dCgPV2oX4zHAsAXyHFGcQ== } - cpu: [arm64] - os: [freebsd] - - "@rollup/rollup-freebsd-x64@4.35.0": - resolution: { integrity: sha512-2mpHCeRuD1u/2kruUiHSsnjWtHjqVbzhBkNVQ1aVD63CcexKVcQGwJ2g5VphOd84GvxfSvnnlEyBtQCE5hxVVw== } - cpu: [x64] - os: [freebsd] - - "@rollup/rollup-linux-arm-gnueabihf@4.35.0": - resolution: { integrity: sha512-mrA0v3QMy6ZSvEuLs0dMxcO2LnaCONs1Z73GUDBHWbY8tFFocM6yl7YyMu7rz4zS81NDSqhrUuolyZXGi8TEqg== } - cpu: [arm] - os: [linux] - - "@rollup/rollup-linux-arm-musleabihf@4.35.0": - resolution: { integrity: sha512-DnYhhzcvTAKNexIql8pFajr0PiDGrIsBYPRvCKlA5ixSS3uwo/CWNZxB09jhIapEIg945KOzcYEAGGSmTSpk7A== } - cpu: [arm] - os: [linux] - - "@rollup/rollup-linux-arm64-gnu@4.35.0": - resolution: { integrity: sha512-uagpnH2M2g2b5iLsCTZ35CL1FgyuzzJQ8L9VtlJ+FckBXroTwNOaD0z0/UF+k5K3aNQjbm8LIVpxykUOQt1m/A== } - cpu: [arm64] - os: [linux] - - "@rollup/rollup-linux-arm64-musl@4.35.0": - resolution: { integrity: sha512-XQxVOCd6VJeHQA/7YcqyV0/88N6ysSVzRjJ9I9UA/xXpEsjvAgDTgH3wQYz5bmr7SPtVK2TsP2fQ2N9L4ukoUg== } - cpu: [arm64] - os: [linux] - - "@rollup/rollup-linux-loongarch64-gnu@4.35.0": - resolution: { integrity: sha512-5pMT5PzfgwcXEwOaSrqVsz/LvjDZt+vQ8RT/70yhPU06PTuq8WaHhfT1LW+cdD7mW6i/J5/XIkX/1tCAkh1W6g== } - cpu: [loong64] - os: [linux] - - "@rollup/rollup-linux-powerpc64le-gnu@4.35.0": - resolution: { integrity: sha512-c+zkcvbhbXF98f4CtEIP1EBA/lCic5xB0lToneZYvMeKu5Kamq3O8gqrxiYYLzlZH6E3Aq+TSW86E4ay8iD8EA== } - cpu: [ppc64] - os: [linux] - - "@rollup/rollup-linux-riscv64-gnu@4.35.0": - resolution: { integrity: sha512-s91fuAHdOwH/Tad2tzTtPX7UZyytHIRR6V4+2IGlV0Cej5rkG0R61SX4l4y9sh0JBibMiploZx3oHKPnQBKe4g== } - cpu: [riscv64] - os: [linux] - - "@rollup/rollup-linux-s390x-gnu@4.35.0": - resolution: { integrity: sha512-hQRkPQPLYJZYGP+Hj4fR9dDBMIM7zrzJDWFEMPdTnTy95Ljnv0/4w/ixFw3pTBMEuuEuoqtBINYND4M7ujcuQw== } - cpu: [s390x] - os: [linux] - - "@rollup/rollup-linux-x64-gnu@4.35.0": - resolution: { integrity: sha512-Pim1T8rXOri+0HmV4CdKSGrqcBWX0d1HoPnQ0uw0bdp1aP5SdQVNBy8LjYncvnLgu3fnnCt17xjWGd4cqh8/hA== } - cpu: [x64] - os: [linux] - - "@rollup/rollup-linux-x64-musl@4.35.0": - resolution: { integrity: sha512-QysqXzYiDvQWfUiTm8XmJNO2zm9yC9P/2Gkrwg2dH9cxotQzunBHYr6jk4SujCTqnfGxduOmQcI7c2ryuW8XVg== } - cpu: [x64] - os: [linux] - - "@rollup/rollup-win32-arm64-msvc@4.35.0": - resolution: { integrity: sha512-OUOlGqPkVJCdJETKOCEf1mw848ZyJ5w50/rZ/3IBQVdLfR5jk/6Sr5m3iO2tdPgwo0x7VcncYuOvMhBWZq8ayg== } - cpu: [arm64] - os: [win32] - - "@rollup/rollup-win32-ia32-msvc@4.35.0": - resolution: { integrity: sha512-2/lsgejMrtwQe44glq7AFFHLfJBPafpsTa6JvP2NGef/ifOa4KBoglVf7AKN7EV9o32evBPRqfg96fEHzWo5kw== } - cpu: [ia32] - os: [win32] - - "@rollup/rollup-win32-x64-msvc@4.35.0": - resolution: { integrity: sha512-PIQeY5XDkrOysbQblSW7v3l1MDZzkTEzAfTPkj5VAu3FW8fS4ynyLg2sINp0fp3SjZ8xkRYpLqoKcYqAkhU1dw== } - cpu: [x64] - os: [win32] - - "@sapphire/async-queue@1.5.5": - resolution: { integrity: sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg== } - engines: { node: ">=v14.0.0", npm: ">=7.0.0" } - - "@sapphire/shapeshift@3.9.7": - resolution: { integrity: sha512-4It2mxPSr4OGn4HSQWGmhFMsNFGfFVhWeRPCRwbH972Ek2pzfGRZtb0pJ4Ze6oIzcyh2jw7nUDa6qGlWofgd9g== } - engines: { node: ">=v16" } - - "@sec-ant/readable-stream@0.4.1": - resolution: { integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg== } - - "@sindresorhus/is@4.6.0": - resolution: { integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== } - engines: { node: ">=10" } - - "@sindresorhus/is@5.6.0": - resolution: { integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g== } - engines: { node: ">=14.16" } - - "@sindresorhus/is@7.0.1": - resolution: { integrity: sha512-QWLl2P+rsCJeofkDNIT3WFmb6NrRud1SUYW8dIhXK/46XFV8Q/g7Bsvib0Askb0reRLe+WYPeeE+l5cH7SlkuQ== } - engines: { node: ">=18" } - - "@szmarczak/http-timer@5.0.1": - resolution: { integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw== } - engines: { node: ">=14.16" } - - "@tokenizer/inflate@0.2.7": - resolution: { integrity: sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg== } - engines: { node: ">=18" } - - "@tokenizer/token@0.3.0": - resolution: { integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A== } - - "@types/estree@1.0.6": - resolution: { integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== } - - "@types/http-cache-semantics@4.0.4": - resolution: { integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA== } - - "@types/json-schema@7.0.15": - resolution: { integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== } - - "@types/node@22.13.10": - resolution: { integrity: sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw== } - - "@types/sax@1.2.7": - resolution: { integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A== } - - "@typescript-eslint/eslint-plugin@8.26.1": - resolution: { integrity: sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - peerDependencies: - "@typescript-eslint/parser": ^8.0.0 || ^8.0.0-alpha.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - - "@typescript-eslint/parser@8.26.1": - resolution: { integrity: sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - - "@typescript-eslint/scope-manager@8.26.1": - resolution: { integrity: sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@typescript-eslint/type-utils@8.26.1": - resolution: { integrity: sha512-Kcj/TagJLwoY/5w9JGEFV0dclQdyqw9+VMndxOJKtoFSjfZhLXhYjzsQEeyza03rwHx2vFEGvrJWJBXKleRvZg== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - - "@typescript-eslint/types@8.26.1": - resolution: { integrity: sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@typescript-eslint/typescript-estree@8.26.1": - resolution: { integrity: sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - peerDependencies: - typescript: ">=4.8.4 <5.9.0" - - "@typescript-eslint/utils@8.26.1": - resolution: { integrity: sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - - "@typescript-eslint/visitor-keys@8.26.1": - resolution: { integrity: sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@vitest/expect@3.0.8": - resolution: { integrity: sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ== } - - "@vitest/mocker@3.0.8": - resolution: { integrity: sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow== } - peerDependencies: - msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 - peerDependenciesMeta: - msw: - optional: true - vite: - optional: true - - "@vitest/pretty-format@3.0.8": - resolution: { integrity: sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg== } - - "@vitest/runner@3.0.8": - resolution: { integrity: sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w== } - - "@vitest/snapshot@3.0.8": - resolution: { integrity: sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A== } - - "@vitest/spy@3.0.8": - resolution: { integrity: sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q== } - - "@vitest/utils@3.0.8": - resolution: { integrity: sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q== } - - "@vladfrangu/async_event_emitter@2.4.6": - resolution: { integrity: sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA== } - engines: { node: ">=v14.0.0", npm: ">=7.0.0" } - - abbrev@1.1.1: - resolution: { integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== } - - abort-controller@3.0.0: - resolution: { integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== } - engines: { node: ">=6.5" } - - acorn-jsx@5.3.2: - resolution: { integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== } - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn@8.14.1: - resolution: { integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== } - engines: { node: ">=0.4.0" } - hasBin: true - - adm-zip@0.5.16: - resolution: { integrity: sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ== } - engines: { node: ">=12.0" } - - agent-base@6.0.2: - resolution: { integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== } - engines: { node: ">= 6.0.0" } - - ajv@6.12.6: - resolution: { integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== } - - ansi-colors@4.1.3: - resolution: { integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== } - engines: { node: ">=6" } - - ansi-regex@5.0.1: - resolution: { integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== } - engines: { node: ">=8" } - ansi-regex@6.1.0: - resolution: { integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== } - engines: { node: ">=12" } + '@apify/consts@2.38.0': + resolution: {integrity: sha512-pP/sNuW+6ekdBZHLBy1alyzrxzcSc4xEhVgHx8Rwoyc7Q8nAA6Oybi7ChZv3KLToPITYCpSoSmopDoqrajld0A==} + + '@apify/datastructures@2.0.2': + resolution: {integrity: sha512-IN9A0s2SCHoZZE1tf4xKgk4fxHM5/0I/UrXhWbn/rSv7E5sA2o0NyHdwcMY2Go9f5qd+E7VAbX6WnESTE6GLeA==} + + '@apify/log@2.5.14': + resolution: {integrity: sha512-s5cjADcGiqSql6szGkM3EkdiHXPo9Ea6lGiXb3Gew2XxQKYMrOpX9ZEEIeQfQPW5nhKcUwxREkptfEsxES3MDQ==} + + '@apify/ps-tree@1.2.0': + resolution: {integrity: sha512-VHIswI7rD/R4bToeIDuJ9WJXt+qr5SdhfoZ9RzdjmCs9mgy7l0P4RugQEUCcU+WB4sfImbd4CKwzXcn0uYx1yw==} + engines: {node: '>= 0.10'} + hasBin: true + + '@apify/pseudo_url@2.0.55': + resolution: {integrity: sha512-E3vubybRuCC1paw4DTPgAgpG9yoEK0WyUeYfj51Ef2eBHG6soM986WikNbDCUACrjub3EFBVztZepbzTc18oNQ==} + + '@apify/timeout@0.3.1': + resolution: {integrity: sha512-sLIuOqfySki/7AXiQ1yZoCI07vX6aYFLgP6YaJ8e8YLn8CFsRERma/Crxcz0zyCaxhc7C7EPgcs1O+p/djZchw==} + + '@apify/utilities@2.15.1': + resolution: {integrity: sha512-QY1pK2c1fDxmPmvZy33y4JOsNGmqhVKl+Cf0bzamhUCq5EECTPZoAvwUtg91/nCqCt/LrgTJoeiK8Ia+9J9tkA==} + + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + + '@biomejs/biome@1.9.4': + resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==} + engines: {node: '>=14.21.3'} + hasBin: true + + '@biomejs/cli-darwin-arm64@1.9.4': + resolution: {integrity: sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [darwin] + + '@biomejs/cli-darwin-x64@1.9.4': + resolution: {integrity: sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [darwin] + + '@biomejs/cli-linux-arm64-musl@1.9.4': + resolution: {integrity: sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + + '@biomejs/cli-linux-arm64@1.9.4': + resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + + '@biomejs/cli-linux-x64-musl@1.9.4': + resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + + '@biomejs/cli-linux-x64@1.9.4': + resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + + '@biomejs/cli-win32-arm64@1.9.4': + resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [win32] + + '@biomejs/cli-win32-x64@1.9.4': + resolution: {integrity: sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [win32] + + '@crawlee/core@3.13.0': + resolution: {integrity: sha512-oDP1tumieNPcKORQfTtolVP6fkOQovTKT4LISAJ/P02iu4bBBfWMxno4uJncskgw6eMUW5xUAhAdPJi52qa6uQ==} + engines: {node: '>=16.0.0'} + + '@crawlee/memory-storage@3.13.0': + resolution: {integrity: sha512-WC+zG2yucSL7lstrijwzm/ZkX0f/iN42x79wDkTG11ZOEGJyCFR3dmPGuNiyhK2fdGIZapLJiUolJnGOAsNtxg==} + engines: {node: '>= 16'} + + '@crawlee/types@3.13.0': + resolution: {integrity: sha512-CdUecVRN2TkqwmVqJ+DiiKBj/jBBlUzsIaCZYDaRwAYEZmzVmWQ7GkcQju6YYbqtRTS+3HLyxW4bgTZdRQW98g==} + engines: {node: '>=16.0.0'} + + '@crawlee/utils@3.13.0': + resolution: {integrity: sha512-hiL+VrJ7jrExwuMHVm28EvfloonrZshhzIaV3MnocURM9B/ByILdEjuYr2bb+lRlsuk3czuhkprYbE+AsEXT9A==} + engines: {node: '>=16.0.0'} + + '@effect/schema@0.75.5': + resolution: {integrity: sha512-TQInulTVCuF+9EIbJpyLP6dvxbQJMphrnRqgexm/Ze39rSjfhJuufF7XvU3SxTgg3HnL7B/kpORTJbHhlE6thw==} + deprecated: this package has been merged into the main effect package + peerDependencies: + effect: ^3.9.2 + + '@esbuild/aix-ppc64@0.25.1': + resolution: {integrity: sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.1': + resolution: {integrity: sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.1': + resolution: {integrity: sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.1': + resolution: {integrity: sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.1': + resolution: {integrity: sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.1': + resolution: {integrity: sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.1': + resolution: {integrity: sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.1': + resolution: {integrity: sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.1': + resolution: {integrity: sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.1': + resolution: {integrity: sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.1': + resolution: {integrity: sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.1': + resolution: {integrity: sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.1': + resolution: {integrity: sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.1': + resolution: {integrity: sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.1': + resolution: {integrity: sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.1': + resolution: {integrity: sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.1': + resolution: {integrity: sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.1': + resolution: {integrity: sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.1': + resolution: {integrity: sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.1': + resolution: {integrity: sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.1': + resolution: {integrity: sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.25.1': + resolution: {integrity: sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.1': + resolution: {integrity: sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.1': + resolution: {integrity: sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.1': + resolution: {integrity: sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@mapbox/node-pre-gyp@1.0.11': + resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} + hasBin: true + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@qnaplus/node-curl-impersonate@1.0.1': + resolution: {integrity: sha512-nAX3/EpTAYpx4IyNJ+GAYhSENd6n/JRQBOG2LuTK3uz/0bYZjRC/J7vQMPpXQ00VumkjCUriMFpNbJw+f47pFQ==} + + '@rollup/rollup-android-arm-eabi@4.35.0': + resolution: {integrity: sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.35.0': + resolution: {integrity: sha512-FtKddj9XZudurLhdJnBl9fl6BwCJ3ky8riCXjEw3/UIbjmIY58ppWwPEvU3fNu+W7FUsAsB1CdH+7EQE6CXAPA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.35.0': + resolution: {integrity: sha512-Uk+GjOJR6CY844/q6r5DR/6lkPFOw0hjfOIzVx22THJXMxktXG6CbejseJFznU8vHcEBLpiXKY3/6xc+cBm65Q==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.35.0': + resolution: {integrity: sha512-3IrHjfAS6Vkp+5bISNQnPogRAW5GAV1n+bNCrDwXmfMHbPl5EhTmWtfmwlJxFRUCBZ+tZ/OxDyU08aF6NI/N5Q==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.35.0': + resolution: {integrity: sha512-sxjoD/6F9cDLSELuLNnY0fOrM9WA0KrM0vWm57XhrIMf5FGiN8D0l7fn+bpUeBSU7dCgPV2oX4zHAsAXyHFGcQ==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.35.0': + resolution: {integrity: sha512-2mpHCeRuD1u/2kruUiHSsnjWtHjqVbzhBkNVQ1aVD63CcexKVcQGwJ2g5VphOd84GvxfSvnnlEyBtQCE5hxVVw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.35.0': + resolution: {integrity: sha512-mrA0v3QMy6ZSvEuLs0dMxcO2LnaCONs1Z73GUDBHWbY8tFFocM6yl7YyMu7rz4zS81NDSqhrUuolyZXGi8TEqg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.35.0': + resolution: {integrity: sha512-DnYhhzcvTAKNexIql8pFajr0PiDGrIsBYPRvCKlA5ixSS3uwo/CWNZxB09jhIapEIg945KOzcYEAGGSmTSpk7A==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.35.0': + resolution: {integrity: sha512-uagpnH2M2g2b5iLsCTZ35CL1FgyuzzJQ8L9VtlJ+FckBXroTwNOaD0z0/UF+k5K3aNQjbm8LIVpxykUOQt1m/A==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.35.0': + resolution: {integrity: sha512-XQxVOCd6VJeHQA/7YcqyV0/88N6ysSVzRjJ9I9UA/xXpEsjvAgDTgH3wQYz5bmr7SPtVK2TsP2fQ2N9L4ukoUg==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.35.0': + resolution: {integrity: sha512-5pMT5PzfgwcXEwOaSrqVsz/LvjDZt+vQ8RT/70yhPU06PTuq8WaHhfT1LW+cdD7mW6i/J5/XIkX/1tCAkh1W6g==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.35.0': + resolution: {integrity: sha512-c+zkcvbhbXF98f4CtEIP1EBA/lCic5xB0lToneZYvMeKu5Kamq3O8gqrxiYYLzlZH6E3Aq+TSW86E4ay8iD8EA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.35.0': + resolution: {integrity: sha512-s91fuAHdOwH/Tad2tzTtPX7UZyytHIRR6V4+2IGlV0Cej5rkG0R61SX4l4y9sh0JBibMiploZx3oHKPnQBKe4g==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.35.0': + resolution: {integrity: sha512-hQRkPQPLYJZYGP+Hj4fR9dDBMIM7zrzJDWFEMPdTnTy95Ljnv0/4w/ixFw3pTBMEuuEuoqtBINYND4M7ujcuQw==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.35.0': + resolution: {integrity: sha512-Pim1T8rXOri+0HmV4CdKSGrqcBWX0d1HoPnQ0uw0bdp1aP5SdQVNBy8LjYncvnLgu3fnnCt17xjWGd4cqh8/hA==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.35.0': + resolution: {integrity: sha512-QysqXzYiDvQWfUiTm8XmJNO2zm9yC9P/2Gkrwg2dH9cxotQzunBHYr6jk4SujCTqnfGxduOmQcI7c2ryuW8XVg==} + cpu: [x64] + os: [linux] - ansi-styles@4.3.0: - resolution: { integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== } - engines: { node: ">=8" } + '@rollup/rollup-win32-arm64-msvc@4.35.0': + resolution: {integrity: sha512-OUOlGqPkVJCdJETKOCEf1mw848ZyJ5w50/rZ/3IBQVdLfR5jk/6Sr5m3iO2tdPgwo0x7VcncYuOvMhBWZq8ayg==} + cpu: [arm64] + os: [win32] - ansi-styles@6.2.1: - resolution: { integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== } - engines: { node: ">=12" } + '@rollup/rollup-win32-ia32-msvc@4.35.0': + resolution: {integrity: sha512-2/lsgejMrtwQe44glq7AFFHLfJBPafpsTa6JvP2NGef/ifOa4KBoglVf7AKN7EV9o32evBPRqfg96fEHzWo5kw==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.35.0': + resolution: {integrity: sha512-PIQeY5XDkrOysbQblSW7v3l1MDZzkTEzAfTPkj5VAu3FW8fS4ynyLg2sINp0fp3SjZ8xkRYpLqoKcYqAkhU1dw==} + cpu: [x64] + os: [win32] - aproba@2.0.0: - resolution: { integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== } + '@sapphire/async-queue@1.5.5': + resolution: {integrity: sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} - are-we-there-yet@2.0.0: - resolution: { integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== } - engines: { node: ">=10" } - deprecated: This package is no longer supported. + '@sapphire/shapeshift@3.9.7': + resolution: {integrity: sha512-4It2mxPSr4OGn4HSQWGmhFMsNFGfFVhWeRPCRwbH972Ek2pzfGRZtb0pJ4Ze6oIzcyh2jw7nUDa6qGlWofgd9g==} + engines: {node: '>=v16'} - argparse@2.0.1: - resolution: { integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== } + '@sec-ant/readable-stream@0.4.1': + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + + '@sindresorhus/is@4.6.0': + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} + engines: {node: '>=10'} - assertion-error@2.0.1: - resolution: { integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== } - engines: { node: ">=12" } + '@sindresorhus/is@5.6.0': + resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} + engines: {node: '>=14.16'} - atomic-sleep@1.0.0: - resolution: { integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== } - engines: { node: ">=8.0.0" } + '@sindresorhus/is@7.0.1': + resolution: {integrity: sha512-QWLl2P+rsCJeofkDNIT3WFmb6NrRud1SUYW8dIhXK/46XFV8Q/g7Bsvib0Askb0reRLe+WYPeeE+l5cH7SlkuQ==} + engines: {node: '>=18'} - balanced-match@1.0.2: - resolution: { integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== } + '@sindresorhus/merge-streams@2.3.0': + resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} + engines: {node: '>=18'} - base64-js@1.5.1: - resolution: { integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== } + '@standard-schema/spec@1.0.0': + resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} - boolbase@1.0.0: - resolution: { integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== } + '@szmarczak/http-timer@5.0.1': + resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} + engines: {node: '>=14.16'} - brace-expansion@1.1.11: - resolution: { integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== } + '@tokenizer/inflate@0.2.7': + resolution: {integrity: sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==} + engines: {node: '>=18'} - brace-expansion@2.0.1: - resolution: { integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== } + '@tokenizer/token@0.3.0': + resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} - braces@3.0.3: - resolution: { integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== } - engines: { node: ">=8" } + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - browserslist@4.24.4: - resolution: { integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== } - engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } - hasBin: true + '@types/http-cache-semantics@4.0.4': + resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} - buffer@6.0.3: - resolution: { integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== } + '@types/node@20.17.27': + resolution: {integrity: sha512-U58sbKhDrthHlxHRJw7ZLiLDZGmAUOZUbpw0S6nL27sYUdhvgBLCRu/keSd6qcTsfArd1sRFCCBxzWATGr/0UA==} - cac@6.7.14: - resolution: { integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== } - engines: { node: ">=8" } + '@types/node@22.13.10': + resolution: {integrity: sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==} - cacheable-lookup@7.0.0: - resolution: { integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w== } - engines: { node: ">=14.16" } + '@types/sax@1.2.7': + resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} - cacheable-request@12.0.1: - resolution: { integrity: sha512-Yo9wGIQUaAfIbk+qY0X4cDQgCosecfBe3V9NSyeY4qPC2SAkbCS4Xj79VP8WOzitpJUZKc/wsRCYF5ariDIwkg== } - engines: { node: ">=18" } + '@vitest/expect@3.0.8': + resolution: {integrity: sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ==} - callsites@3.1.0: - resolution: { integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== } - engines: { node: ">=6" } + '@vitest/mocker@3.0.8': + resolution: {integrity: sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true - callsites@4.2.0: - resolution: { integrity: sha512-kfzR4zzQtAE9PC7CzZsjl3aBNbXWuXiSeOCdLcPpBfGW8YuCqQHcRPFDbr/BPVmd3EEPVpuFzLyuT/cUhPr4OQ== } - engines: { node: ">=12.20" } + '@vitest/pretty-format@3.0.8': + resolution: {integrity: sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg==} - caniuse-lite@1.0.30001703: - resolution: { integrity: sha512-kRlAGTRWgPsOj7oARC9m1okJEXdL/8fekFVcxA8Hl7GH4r/sN4OJn/i6Flde373T50KS7Y37oFbMwlE8+F42kQ== } + '@vitest/runner@3.0.8': + resolution: {integrity: sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w==} - canvas@2.11.2: - resolution: { integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw== } - engines: { node: ">=6" } + '@vitest/snapshot@3.0.8': + resolution: {integrity: sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A==} - chai@5.2.0: - resolution: { integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw== } - engines: { node: ">=12" } + '@vitest/spy@3.0.8': + resolution: {integrity: sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==} - chalk@4.1.2: - resolution: { integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== } - engines: { node: ">=10" } + '@vitest/utils@3.0.8': + resolution: {integrity: sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q==} - check-error@2.1.1: - resolution: { integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== } - engines: { node: ">= 16" } + '@vladfrangu/async_event_emitter@2.4.6': + resolution: {integrity: sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} - cheerio-select@2.1.0: - resolution: { integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== } + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - cheerio@1.0.0: - resolution: { integrity: sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww== } - engines: { node: ">=18.17" } + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} - cheerio@1.0.0-rc.12: - resolution: { integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== } - engines: { node: ">= 6" } + adm-zip@0.5.16: + resolution: {integrity: sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==} + engines: {node: '>=12.0'} - chownr@2.0.0: - resolution: { integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== } - engines: { node: ">=10" } + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} - color-convert@2.0.1: - resolution: { integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== } - engines: { node: ">=7.0.0" } + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} - color-name@1.1.4: - resolution: { integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== } + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} - color-support@1.1.3: - resolution: { integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== } - hasBin: true + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} - colorette@2.0.20: - resolution: { integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== } + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} - concat-map@0.0.1: - resolution: { integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== } + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} - console-control-strings@1.1.0: - resolution: { integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== } + aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - content-type@1.0.5: - resolution: { integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== } - engines: { node: ">= 0.6" } + are-we-there-yet@2.0.0: + resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} + engines: {node: '>=10'} + deprecated: This package is no longer supported. - cross-spawn@7.0.6: - resolution: { integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== } - engines: { node: ">= 8" } + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - css-select@5.1.0: - resolution: { integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== } + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} - css-what@6.1.0: - resolution: { integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== } - engines: { node: ">= 6" } + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - csv-stringify@6.5.2: - resolution: { integrity: sha512-RFPahj0sXcmUyjrObAK+DOWtMvMIFV328n4qZJhgX3x2RqkQgOTU2mCUmiFR0CzM6AzChlRSUErjiJeEt8BaQA== } + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} - dateformat@4.6.3: - resolution: { integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== } + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - debug@4.4.0: - resolution: { integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== } - engines: { node: ">=6.0" } - peerDependencies: - supports-color: "*" - peerDependenciesMeta: - supports-color: - optional: true + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - decompress-response@4.2.1: - resolution: { integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== } - engines: { node: ">=8" } + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - decompress-response@6.0.0: - resolution: { integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== } - engines: { node: ">=10" } + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - deep-eql@5.0.2: - resolution: { integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== } - engines: { node: ">=6" } + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - deep-is@0.1.4: - resolution: { integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== } + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} - defer-to-connect@2.0.1: - resolution: { integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== } - engines: { node: ">=10" } + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true - delegates@1.0.0: - resolution: { integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== } + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - detect-libc@2.0.3: - resolution: { integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== } - engines: { node: ">=8" } + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} - dom-serializer@2.0.0: - resolution: { integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== } + cacheable-lookup@7.0.0: + resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} + engines: {node: '>=14.16'} - domelementtype@2.3.0: - resolution: { integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== } + cacheable-request@12.0.1: + resolution: {integrity: sha512-Yo9wGIQUaAfIbk+qY0X4cDQgCosecfBe3V9NSyeY4qPC2SAkbCS4Xj79VP8WOzitpJUZKc/wsRCYF5ariDIwkg==} + engines: {node: '>=18'} - domhandler@5.0.3: - resolution: { integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== } - engines: { node: ">= 4" } + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} - domutils@3.2.2: - resolution: { integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw== } + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} - dot-prop@6.0.1: - resolution: { integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA== } - engines: { node: ">=10" } + callsites@4.2.0: + resolution: {integrity: sha512-kfzR4zzQtAE9PC7CzZsjl3aBNbXWuXiSeOCdLcPpBfGW8YuCqQHcRPFDbr/BPVmd3EEPVpuFzLyuT/cUhPr4OQ==} + engines: {node: '>=12.20'} - dot-prop@7.2.0: - resolution: { integrity: sha512-Ol/IPXUARn9CSbkrdV4VJo7uCy1I3VuSiWCaFSg+8BdUOzF9n3jefIpcgAydvUZbTdEBZs2vEiTiS9m61ssiDA== } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + caniuse-lite@1.0.30001703: + resolution: {integrity: sha512-kRlAGTRWgPsOj7oARC9m1okJEXdL/8fekFVcxA8Hl7GH4r/sN4OJn/i6Flde373T50KS7Y37oFbMwlE8+F42kQ==} - duplexer@0.1.2: - resolution: { integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== } + canvas@2.11.2: + resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==} + engines: {node: '>=6'} - eastasianwidth@0.2.0: - resolution: { integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== } + chai@5.2.0: + resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} + engines: {node: '>=12'} - electron-to-chromium@1.5.115: - resolution: { integrity: sha512-MN1nahVHAQMOz6dz6bNZ7apgqc9InZy7Ja4DBEVCTdeiUcegbyOYE9bi/f2Z/z6ZxLi0RxLpyJ3EGe+4h3w73A== } + chalk-template@1.1.0: + resolution: {integrity: sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==} + engines: {node: '>=14.16'} - emoji-regex@8.0.0: - resolution: { integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== } + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - emoji-regex@9.2.2: - resolution: { integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== } + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} - encoding-sniffer@0.2.0: - resolution: { integrity: sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg== } + cheerio-select@2.1.0: + resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} - end-of-stream@1.4.4: - resolution: { integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== } + cheerio@1.0.0: + resolution: {integrity: sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==} + engines: {node: '>=18.17'} - entities@4.5.0: - resolution: { integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== } - engines: { node: ">=0.12" } + cheerio@1.0.0-rc.12: + resolution: {integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==} + engines: {node: '>= 6'} - es-module-lexer@1.6.0: - resolution: { integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ== } + chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} - esbuild@0.25.1: - resolution: { integrity: sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ== } - engines: { node: ">=18" } - hasBin: true + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} - escalade@3.2.0: - resolution: { integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== } - engines: { node: ">=6" } + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} - escape-string-regexp@4.0.0: - resolution: { integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== } - engines: { node: ">=10" } + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} - eslint-scope@8.3.0: - resolution: { integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - eslint-visitor-keys@3.4.3: - resolution: { integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true - eslint-visitor-keys@4.2.0: - resolution: { integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - eslint@9.22.0: - resolution: { integrity: sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - hasBin: true - peerDependencies: - jiti: "*" - peerDependenciesMeta: - jiti: - optional: true + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} - espree@10.3.0: - resolution: { integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + commander@13.1.0: + resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} + engines: {node: '>=18'} - esquery@1.6.0: - resolution: { integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== } - engines: { node: ">=0.10" } + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - esrecurse@4.3.0: - resolution: { integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== } - engines: { node: ">=4.0" } + console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - estraverse@5.3.0: - resolution: { integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== } - engines: { node: ">=4.0" } + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} - estree-walker@3.0.3: - resolution: { integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== } + cosmiconfig@9.0.0: + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true - esutils@2.0.3: - resolution: { integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== } - engines: { node: ">=0.10.0" } + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} - event-stream@3.3.4: - resolution: { integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g== } + css-select@5.1.0: + resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} - event-target-shim@5.0.1: - resolution: { integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== } - engines: { node: ">=6" } + css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} - events@3.3.0: - resolution: { integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== } - engines: { node: ">=0.8.x" } + csv-stringify@6.5.2: + resolution: {integrity: sha512-RFPahj0sXcmUyjrObAK+DOWtMvMIFV328n4qZJhgX3x2RqkQgOTU2mCUmiFR0CzM6AzChlRSUErjiJeEt8BaQA==} - expect-type@1.2.0: - resolution: { integrity: sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA== } - engines: { node: ">=12.0.0" } + cycletls@1.0.27: + resolution: {integrity: sha512-LZPyuj32BZm/rIt35dmim2ykb1hodwkFXc7K4zXei2p/ykcb7qNOf+JeBK0Ls5lyCbmyDyYkHYQmkHfow0JmNw==} + engines: {node: '>=18.0.0'} - fast-copy@3.0.2: - resolution: { integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ== } + dateformat@4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} - fast-deep-equal@3.1.3: - resolution: { integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== } + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true - fast-glob@3.3.3: - resolution: { integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== } - engines: { node: ">=8.6.0" } + decompress-response@4.2.1: + resolution: {integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==} + engines: {node: '>=8'} - fast-json-stable-stringify@2.1.0: - resolution: { integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== } + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} - fast-levenshtein@2.0.6: - resolution: { integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== } + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} - fast-redact@3.5.0: - resolution: { integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A== } - engines: { node: ">=6" } + defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} - fast-safe-stringify@2.1.1: - resolution: { integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== } + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} - fastq@1.19.1: - resolution: { integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== } + delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - fflate@0.8.2: - resolution: { integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== } + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} - file-entry-cache@8.0.0: - resolution: { integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== } - engines: { node: ">=16.0.0" } + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - file-type@20.4.0: - resolution: { integrity: sha512-+NZeExsi4G6EWaMbSmvBeCoqsj9EqNvOj1o/0uPVPW4O51FSCmxFlNEp/PitsqBMCbax4cGoaYmnUK5FLTuG4g== } - engines: { node: ">=18" } + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - fill-range@7.1.1: - resolution: { integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== } - engines: { node: ">=8" } + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} - find-up@5.0.0: - resolution: { integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== } - engines: { node: ">=10" } + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} - flat-cache@4.0.1: - resolution: { integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== } - engines: { node: ">=16" } + dot-prop@6.0.1: + resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==} + engines: {node: '>=10'} - flatted@3.3.3: - resolution: { integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== } + dot-prop@7.2.0: + resolution: {integrity: sha512-Ol/IPXUARn9CSbkrdV4VJo7uCy1I3VuSiWCaFSg+8BdUOzF9n3jefIpcgAydvUZbTdEBZs2vEiTiS9m61ssiDA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - foreground-child@3.3.1: - resolution: { integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== } - engines: { node: ">=14" } + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} - form-data-encoder@4.0.2: - resolution: { integrity: sha512-KQVhvhK8ZkWzxKxOr56CPulAhH3dobtuQ4+hNQ+HekH/Wp5gSOafqRAeTphQUJAIk0GBvHZgJ2ZGRWd5kphMuw== } - engines: { node: ">= 18" } + duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} - from@0.1.7: - resolution: { integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g== } + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - fs-extra@11.3.0: - resolution: { integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew== } - engines: { node: ">=14.14" } + effect@3.14.2: + resolution: {integrity: sha512-AqLlvhkcWqSgfPnfGO/JdwvEqhtzFLb4qwe43YLwrvnN5ev2dqB4ve2Bv6oq64iplRMYO9lmYRibN0Ig6fK/nQ==} - fs-minipass@2.1.0: - resolution: { integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== } - engines: { node: ">= 8" } + electron-to-chromium@1.5.115: + resolution: {integrity: sha512-MN1nahVHAQMOz6dz6bNZ7apgqc9InZy7Ja4DBEVCTdeiUcegbyOYE9bi/f2Z/z6ZxLi0RxLpyJ3EGe+4h3w73A==} - fs.realpath@1.0.0: - resolution: { integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== } + emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} - fsevents@2.3.3: - resolution: { integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== } - engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } - os: [darwin] + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - gauge@3.0.2: - resolution: { integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== } - engines: { node: ">=10" } - deprecated: This package is no longer supported. + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - generative-bayesian-network@2.1.62: - resolution: { integrity: sha512-+zq1/AHdxb+0MXF34krM/IUu/N9gI6llzQg2gf7WMfuzh0nv6xbhb8QyfL48MOJihum7wSE90+/hMXK60X+Kpw== } + encoding-sniffer@0.2.0: + resolution: {integrity: sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==} - get-stream@9.0.1: - resolution: { integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA== } - engines: { node: ">=18" } + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - glob-parent@5.1.2: - resolution: { integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== } - engines: { node: ">= 6" } + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} - glob-parent@6.0.2: - resolution: { integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== } - engines: { node: ">=10.13.0" } + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} - glob@11.0.1: - resolution: { integrity: sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw== } - engines: { node: 20 || >=22 } - hasBin: true + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} - glob@7.2.3: - resolution: { integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== } - deprecated: Glob versions prior to v9 are no longer supported + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - globals@14.0.0: - resolution: { integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== } - engines: { node: ">=18" } + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} - got-scraping@4.1.1: - resolution: { integrity: sha512-MbT+NMMU4VgvOg2tFIPOSIrMfH986fm0LJ17RxBLKlyTs3gh3xIMETpe+zdPaXY7tH1j6YYeqtfG0TnVMx6V2g== } - engines: { node: ">=16" } + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} - got@14.4.6: - resolution: { integrity: sha512-rnhwfM/PhMNJ1i17k3DuDqgj0cKx3IHxBKVv/WX1uDKqrhi2Gv3l7rhPThR/Cc6uU++dD97W9c8Y0qyw9x0jag== } - engines: { node: ">=20" } + es-module-lexer@1.6.0: + resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} - graceful-fs@4.2.11: - resolution: { integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== } + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} - graphemer@1.4.0: - resolution: { integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== } + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} - has-flag@4.0.0: - resolution: { integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== } - engines: { node: ">=8" } + esbuild@0.25.1: + resolution: {integrity: sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==} + engines: {node: '>=18'} + hasBin: true - has-unicode@2.0.1: - resolution: { integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== } + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} - header-generator@2.1.62: - resolution: { integrity: sha512-L4y1Fush4bkC/3zEurWjiwzeuekAH3HMYA508EZDmvk1wPmcbpV/mq3u3d3fxq7v4oPmaCfsRm1T5DUH19uikA== } - engines: { node: ">=16.0.0" } + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - help-me@5.0.0: - resolution: { integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg== } + event-stream@3.3.4: + resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==} - htmlparser2@8.0.2: - resolution: { integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== } + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} - htmlparser2@9.1.0: - resolution: { integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ== } + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} - http-cache-semantics@4.1.1: - resolution: { integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== } + expect-type@1.2.0: + resolution: {integrity: sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA==} + engines: {node: '>=12.0.0'} - http2-wrapper@2.2.1: - resolution: { integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ== } - engines: { node: ">=10.19.0" } + fast-check@3.23.2: + resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==} + engines: {node: '>=8.0.0'} - https-proxy-agent@5.0.1: - resolution: { integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== } - engines: { node: ">= 6" } + fast-copy@3.0.2: + resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==} - iconv-lite@0.6.3: - resolution: { integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== } - engines: { node: ">=0.10.0" } + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - ieee754@1.2.1: - resolution: { integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== } + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} - ignore@5.3.2: - resolution: { integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== } - engines: { node: ">= 4" } + fast-redact@3.5.0: + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} + engines: {node: '>=6'} - import-fresh@3.3.1: - resolution: { integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== } - engines: { node: ">=6" } + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - imurmurhash@0.1.4: - resolution: { integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== } - engines: { node: ">=0.8.19" } + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} - inflight@1.0.6: - resolution: { integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== } - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} - inherits@2.0.4: - resolution: { integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== } + file-type@20.4.0: + resolution: {integrity: sha512-+NZeExsi4G6EWaMbSmvBeCoqsj9EqNvOj1o/0uPVPW4O51FSCmxFlNEp/PitsqBMCbax4cGoaYmnUK5FLTuG4g==} + engines: {node: '>=18'} - is-extglob@2.1.1: - resolution: { integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== } - engines: { node: ">=0.10.0" } + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} - is-fullwidth-code-point@3.0.0: - resolution: { integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== } - engines: { node: ">=8" } + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} - is-glob@4.0.3: - resolution: { integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== } - engines: { node: ">=0.10.0" } + form-data-encoder@4.0.2: + resolution: {integrity: sha512-KQVhvhK8ZkWzxKxOr56CPulAhH3dobtuQ4+hNQ+HekH/Wp5gSOafqRAeTphQUJAIk0GBvHZgJ2ZGRWd5kphMuw==} + engines: {node: '>= 18'} - is-number@7.0.0: - resolution: { integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== } - engines: { node: ">=0.12.0" } + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} + engines: {node: '>= 6'} - is-obj@2.0.0: - resolution: { integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== } - engines: { node: ">=8" } + from@0.1.7: + resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==} - is-stream@4.0.1: - resolution: { integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A== } - engines: { node: ">=18" } + fs-extra@11.3.0: + resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} + engines: {node: '>=14.14'} - isexe@2.0.0: - resolution: { integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== } + fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} - jackspeak@4.1.0: - resolution: { integrity: sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw== } - engines: { node: 20 || >=22 } + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - joycon@3.1.1: - resolution: { integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== } - engines: { node: ">=10" } + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] - js-yaml@4.1.0: - resolution: { integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== } - hasBin: true + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - json-buffer@3.0.1: - resolution: { integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== } + gauge@3.0.2: + resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} + engines: {node: '>=10'} + deprecated: This package is no longer supported. - json-schema-traverse@0.4.1: - resolution: { integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== } + generative-bayesian-network@2.1.62: + resolution: {integrity: sha512-+zq1/AHdxb+0MXF34krM/IUu/N9gI6llzQg2gf7WMfuzh0nv6xbhb8QyfL48MOJihum7wSE90+/hMXK60X+Kpw==} - json-stable-stringify-without-jsonify@1.0.1: - resolution: { integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== } + get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + engines: {node: '>=18'} - json5@2.2.3: - resolution: { integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== } - engines: { node: ">=6" } - hasBin: true + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} - jsonfile@6.1.0: - resolution: { integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== } + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} - keyv@4.5.4: - resolution: { integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== } + get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} - levn@0.4.1: - resolution: { integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== } - engines: { node: ">= 0.8.0" } + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} - locate-path@6.0.0: - resolution: { integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== } - engines: { node: ">=10" } + glob@11.0.1: + resolution: {integrity: sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==} + engines: {node: 20 || >=22} + hasBin: true - lodash.isequal@4.5.0: - resolution: { integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== } - deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported - lodash.merge@4.6.2: - resolution: { integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== } + globby@14.1.0: + resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==} + engines: {node: '>=18'} - lodash@4.17.21: - resolution: { integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== } + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} - loupe@3.1.3: - resolution: { integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug== } + got-scraping@4.1.1: + resolution: {integrity: sha512-MbT+NMMU4VgvOg2tFIPOSIrMfH986fm0LJ17RxBLKlyTs3gh3xIMETpe+zdPaXY7tH1j6YYeqtfG0TnVMx6V2g==} + engines: {node: '>=16'} - lowercase-keys@3.0.0: - resolution: { integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + got@14.4.6: + resolution: {integrity: sha512-rnhwfM/PhMNJ1i17k3DuDqgj0cKx3IHxBKVv/WX1uDKqrhi2Gv3l7rhPThR/Cc6uU++dD97W9c8Y0qyw9x0jag==} + engines: {node: '>=20'} - lru-cache@11.0.2: - resolution: { integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA== } - engines: { node: 20 || >=22 } + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - magic-string@0.30.17: - resolution: { integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== } + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} - make-dir@3.1.0: - resolution: { integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== } - engines: { node: ">=8" } + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} - map-stream@0.1.0: - resolution: { integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g== } + has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - merge2@1.4.1: - resolution: { integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== } - engines: { node: ">= 8" } + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} - micromatch@4.0.8: - resolution: { integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== } - engines: { node: ">=8.6" } + header-generator@2.1.62: + resolution: {integrity: sha512-L4y1Fush4bkC/3zEurWjiwzeuekAH3HMYA508EZDmvk1wPmcbpV/mq3u3d3fxq7v4oPmaCfsRm1T5DUH19uikA==} + engines: {node: '>=16.0.0'} - mime-db@1.52.0: - resolution: { integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== } - engines: { node: ">= 0.6" } + help-me@5.0.0: + resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} - mime-types@2.1.35: - resolution: { integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== } - engines: { node: ">= 0.6" } + hosted-git-info@8.0.2: + resolution: {integrity: sha512-sYKnA7eGln5ov8T8gnYlkSOxFJvywzEx9BueN6xo/GKO8PGiI6uK6xx+DIGe45T3bdVjLAQDQW1aicT8z8JwQg==} + engines: {node: ^18.17.0 || >=20.5.0} - mimic-response@2.1.0: - resolution: { integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== } - engines: { node: ">=8" } + htmlparser2@8.0.2: + resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} - mimic-response@3.1.0: - resolution: { integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== } - engines: { node: ">=10" } + htmlparser2@9.1.0: + resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} - mimic-response@4.0.0: - resolution: { integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg== } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - minimatch@10.0.1: - resolution: { integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ== } - engines: { node: 20 || >=22 } + http2-wrapper@2.2.1: + resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} + engines: {node: '>=10.19.0'} - minimatch@3.1.2: - resolution: { integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== } + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} - minimatch@9.0.5: - resolution: { integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== } - engines: { node: ">=16 || 14 >=14.17" } + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} - minimist@1.2.8: - resolution: { integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== } + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - minipass@3.3.6: - resolution: { integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== } - engines: { node: ">=8" } + ignore@7.0.3: + resolution: {integrity: sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==} + engines: {node: '>= 4'} - minipass@5.0.0: - resolution: { integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== } - engines: { node: ">=8" } + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} - minipass@7.1.2: - resolution: { integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== } - engines: { node: ">=16 || 14 >=14.17" } + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - minizlib@2.1.2: - resolution: { integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== } - engines: { node: ">= 8" } + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - mkdirp@1.0.4: - resolution: { integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== } - engines: { node: ">=10" } - hasBin: true + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - ms@2.1.3: - resolution: { integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== } + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} - nan@2.22.2: - resolution: { integrity: sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ== } + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} - nanoid@3.3.9: - resolution: { integrity: sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg== } - engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } - hasBin: true + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} - natural-compare@1.4.0: - resolution: { integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== } + is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} - node-fetch@2.7.0: - resolution: { integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== } - engines: { node: 4.x || >=6.0.0 } - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} - node-pdf-parser@1.0.3: - resolution: { integrity: sha512-LnvqloLp5A2rsR4Ht8Sci5xK0HDrWq8A1bJ1ZjL/bmnmcD3zbjX8AItrEovoadpyLrV5R9XKtE0CoTipcJuQKg== } + is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} - node-releases@2.0.19: - resolution: { integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== } + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} - nopt@5.0.0: - resolution: { integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== } - engines: { node: ">=6" } - hasBin: true + is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} - normalize-url@8.0.1: - resolution: { integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w== } - engines: { node: ">=14.16" } + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} - npmlog@5.0.1: - resolution: { integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== } - deprecated: This package is no longer supported. + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - nth-check@2.1.1: - resolution: { integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== } + jackspeak@4.1.0: + resolution: {integrity: sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==} + engines: {node: 20 || >=22} - object-assign@4.1.1: - resolution: { integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== } - engines: { node: ">=0.10.0" } + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} - on-exit-leak-free@2.1.2: - resolution: { integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== } - engines: { node: ">=14.0.0" } + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - once@1.4.0: - resolution: { integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== } + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true - optionator@0.9.4: - resolution: { integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== } - engines: { node: ">= 0.8.0" } + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - ow@0.28.2: - resolution: { integrity: sha512-dD4UpyBh/9m4X2NVjA+73/ZPBRF+uF4zIMFvvQsabMiEK8x41L3rQ8EENOi35kyyoaJwNxEeJcP6Fj1H4U409Q== } - engines: { node: ">=12" } + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - ow@1.1.1: - resolution: { integrity: sha512-sJBRCbS5vh1Jp9EOgwp1Ws3c16lJrUkJYlvWTYC03oyiYVwS/ns7lKRWow4w4XjDyTrA2pplQv4B2naWSR6yDA== } - engines: { node: ">=14.16" } + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true - p-cancelable@4.0.1: - resolution: { integrity: sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg== } - engines: { node: ">=14.16" } + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} - p-limit@3.1.0: - resolution: { integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== } - engines: { node: ">=10" } + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - p-locate@5.0.0: - resolution: { integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== } - engines: { node: ">=10" } + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - package-json-from-dist@1.0.1: - resolution: { integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== } + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} - parent-module@1.0.1: - resolution: { integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== } - engines: { node: ">=6" } + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - parse5-htmlparser2-tree-adapter@7.1.0: - resolution: { integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g== } + lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. - parse5-parser-stream@7.1.2: - resolution: { integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow== } + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - parse5@7.2.1: - resolution: { integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ== } + log-symbols@6.0.0: + resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + engines: {node: '>=18'} - path-exists@4.0.0: - resolution: { integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== } - engines: { node: ">=8" } + loupe@3.1.3: + resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} - path-is-absolute@1.0.1: - resolution: { integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== } - engines: { node: ">=0.10.0" } + lowercase-keys@3.0.0: + resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - path-key@3.1.1: - resolution: { integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== } - engines: { node: ">=8" } + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - path-scurry@2.0.0: - resolution: { integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg== } - engines: { node: 20 || >=22 } + lru-cache@11.0.2: + resolution: {integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==} + engines: {node: 20 || >=22} - path2d-polyfill@2.0.1: - resolution: { integrity: sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA== } - engines: { node: ">=8" } + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} - pathe@2.0.3: - resolution: { integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== } + make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} - pathval@2.0.0: - resolution: { integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== } - engines: { node: ">= 14.16" } + map-stream@0.1.0: + resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} - pause-stream@0.0.11: - resolution: { integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A== } + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} - pdfjs-dist@3.11.174: - resolution: { integrity: sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA== } - engines: { node: ">=18" } + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} - peek-readable@7.0.0: - resolution: { integrity: sha512-nri2TO5JE3/mRryik9LlHFT53cgHfRK0Lt0BAZQXku/AW3E6XLt2GaY8siWi7dvW/m1z0ecn+J+bpDa9ZN3IsQ== } - engines: { node: ">=18" } + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} - picocolors@1.1.1: - resolution: { integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== } + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} - picomatch@2.3.1: - resolution: { integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== } - engines: { node: ">=8.6" } + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} - pino-abstract-transport@2.0.0: - resolution: { integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw== } + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} - pino-pretty@11.3.0: - resolution: { integrity: sha512-oXwn7ICywaZPHmu3epHGU2oJX4nPmKvHvB/bwrJHlGcbEWaVcotkpyVHMKLKmiVryWYByNp0jpgAcXpFJDXJzA== } - hasBin: true + mimic-response@2.1.0: + resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} + engines: {node: '>=8'} - pino-std-serializers@7.0.0: - resolution: { integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA== } + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} - pino@9.6.0: - resolution: { integrity: sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg== } - hasBin: true + mimic-response@4.0.0: + resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - postcss@8.5.3: - resolution: { integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== } - engines: { node: ^10 || ^12 || >=14 } + minimatch@10.0.1: + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} - prelude-ls@1.2.1: - resolution: { integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== } - engines: { node: ">= 0.8.0" } + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - prettier@3.5.3: - resolution: { integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw== } - engines: { node: ">=14" } - hasBin: true + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} - process-warning@4.0.1: - resolution: { integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q== } + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - process@0.11.10: - resolution: { integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== } - engines: { node: ">= 0.6.0" } + minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} - proper-lockfile@4.1.2: - resolution: { integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== } + minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} - pump@3.0.2: - resolution: { integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw== } + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} - punycode@2.3.1: - resolution: { integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== } - engines: { node: ">=6" } + minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} - queue-microtask@1.2.3: - resolution: { integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== } + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true - quick-format-unescaped@4.0.4: - resolution: { integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== } + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - quick-lru@5.1.1: - resolution: { integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== } - engines: { node: ">=10" } + nan@2.22.2: + resolution: {integrity: sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==} - quick-lru@7.0.0: - resolution: { integrity: sha512-MX8gB7cVYTrYcFfAnfLlhRd0+Toyl8yX8uBx1MrX7K0jegiz9TumwOK27ldXrgDlHRdVi+MqU9Ssw6dr4BNreg== } - engines: { node: ">=18" } + nanoid@3.3.9: + resolution: {integrity: sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true - readable-stream@3.6.2: - resolution: { integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== } - engines: { node: ">= 6" } + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true - readable-stream@4.7.0: - resolution: { integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg== } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + node-pdf-parser@1.0.3: + resolution: {integrity: sha512-LnvqloLp5A2rsR4Ht8Sci5xK0HDrWq8A1bJ1ZjL/bmnmcD3zbjX8AItrEovoadpyLrV5R9XKtE0CoTipcJuQKg==} - real-require@0.2.0: - resolution: { integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== } - engines: { node: ">= 12.13.0" } + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} - resolve-alpn@1.2.1: - resolution: { integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== } + nopt@5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true - resolve-from@4.0.0: - resolution: { integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== } - engines: { node: ">=4" } + normalize-url@8.0.1: + resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==} + engines: {node: '>=14.16'} - responselike@3.0.0: - resolution: { integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg== } - engines: { node: ">=14.16" } + npm-package-arg@12.0.2: + resolution: {integrity: sha512-f1NpFjNI9O4VbKMOlA5QoBq/vSQPORHcTZ2feJpFkTHJ9eQkdlmZEKSjcAhxTGInC7RlEyScT9ui67NaOsjFWA==} + engines: {node: ^18.17.0 || >=20.5.0} - retry@0.12.0: - resolution: { integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== } - engines: { node: ">= 4" } + npmlog@5.0.1: + resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} + deprecated: This package is no longer supported. - reusify@1.1.0: - resolution: { integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== } - engines: { iojs: ">=1.0.0", node: ">=0.10.0" } + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - rimraf@3.0.2: - resolution: { integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== } - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} - rimraf@6.0.1: - resolution: { integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A== } - engines: { node: 20 || >=22 } - hasBin: true + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} - robots-parser@3.0.1: - resolution: { integrity: sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ== } - engines: { node: ">=10.0.0" } + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - rollup@4.35.0: - resolution: { integrity: sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg== } - engines: { node: ">=18.0.0", npm: ">=8.0.0" } - hasBin: true + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} - run-parallel@1.2.0: - resolution: { integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== } + ora@8.2.0: + resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} + engines: {node: '>=18'} - safe-buffer@5.2.1: - resolution: { integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== } + ow@0.28.2: + resolution: {integrity: sha512-dD4UpyBh/9m4X2NVjA+73/ZPBRF+uF4zIMFvvQsabMiEK8x41L3rQ8EENOi35kyyoaJwNxEeJcP6Fj1H4U409Q==} + engines: {node: '>=12'} - safe-stable-stringify@2.5.0: - resolution: { integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== } - engines: { node: ">=10" } + ow@1.1.1: + resolution: {integrity: sha512-sJBRCbS5vh1Jp9EOgwp1Ws3c16lJrUkJYlvWTYC03oyiYVwS/ns7lKRWow4w4XjDyTrA2pplQv4B2naWSR6yDA==} + engines: {node: '>=14.16'} - safer-buffer@2.1.2: - resolution: { integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== } + p-cancelable@4.0.1: + resolution: {integrity: sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==} + engines: {node: '>=14.16'} - sax@1.4.1: - resolution: { integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== } + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - secure-json-parse@2.7.0: - resolution: { integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== } + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} - semver@6.3.1: - resolution: { integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== } - hasBin: true + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} - semver@7.7.1: - resolution: { integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== } - engines: { node: ">=10" } - hasBin: true + parse5-htmlparser2-tree-adapter@7.1.0: + resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} - set-blocking@2.0.0: - resolution: { integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== } + parse5-parser-stream@7.1.2: + resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} - shebang-command@2.0.0: - resolution: { integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== } - engines: { node: ">=8" } + parse5@7.2.1: + resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==} - shebang-regex@3.0.0: - resolution: { integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== } - engines: { node: ">=8" } + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} - siginfo@2.0.0: - resolution: { integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== } + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} - signal-exit@3.0.7: - resolution: { integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== } + path-scurry@2.0.0: + resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + engines: {node: 20 || >=22} - signal-exit@4.1.0: - resolution: { integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== } - engines: { node: ">=14" } + path-type@6.0.0: + resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==} + engines: {node: '>=18'} - simple-concat@1.0.1: - resolution: { integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== } + path2d-polyfill@2.0.1: + resolution: {integrity: sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==} + engines: {node: '>=8'} - simple-get@3.1.1: - resolution: { integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== } + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - sonic-boom@4.2.0: - resolution: { integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww== } + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} - source-map-js@1.2.1: - resolution: { integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== } - engines: { node: ">=0.10.0" } + pause-stream@0.0.11: + resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} - split2@4.2.0: - resolution: { integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== } - engines: { node: ">= 10.x" } + pdfjs-dist@3.11.174: + resolution: {integrity: sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==} + engines: {node: '>=18'} - split@0.3.3: - resolution: { integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA== } + peek-readable@7.0.0: + resolution: {integrity: sha512-nri2TO5JE3/mRryik9LlHFT53cgHfRK0Lt0BAZQXku/AW3E6XLt2GaY8siWi7dvW/m1z0ecn+J+bpDa9ZN3IsQ==} + engines: {node: '>=18'} - stackback@0.0.2: - resolution: { integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== } + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - std-env@3.8.1: - resolution: { integrity: sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA== } + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} - stream-chain@2.2.5: - resolution: { integrity: sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA== } + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} - stream-combiner@0.0.4: - resolution: { integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw== } + pino-pretty@11.3.0: + resolution: {integrity: sha512-oXwn7ICywaZPHmu3epHGU2oJX4nPmKvHvB/bwrJHlGcbEWaVcotkpyVHMKLKmiVryWYByNp0jpgAcXpFJDXJzA==} + hasBin: true - stream-json@1.9.1: - resolution: { integrity: sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw== } + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} - string-width@4.2.3: - resolution: { integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== } - engines: { node: ">=8" } + pino@9.6.0: + resolution: {integrity: sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==} + hasBin: true - string-width@5.1.2: - resolution: { integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== } - engines: { node: ">=12" } + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} - string_decoder@1.3.0: - resolution: { integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== } + proc-log@5.0.0: + resolution: {integrity: sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==} + engines: {node: ^18.17.0 || >=20.5.0} - strip-ansi@6.0.1: - resolution: { integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== } - engines: { node: ">=8" } + process-warning@4.0.1: + resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==} - strip-ansi@7.1.0: - resolution: { integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== } - engines: { node: ">=12" } + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} - strip-json-comments@3.1.1: - resolution: { integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== } - engines: { node: ">=8" } + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} - strtok3@10.2.2: - resolution: { integrity: sha512-Xt18+h4s7Z8xyZ0tmBoRmzxcop97R4BAh+dXouUDCYn+Em+1P3qpkUfI5ueWLT8ynC5hZ+q4iPEmGG1urvQGBg== } - engines: { node: ">=18" } + proper-lockfile@4.1.2: + resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} - supports-color@7.2.0: - resolution: { integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== } - engines: { node: ">=8" } + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} - tar@6.2.1: - resolution: { integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== } - engines: { node: ">=10" } + pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} - thread-stream@3.1.0: - resolution: { integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A== } + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - through@2.3.8: - resolution: { integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== } + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} - tinybench@2.9.0: - resolution: { integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== } + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} - tinyexec@0.3.2: - resolution: { integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== } + quick-lru@7.0.0: + resolution: {integrity: sha512-MX8gB7cVYTrYcFfAnfLlhRd0+Toyl8yX8uBx1MrX7K0jegiz9TumwOK27ldXrgDlHRdVi+MqU9Ssw6dr4BNreg==} + engines: {node: '>=18'} - tinypool@1.0.2: - resolution: { integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA== } - engines: { node: ^18.0.0 || >=20.0.0 } + read-yaml-file@2.1.0: + resolution: {integrity: sha512-UkRNRIwnhG+y7hpqnycCL/xbTk7+ia9VuVTC0S+zVbwd65DI9eUpRMfsWIGrCWxTU/mi+JW8cHQCrv+zfCbEPQ==} + engines: {node: '>=10.13'} - tinyrainbow@2.0.0: - resolution: { integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw== } - engines: { node: ">=14.0.0" } + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} - tinyspy@3.0.2: - resolution: { integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q== } - engines: { node: ">=14.0.0" } + readable-stream@4.7.0: + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - tldts-core@6.1.84: - resolution: { integrity: sha512-NaQa1W76W2aCGjXybvnMYzGSM4x8fvG2AN/pla7qxcg0ZHbooOPhA8kctmOZUDfZyhDL27OGNbwAeig8P4p1vg== } + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} - tldts@6.1.84: - resolution: { integrity: sha512-aRGIbCIF3teodtUFAYSdQONVmDRy21REM3o6JnqWn5ZkQBJJ4gHxhw6OfwQ+WkSAi3ASamrS4N4nyazWx6uTYg== } - hasBin: true - - to-regex-range@5.0.1: - resolution: { integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== } - engines: { node: ">=8.0" } - - token-types@6.0.0: - resolution: { integrity: sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA== } - engines: { node: ">=14.16" } - - tough-cookie@5.1.2: - resolution: { integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A== } - engines: { node: ">=16" } - - tr46@0.0.3: - resolution: { integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== } - - ts-api-utils@2.0.1: - resolution: { integrity: sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w== } - engines: { node: ">=18.12" } - peerDependencies: - typescript: ">=4.8.4" - - tslib@2.8.1: - resolution: { integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== } - - type-check@0.4.0: - resolution: { integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== } - engines: { node: ">= 0.8.0" } - - type-fest@2.19.0: - resolution: { integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== } - engines: { node: ">=12.20" } - - type-fest@4.37.0: - resolution: { integrity: sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg== } - engines: { node: ">=16" } - - typescript-eslint@8.26.1: - resolution: { integrity: sha512-t/oIs9mYyrwZGRpDv3g+3K6nZ5uhKEMt2oNmAPwaY4/ye0+EH4nXIPYNtkYFS6QHm+1DFg34DbglYBz5P9Xysg== } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - - typescript@5.5.4: - resolution: { integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== } - engines: { node: ">=14.17" } - hasBin: true - - uint8array-extras@1.4.0: - resolution: { integrity: sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ== } - engines: { node: ">=18" } - - undici-types@6.20.0: - resolution: { integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== } - - undici@6.21.1: - resolution: { integrity: sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ== } - engines: { node: ">=18.17" } - - universalify@2.0.1: - resolution: { integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== } - engines: { node: ">= 10.0.0" } - - update-browserslist-db@1.1.3: - resolution: { integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== } - hasBin: true - peerDependencies: - browserslist: ">= 4.21.0" - - uri-js@4.4.1: - resolution: { integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== } - - util-deprecate@1.0.2: - resolution: { integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== } - - vali-date@1.0.0: - resolution: { integrity: sha512-sgECfZthyaCKW10N0fm27cg8HYTFK5qMWgypqkXMQ4Wbl/zZKx7xZICgcoxIIE+WFAP/MBL2EFwC/YvLxw3Zeg== } - engines: { node: ">=0.10.0" } - - vite-node@3.0.8: - resolution: { integrity: sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg== } - engines: { node: ^18.0.0 || ^20.0.0 || >=22.0.0 } - hasBin: true - - vite@6.2.1: - resolution: { integrity: sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q== } - engines: { node: ^18.0.0 || ^20.0.0 || >=22.0.0 } - hasBin: true - peerDependencies: - "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 - jiti: ">=1.21.0" - less: "*" - lightningcss: ^1.21.0 - sass: "*" - sass-embedded: "*" - stylus: "*" - sugarss: "*" - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - "@types/node": - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - - vitest@3.0.8: - resolution: { integrity: sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA== } - engines: { node: ^18.0.0 || ^20.0.0 || >=22.0.0 } - hasBin: true - peerDependencies: - "@edge-runtime/vm": "*" - "@types/debug": ^4.1.12 - "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 - "@vitest/browser": 3.0.8 - "@vitest/ui": 3.0.8 - happy-dom: "*" - jsdom: "*" - peerDependenciesMeta: - "@edge-runtime/vm": - optional: true - "@types/debug": - optional: true - "@types/node": - optional: true - "@vitest/browser": - optional: true - "@vitest/ui": - optional: true - happy-dom: - optional: true - jsdom: - optional: true - - webidl-conversions@3.0.1: - resolution: { integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== } - - whatwg-encoding@3.1.1: - resolution: { integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ== } - engines: { node: ">=18" } - - whatwg-mimetype@4.0.0: - resolution: { integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg== } - engines: { node: ">=18" } - - whatwg-url@5.0.0: - resolution: { integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== } - - which@2.0.2: - resolution: { integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== } - engines: { node: ">= 8" } - hasBin: true - - why-is-node-running@2.3.0: - resolution: { integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w== } - engines: { node: ">=8" } - hasBin: true - - wide-align@1.1.5: - resolution: { integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== } - - word-wrap@1.2.5: - resolution: { integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== } - engines: { node: ">=0.10.0" } - - wrap-ansi@7.0.0: - resolution: { integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== } - engines: { node: ">=10" } - - wrap-ansi@8.1.0: - resolution: { integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== } - engines: { node: ">=12" } - - wrappy@1.0.2: - resolution: { integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== } - - yallist@4.0.0: - resolution: { integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== } - - yocto-queue@0.1.0: - resolution: { integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== } - engines: { node: ">=10" } + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} -snapshots: - "@apify/consts@2.38.0": {} - - "@apify/datastructures@2.0.2": {} - - "@apify/log@2.5.14": - dependencies: - "@apify/consts": 2.38.0 - ansi-colors: 4.1.3 - - "@apify/ps-tree@1.2.0": - dependencies: - event-stream: 3.3.4 - - "@apify/pseudo_url@2.0.55": - dependencies: - "@apify/log": 2.5.14 - - "@apify/timeout@0.3.1": {} - - "@apify/utilities@2.15.1": - dependencies: - "@apify/consts": 2.38.0 - "@apify/log": 2.5.14 - - "@crawlee/core@3.13.0": - dependencies: - "@apify/consts": 2.38.0 - "@apify/datastructures": 2.0.2 - "@apify/log": 2.5.14 - "@apify/pseudo_url": 2.0.55 - "@apify/timeout": 0.3.1 - "@apify/utilities": 2.15.1 - "@crawlee/memory-storage": 3.13.0 - "@crawlee/types": 3.13.0 - "@crawlee/utils": 3.13.0 - "@sapphire/async-queue": 1.5.5 - "@vladfrangu/async_event_emitter": 2.4.6 - csv-stringify: 6.5.2 - fs-extra: 11.3.0 - got-scraping: 4.1.1 - json5: 2.2.3 - minimatch: 9.0.5 - ow: 0.28.2 - stream-json: 1.9.1 - tldts: 6.1.84 - tough-cookie: 5.1.2 - tslib: 2.8.1 - type-fest: 4.37.0 - transitivePeerDependencies: - - supports-color - - "@crawlee/memory-storage@3.13.0": - dependencies: - "@apify/log": 2.5.14 - "@crawlee/types": 3.13.0 - "@sapphire/async-queue": 1.5.5 - "@sapphire/shapeshift": 3.9.7 - content-type: 1.0.5 - fs-extra: 11.3.0 - json5: 2.2.3 - mime-types: 2.1.35 - proper-lockfile: 4.1.2 - tslib: 2.8.1 - - "@crawlee/types@3.13.0": - dependencies: - tslib: 2.8.1 - - "@crawlee/utils@3.13.0": - dependencies: - "@apify/log": 2.5.14 - "@apify/ps-tree": 1.2.0 - "@crawlee/types": 3.13.0 - "@types/sax": 1.2.7 - cheerio: 1.0.0-rc.12 - file-type: 20.4.0 - got-scraping: 4.1.1 - ow: 0.28.2 - robots-parser: 3.0.1 - sax: 1.4.1 - tslib: 2.8.1 - whatwg-mimetype: 4.0.0 - transitivePeerDependencies: - - supports-color - - "@esbuild/aix-ppc64@0.25.1": - optional: true + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} - "@esbuild/android-arm64@0.25.1": - optional: true + responselike@3.0.0: + resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} + engines: {node: '>=14.16'} - "@esbuild/android-arm@0.25.1": - optional: true + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} - "@esbuild/android-x64@0.25.1": - optional: true + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} - "@esbuild/darwin-arm64@0.25.1": - optional: true + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - "@esbuild/darwin-x64@0.25.1": - optional: true + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true - "@esbuild/freebsd-arm64@0.25.1": - optional: true + rimraf@6.0.1: + resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} + engines: {node: 20 || >=22} + hasBin: true - "@esbuild/freebsd-x64@0.25.1": - optional: true + robots-parser@3.0.1: + resolution: {integrity: sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ==} + engines: {node: '>=10.0.0'} - "@esbuild/linux-arm64@0.25.1": - optional: true + rollup@4.35.0: + resolution: {integrity: sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true - "@esbuild/linux-arm@0.25.1": - optional: true + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - "@esbuild/linux-ia32@0.25.1": - optional: true + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - "@esbuild/linux-loong64@0.25.1": - optional: true + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} - "@esbuild/linux-mips64el@0.25.1": - optional: true + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - "@esbuild/linux-ppc64@0.25.1": - optional: true + sax@1.4.1: + resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} - "@esbuild/linux-riscv64@0.25.1": - optional: true + secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} - "@esbuild/linux-s390x@0.25.1": - optional: true + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true - "@esbuild/linux-x64@0.25.1": - optional: true + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true - "@esbuild/netbsd-arm64@0.25.1": - optional: true + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - "@esbuild/netbsd-x64@0.25.1": - optional: true + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} - "@esbuild/openbsd-arm64@0.25.1": - optional: true + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} - "@esbuild/openbsd-x64@0.25.1": - optional: true + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - "@esbuild/sunos-x64@0.25.1": - optional: true + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - "@esbuild/win32-arm64@0.25.1": - optional: true + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} - "@esbuild/win32-ia32@0.25.1": - optional: true + simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} - "@esbuild/win32-x64@0.25.1": - optional: true + simple-get@3.1.1: + resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==} - "@eslint-community/eslint-utils@4.5.0(eslint@9.22.0)": - dependencies: - eslint: 9.22.0 - eslint-visitor-keys: 3.4.3 - - "@eslint-community/regexpp@4.12.1": {} - - "@eslint/config-array@0.19.2": - dependencies: - "@eslint/object-schema": 2.1.6 - debug: 4.4.0 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - "@eslint/config-helpers@0.1.0": {} - - "@eslint/core@0.12.0": - dependencies: - "@types/json-schema": 7.0.15 - - "@eslint/eslintrc@3.3.0": - dependencies: - ajv: 6.12.6 - debug: 4.4.0 - espree: 10.3.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.1 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - "@eslint/js@9.22.0": {} - - "@eslint/object-schema@2.1.6": {} - - "@eslint/plugin-kit@0.2.7": - dependencies: - "@eslint/core": 0.12.0 - levn: 0.4.1 - - "@humanfs/core@0.19.1": {} - - "@humanfs/node@0.16.6": - dependencies: - "@humanfs/core": 0.19.1 - "@humanwhocodes/retry": 0.3.1 - - "@humanwhocodes/module-importer@1.0.1": {} - - "@humanwhocodes/retry@0.3.1": {} - - "@humanwhocodes/retry@0.4.2": {} - - "@isaacs/cliui@8.0.2": - dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 - - "@jridgewell/sourcemap-codec@1.5.0": {} - - "@mapbox/node-pre-gyp@1.0.11": - dependencies: - detect-libc: 2.0.3 - https-proxy-agent: 5.0.1 - make-dir: 3.1.0 - node-fetch: 2.7.0 - nopt: 5.0.0 - npmlog: 5.0.1 - rimraf: 3.0.2 - semver: 7.7.1 - tar: 6.2.1 - transitivePeerDependencies: - - encoding - - supports-color - optional: true + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - "@nodelib/fs.scandir@2.1.5": - dependencies: - "@nodelib/fs.stat": 2.0.5 - run-parallel: 1.2.0 + slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} - "@nodelib/fs.stat@2.0.5": {} + sonic-boom@4.2.0: + resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} - "@nodelib/fs.walk@1.2.8": - dependencies: - "@nodelib/fs.scandir": 2.1.5 - fastq: 1.19.1 + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} - "@rollup/rollup-android-arm-eabi@4.35.0": - optional: true + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} - "@rollup/rollup-android-arm64@4.35.0": - optional: true + split@0.3.3: + resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==} - "@rollup/rollup-darwin-arm64@4.35.0": - optional: true + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - "@rollup/rollup-darwin-x64@4.35.0": - optional: true + std-env@3.8.1: + resolution: {integrity: sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==} - "@rollup/rollup-freebsd-arm64@4.35.0": - optional: true + stdin-discarder@0.2.2: + resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} + engines: {node: '>=18'} - "@rollup/rollup-freebsd-x64@4.35.0": - optional: true + stream-chain@2.2.5: + resolution: {integrity: sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==} - "@rollup/rollup-linux-arm-gnueabihf@4.35.0": - optional: true + stream-combiner@0.0.4: + resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==} - "@rollup/rollup-linux-arm-musleabihf@4.35.0": - optional: true + stream-json@1.9.1: + resolution: {integrity: sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==} - "@rollup/rollup-linux-arm64-gnu@4.35.0": - optional: true + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} - "@rollup/rollup-linux-arm64-musl@4.35.0": - optional: true + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} - "@rollup/rollup-linux-loongarch64-gnu@4.35.0": - optional: true + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} - "@rollup/rollup-linux-powerpc64le-gnu@4.35.0": - optional: true + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - "@rollup/rollup-linux-riscv64-gnu@4.35.0": - optional: true + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} - "@rollup/rollup-linux-s390x-gnu@4.35.0": - optional: true + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} - "@rollup/rollup-linux-x64-gnu@4.35.0": - optional: true + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} - "@rollup/rollup-linux-x64-musl@4.35.0": - optional: true + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} - "@rollup/rollup-win32-arm64-msvc@4.35.0": - optional: true + strtok3@10.2.2: + resolution: {integrity: sha512-Xt18+h4s7Z8xyZ0tmBoRmzxcop97R4BAh+dXouUDCYn+Em+1P3qpkUfI5ueWLT8ynC5hZ+q4iPEmGG1urvQGBg==} + engines: {node: '>=18'} - "@rollup/rollup-win32-ia32-msvc@4.35.0": - optional: true + syncpack@13.0.3: + resolution: {integrity: sha512-ZKrdDVmOUBWeaTVaxRnfwtqBJ5rMzMo7Lfdp04wtORwHEcvrq6M+NzCwS4PPIhTucD005wD8wumy90Ucz3lwXg==} + engines: {node: '>=18.18.0'} + hasBin: true + + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + tightrope@0.2.0: + resolution: {integrity: sha512-Kw36UHxJEELq2VUqdaSGR2/8cAsPgMtvX8uGVU6Jk26O66PhXec0A5ZnRYs47btbtwPDpXXF66+Fo3vimCM9aQ==} + engines: {node: '>=16'} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinypool@1.0.2: + resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + + tldts-core@6.1.84: + resolution: {integrity: sha512-NaQa1W76W2aCGjXybvnMYzGSM4x8fvG2AN/pla7qxcg0ZHbooOPhA8kctmOZUDfZyhDL27OGNbwAeig8P4p1vg==} + + tldts@6.1.84: + resolution: {integrity: sha512-aRGIbCIF3teodtUFAYSdQONVmDRy21REM3o6JnqWn5ZkQBJJ4gHxhw6OfwQ+WkSAi3ASamrS4N4nyazWx6uTYg==} + hasBin: true + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + token-types@6.0.0: + resolution: {integrity: sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA==} + engines: {node: '>=14.16'} + + tough-cookie@5.1.2: + resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} + engines: {node: '>=16'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + ts-toolbelt@9.6.0: + resolution: {integrity: sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==} - "@rollup/rollup-win32-x64-msvc@4.35.0": + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + + type-fest@4.37.0: + resolution: {integrity: sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg==} + engines: {node: '>=16'} + + typescript@5.5.4: + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} + engines: {node: '>=14.17'} + hasBin: true + + uint8array-extras@1.4.0: + resolution: {integrity: sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==} + engines: {node: '>=18'} + + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + + undici@6.21.1: + resolution: {integrity: sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==} + engines: {node: '>=18.17'} + + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vali-date@1.0.0: + resolution: {integrity: sha512-sgECfZthyaCKW10N0fm27cg8HYTFK5qMWgypqkXMQ4Wbl/zZKx7xZICgcoxIIE+WFAP/MBL2EFwC/YvLxw3Zeg==} + engines: {node: '>=0.10.0'} + + validate-npm-package-name@6.0.0: + resolution: {integrity: sha512-d7KLgL1LD3U3fgnvWEY1cQXoO/q6EQ1BSz48Sa149V/5zVTAbgmZIpyI8TRi6U9/JNyeYLlTKsEMPtLC27RFUg==} + engines: {node: ^18.17.0 || >=20.5.0} + + vite-node@3.0.8: + resolution: {integrity: sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + vite@6.2.1: + resolution: {integrity: sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: optional: true - "@sapphire/async-queue@1.5.5": {} - - "@sapphire/shapeshift@3.9.7": - dependencies: - fast-deep-equal: 3.1.3 - lodash: 4.17.21 - - "@sec-ant/readable-stream@0.4.1": {} - - "@sindresorhus/is@4.6.0": {} - - "@sindresorhus/is@5.6.0": {} - - "@sindresorhus/is@7.0.1": {} - - "@szmarczak/http-timer@5.0.1": - dependencies: - defer-to-connect: 2.0.1 - - "@tokenizer/inflate@0.2.7": - dependencies: - debug: 4.4.0 - fflate: 0.8.2 - token-types: 6.0.0 - transitivePeerDependencies: - - supports-color - - "@tokenizer/token@0.3.0": {} - - "@types/estree@1.0.6": {} - - "@types/http-cache-semantics@4.0.4": {} - - "@types/json-schema@7.0.15": {} - - "@types/node@22.13.10": - dependencies: - undici-types: 6.20.0 - - "@types/sax@1.2.7": - dependencies: - "@types/node": 22.13.10 - - "@typescript-eslint/eslint-plugin@8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.5.4))(eslint@9.22.0)(typescript@5.5.4)": - dependencies: - "@eslint-community/regexpp": 4.12.1 - "@typescript-eslint/parser": 8.26.1(eslint@9.22.0)(typescript@5.5.4) - "@typescript-eslint/scope-manager": 8.26.1 - "@typescript-eslint/type-utils": 8.26.1(eslint@9.22.0)(typescript@5.5.4) - "@typescript-eslint/utils": 8.26.1(eslint@9.22.0)(typescript@5.5.4) - "@typescript-eslint/visitor-keys": 8.26.1 - eslint: 9.22.0 - graphemer: 1.4.0 - ignore: 5.3.2 - natural-compare: 1.4.0 - ts-api-utils: 2.0.1(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - "@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.5.4)": - dependencies: - "@typescript-eslint/scope-manager": 8.26.1 - "@typescript-eslint/types": 8.26.1 - "@typescript-eslint/typescript-estree": 8.26.1(typescript@5.5.4) - "@typescript-eslint/visitor-keys": 8.26.1 - debug: 4.4.0 - eslint: 9.22.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - "@typescript-eslint/scope-manager@8.26.1": - dependencies: - "@typescript-eslint/types": 8.26.1 - "@typescript-eslint/visitor-keys": 8.26.1 - - "@typescript-eslint/type-utils@8.26.1(eslint@9.22.0)(typescript@5.5.4)": - dependencies: - "@typescript-eslint/typescript-estree": 8.26.1(typescript@5.5.4) - "@typescript-eslint/utils": 8.26.1(eslint@9.22.0)(typescript@5.5.4) - debug: 4.4.0 - eslint: 9.22.0 - ts-api-utils: 2.0.1(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - "@typescript-eslint/types@8.26.1": {} - - "@typescript-eslint/typescript-estree@8.26.1(typescript@5.5.4)": - dependencies: - "@typescript-eslint/types": 8.26.1 - "@typescript-eslint/visitor-keys": 8.26.1 - debug: 4.4.0 - fast-glob: 3.3.3 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.7.1 - ts-api-utils: 2.0.1(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - "@typescript-eslint/utils@8.26.1(eslint@9.22.0)(typescript@5.5.4)": - dependencies: - "@eslint-community/eslint-utils": 4.5.0(eslint@9.22.0) - "@typescript-eslint/scope-manager": 8.26.1 - "@typescript-eslint/types": 8.26.1 - "@typescript-eslint/typescript-estree": 8.26.1(typescript@5.5.4) - eslint: 9.22.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - "@typescript-eslint/visitor-keys@8.26.1": - dependencies: - "@typescript-eslint/types": 8.26.1 - eslint-visitor-keys: 4.2.0 - - "@vitest/expect@3.0.8": - dependencies: - "@vitest/spy": 3.0.8 - "@vitest/utils": 3.0.8 - chai: 5.2.0 - tinyrainbow: 2.0.0 - - "@vitest/mocker@3.0.8(vite@6.2.1(@types/node@22.13.10))": - dependencies: - "@vitest/spy": 3.0.8 - estree-walker: 3.0.3 - magic-string: 0.30.17 - optionalDependencies: - vite: 6.2.1(@types/node@22.13.10) - - "@vitest/pretty-format@3.0.8": - dependencies: - tinyrainbow: 2.0.0 - - "@vitest/runner@3.0.8": - dependencies: - "@vitest/utils": 3.0.8 - pathe: 2.0.3 - - "@vitest/snapshot@3.0.8": - dependencies: - "@vitest/pretty-format": 3.0.8 - magic-string: 0.30.17 - pathe: 2.0.3 - - "@vitest/spy@3.0.8": - dependencies: - tinyspy: 3.0.2 - - "@vitest/utils@3.0.8": - dependencies: - "@vitest/pretty-format": 3.0.8 - loupe: 3.1.3 - tinyrainbow: 2.0.0 - - "@vladfrangu/async_event_emitter@2.4.6": {} - - abbrev@1.1.1: + vitest@3.0.8: + resolution: {integrity: sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.0.8 + '@vitest/ui': 3.0.8 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - abort-controller@3.0.0: - dependencies: - event-target-shim: 5.0.1 + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} - acorn-jsx@5.3.2(acorn@8.14.1): - dependencies: - acorn: 8.14.1 + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} - acorn@8.14.1: {} + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - adm-zip@0.5.16: {} + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true - agent-base@6.0.2: - dependencies: - debug: 4.4.0 - transitivePeerDependencies: - - supports-color + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: optional: true - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - ansi-colors@4.1.3: {} +snapshots: - ansi-regex@5.0.1: {} + '@apify/consts@2.38.0': {} + + '@apify/datastructures@2.0.2': {} + + '@apify/log@2.5.14': + dependencies: + '@apify/consts': 2.38.0 + ansi-colors: 4.1.3 + + '@apify/ps-tree@1.2.0': + dependencies: + event-stream: 3.3.4 + + '@apify/pseudo_url@2.0.55': + dependencies: + '@apify/log': 2.5.14 + + '@apify/timeout@0.3.1': {} + + '@apify/utilities@2.15.1': + dependencies: + '@apify/consts': 2.38.0 + '@apify/log': 2.5.14 + + '@babel/code-frame@7.26.2': + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/helper-validator-identifier@7.25.9': {} + + '@biomejs/biome@1.9.4': + optionalDependencies: + '@biomejs/cli-darwin-arm64': 1.9.4 + '@biomejs/cli-darwin-x64': 1.9.4 + '@biomejs/cli-linux-arm64': 1.9.4 + '@biomejs/cli-linux-arm64-musl': 1.9.4 + '@biomejs/cli-linux-x64': 1.9.4 + '@biomejs/cli-linux-x64-musl': 1.9.4 + '@biomejs/cli-win32-arm64': 1.9.4 + '@biomejs/cli-win32-x64': 1.9.4 + + '@biomejs/cli-darwin-arm64@1.9.4': + optional: true + + '@biomejs/cli-darwin-x64@1.9.4': + optional: true + + '@biomejs/cli-linux-arm64-musl@1.9.4': + optional: true + + '@biomejs/cli-linux-arm64@1.9.4': + optional: true + + '@biomejs/cli-linux-x64-musl@1.9.4': + optional: true + + '@biomejs/cli-linux-x64@1.9.4': + optional: true + + '@biomejs/cli-win32-arm64@1.9.4': + optional: true + + '@biomejs/cli-win32-x64@1.9.4': + optional: true + + '@crawlee/core@3.13.0': + dependencies: + '@apify/consts': 2.38.0 + '@apify/datastructures': 2.0.2 + '@apify/log': 2.5.14 + '@apify/pseudo_url': 2.0.55 + '@apify/timeout': 0.3.1 + '@apify/utilities': 2.15.1 + '@crawlee/memory-storage': 3.13.0 + '@crawlee/types': 3.13.0 + '@crawlee/utils': 3.13.0 + '@sapphire/async-queue': 1.5.5 + '@vladfrangu/async_event_emitter': 2.4.6 + csv-stringify: 6.5.2 + fs-extra: 11.3.0 + got-scraping: 4.1.1 + json5: 2.2.3 + minimatch: 9.0.5 + ow: 0.28.2 + stream-json: 1.9.1 + tldts: 6.1.84 + tough-cookie: 5.1.2 + tslib: 2.8.1 + type-fest: 4.37.0 + transitivePeerDependencies: + - supports-color + + '@crawlee/memory-storage@3.13.0': + dependencies: + '@apify/log': 2.5.14 + '@crawlee/types': 3.13.0 + '@sapphire/async-queue': 1.5.5 + '@sapphire/shapeshift': 3.9.7 + content-type: 1.0.5 + fs-extra: 11.3.0 + json5: 2.2.3 + mime-types: 2.1.35 + proper-lockfile: 4.1.2 + tslib: 2.8.1 + + '@crawlee/types@3.13.0': + dependencies: + tslib: 2.8.1 + + '@crawlee/utils@3.13.0': + dependencies: + '@apify/log': 2.5.14 + '@apify/ps-tree': 1.2.0 + '@crawlee/types': 3.13.0 + '@types/sax': 1.2.7 + cheerio: 1.0.0-rc.12 + file-type: 20.4.0 + got-scraping: 4.1.1 + ow: 0.28.2 + robots-parser: 3.0.1 + sax: 1.4.1 + tslib: 2.8.1 + whatwg-mimetype: 4.0.0 + transitivePeerDependencies: + - supports-color + + '@effect/schema@0.75.5(effect@3.14.2)': + dependencies: + effect: 3.14.2 + fast-check: 3.23.2 + + '@esbuild/aix-ppc64@0.25.1': + optional: true + + '@esbuild/android-arm64@0.25.1': + optional: true + + '@esbuild/android-arm@0.25.1': + optional: true + + '@esbuild/android-x64@0.25.1': + optional: true + + '@esbuild/darwin-arm64@0.25.1': + optional: true + + '@esbuild/darwin-x64@0.25.1': + optional: true + + '@esbuild/freebsd-arm64@0.25.1': + optional: true + + '@esbuild/freebsd-x64@0.25.1': + optional: true + + '@esbuild/linux-arm64@0.25.1': + optional: true + + '@esbuild/linux-arm@0.25.1': + optional: true + + '@esbuild/linux-ia32@0.25.1': + optional: true + + '@esbuild/linux-loong64@0.25.1': + optional: true + + '@esbuild/linux-mips64el@0.25.1': + optional: true + + '@esbuild/linux-ppc64@0.25.1': + optional: true + + '@esbuild/linux-riscv64@0.25.1': + optional: true + + '@esbuild/linux-s390x@0.25.1': + optional: true + + '@esbuild/linux-x64@0.25.1': + optional: true + + '@esbuild/netbsd-arm64@0.25.1': + optional: true + + '@esbuild/netbsd-x64@0.25.1': + optional: true - ansi-regex@6.1.0: {} + '@esbuild/openbsd-arm64@0.25.1': + optional: true - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 + '@esbuild/openbsd-x64@0.25.1': + optional: true - ansi-styles@6.2.1: {} + '@esbuild/sunos-x64@0.25.1': + optional: true - aproba@2.0.0: - optional: true + '@esbuild/win32-arm64@0.25.1': + optional: true - are-we-there-yet@2.0.0: - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.2 - optional: true + '@esbuild/win32-ia32@0.25.1': + optional: true - argparse@2.0.1: {} + '@esbuild/win32-x64@0.25.1': + optional: true - assertion-error@2.0.1: {} + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 - atomic-sleep@1.0.0: {} + '@jridgewell/sourcemap-codec@1.5.0': {} - balanced-match@1.0.2: {} + '@mapbox/node-pre-gyp@1.0.11': + dependencies: + detect-libc: 2.0.3 + https-proxy-agent: 5.0.1 + make-dir: 3.1.0 + node-fetch: 2.7.0 + nopt: 5.0.0 + npmlog: 5.0.1 + rimraf: 3.0.2 + semver: 7.7.1 + tar: 6.2.1 + transitivePeerDependencies: + - encoding + - supports-color + optional: true - base64-js@1.5.1: {} + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 - boolbase@1.0.0: {} + '@nodelib/fs.stat@2.0.5': {} - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 - brace-expansion@2.0.1: - dependencies: - balanced-match: 1.0.2 + '@qnaplus/node-curl-impersonate@1.0.1': {} - braces@3.0.3: - dependencies: - fill-range: 7.1.1 + '@rollup/rollup-android-arm-eabi@4.35.0': + optional: true - browserslist@4.24.4: - dependencies: - caniuse-lite: 1.0.30001703 - electron-to-chromium: 1.5.115 - node-releases: 2.0.19 - update-browserslist-db: 1.1.3(browserslist@4.24.4) + '@rollup/rollup-android-arm64@4.35.0': + optional: true - buffer@6.0.3: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 + '@rollup/rollup-darwin-arm64@4.35.0': + optional: true - cac@6.7.14: {} + '@rollup/rollup-darwin-x64@4.35.0': + optional: true - cacheable-lookup@7.0.0: {} + '@rollup/rollup-freebsd-arm64@4.35.0': + optional: true - cacheable-request@12.0.1: - dependencies: - "@types/http-cache-semantics": 4.0.4 - get-stream: 9.0.1 - http-cache-semantics: 4.1.1 - keyv: 4.5.4 - mimic-response: 4.0.0 - normalize-url: 8.0.1 - responselike: 3.0.0 + '@rollup/rollup-freebsd-x64@4.35.0': + optional: true - callsites@3.1.0: {} + '@rollup/rollup-linux-arm-gnueabihf@4.35.0': + optional: true - callsites@4.2.0: {} + '@rollup/rollup-linux-arm-musleabihf@4.35.0': + optional: true - caniuse-lite@1.0.30001703: {} + '@rollup/rollup-linux-arm64-gnu@4.35.0': + optional: true - canvas@2.11.2: - dependencies: - "@mapbox/node-pre-gyp": 1.0.11 - nan: 2.22.2 - simple-get: 3.1.1 - transitivePeerDependencies: - - encoding - - supports-color - optional: true + '@rollup/rollup-linux-arm64-musl@4.35.0': + optional: true - chai@5.2.0: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.1 - deep-eql: 5.0.2 - loupe: 3.1.3 - pathval: 2.0.0 - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - check-error@2.1.1: {} - - cheerio-select@2.1.0: - dependencies: - boolbase: 1.0.0 - css-select: 5.1.0 - css-what: 6.1.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.2.2 - - cheerio@1.0.0: - dependencies: - cheerio-select: 2.1.0 - dom-serializer: 2.0.0 - domhandler: 5.0.3 - domutils: 3.2.2 - encoding-sniffer: 0.2.0 - htmlparser2: 9.1.0 - parse5: 7.2.1 - parse5-htmlparser2-tree-adapter: 7.1.0 - parse5-parser-stream: 7.1.2 - undici: 6.21.1 - whatwg-mimetype: 4.0.0 - - cheerio@1.0.0-rc.12: - dependencies: - cheerio-select: 2.1.0 - dom-serializer: 2.0.0 - domhandler: 5.0.3 - domutils: 3.2.2 - htmlparser2: 8.0.2 - parse5: 7.2.1 - parse5-htmlparser2-tree-adapter: 7.1.0 - - chownr@2.0.0: - optional: true + '@rollup/rollup-linux-loongarch64-gnu@4.35.0': + optional: true - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 + '@rollup/rollup-linux-powerpc64le-gnu@4.35.0': + optional: true - color-name@1.1.4: {} + '@rollup/rollup-linux-riscv64-gnu@4.35.0': + optional: true - color-support@1.1.3: - optional: true + '@rollup/rollup-linux-s390x-gnu@4.35.0': + optional: true - colorette@2.0.20: {} + '@rollup/rollup-linux-x64-gnu@4.35.0': + optional: true - concat-map@0.0.1: {} + '@rollup/rollup-linux-x64-musl@4.35.0': + optional: true - console-control-strings@1.1.0: - optional: true + '@rollup/rollup-win32-arm64-msvc@4.35.0': + optional: true - content-type@1.0.5: {} + '@rollup/rollup-win32-ia32-msvc@4.35.0': + optional: true - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 + '@rollup/rollup-win32-x64-msvc@4.35.0': + optional: true - css-select@5.1.0: - dependencies: - boolbase: 1.0.0 - css-what: 6.1.0 - domhandler: 5.0.3 - domutils: 3.2.2 - nth-check: 2.1.1 + '@sapphire/async-queue@1.5.5': {} - css-what@6.1.0: {} + '@sapphire/shapeshift@3.9.7': + dependencies: + fast-deep-equal: 3.1.3 + lodash: 4.17.21 - csv-stringify@6.5.2: {} + '@sec-ant/readable-stream@0.4.1': {} - dateformat@4.6.3: {} + '@sindresorhus/is@4.6.0': {} - debug@4.4.0: - dependencies: - ms: 2.1.3 + '@sindresorhus/is@5.6.0': {} - decompress-response@4.2.1: - dependencies: - mimic-response: 2.1.0 - optional: true + '@sindresorhus/is@7.0.1': {} - decompress-response@6.0.0: - dependencies: - mimic-response: 3.1.0 + '@sindresorhus/merge-streams@2.3.0': {} - deep-eql@5.0.2: {} + '@standard-schema/spec@1.0.0': {} - deep-is@0.1.4: {} + '@szmarczak/http-timer@5.0.1': + dependencies: + defer-to-connect: 2.0.1 - defer-to-connect@2.0.1: {} + '@tokenizer/inflate@0.2.7': + dependencies: + debug: 4.4.0 + fflate: 0.8.2 + token-types: 6.0.0 + transitivePeerDependencies: + - supports-color - delegates@1.0.0: - optional: true + '@tokenizer/token@0.3.0': {} - detect-libc@2.0.3: - optional: true + '@types/estree@1.0.6': {} - dom-serializer@2.0.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - - domelementtype@2.3.0: {} - - domhandler@5.0.3: - dependencies: - domelementtype: 2.3.0 - - domutils@3.2.2: - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - - dot-prop@6.0.1: - dependencies: - is-obj: 2.0.0 - - dot-prop@7.2.0: - dependencies: - type-fest: 2.19.0 - - duplexer@0.1.2: {} - - eastasianwidth@0.2.0: {} - - electron-to-chromium@1.5.115: {} - - emoji-regex@8.0.0: {} - - emoji-regex@9.2.2: {} - - encoding-sniffer@0.2.0: - dependencies: - iconv-lite: 0.6.3 - whatwg-encoding: 3.1.1 - - end-of-stream@1.4.4: - dependencies: - once: 1.4.0 - - entities@4.5.0: {} - - es-module-lexer@1.6.0: {} - - esbuild@0.25.1: - optionalDependencies: - "@esbuild/aix-ppc64": 0.25.1 - "@esbuild/android-arm": 0.25.1 - "@esbuild/android-arm64": 0.25.1 - "@esbuild/android-x64": 0.25.1 - "@esbuild/darwin-arm64": 0.25.1 - "@esbuild/darwin-x64": 0.25.1 - "@esbuild/freebsd-arm64": 0.25.1 - "@esbuild/freebsd-x64": 0.25.1 - "@esbuild/linux-arm": 0.25.1 - "@esbuild/linux-arm64": 0.25.1 - "@esbuild/linux-ia32": 0.25.1 - "@esbuild/linux-loong64": 0.25.1 - "@esbuild/linux-mips64el": 0.25.1 - "@esbuild/linux-ppc64": 0.25.1 - "@esbuild/linux-riscv64": 0.25.1 - "@esbuild/linux-s390x": 0.25.1 - "@esbuild/linux-x64": 0.25.1 - "@esbuild/netbsd-arm64": 0.25.1 - "@esbuild/netbsd-x64": 0.25.1 - "@esbuild/openbsd-arm64": 0.25.1 - "@esbuild/openbsd-x64": 0.25.1 - "@esbuild/sunos-x64": 0.25.1 - "@esbuild/win32-arm64": 0.25.1 - "@esbuild/win32-ia32": 0.25.1 - "@esbuild/win32-x64": 0.25.1 - - escalade@3.2.0: {} - - escape-string-regexp@4.0.0: {} - - eslint-scope@8.3.0: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint-visitor-keys@4.2.0: {} - - eslint@9.22.0: - dependencies: - "@eslint-community/eslint-utils": 4.5.0(eslint@9.22.0) - "@eslint-community/regexpp": 4.12.1 - "@eslint/config-array": 0.19.2 - "@eslint/config-helpers": 0.1.0 - "@eslint/core": 0.12.0 - "@eslint/eslintrc": 3.3.0 - "@eslint/js": 9.22.0 - "@eslint/plugin-kit": 0.2.7 - "@humanfs/node": 0.16.6 - "@humanwhocodes/module-importer": 1.0.1 - "@humanwhocodes/retry": 0.4.2 - "@types/estree": 1.0.6 - "@types/json-schema": 7.0.15 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.0 - escape-string-regexp: 4.0.0 - eslint-scope: 8.3.0 - eslint-visitor-keys: 4.2.0 - espree: 10.3.0 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - transitivePeerDependencies: - - supports-color - - espree@10.3.0: - dependencies: - acorn: 8.14.1 - acorn-jsx: 5.3.2(acorn@8.14.1) - eslint-visitor-keys: 4.2.0 - - esquery@1.6.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - - estree-walker@3.0.3: - dependencies: - "@types/estree": 1.0.6 - - esutils@2.0.3: {} - - event-stream@3.3.4: - dependencies: - duplexer: 0.1.2 - from: 0.1.7 - map-stream: 0.1.0 - pause-stream: 0.0.11 - split: 0.3.3 - stream-combiner: 0.0.4 - through: 2.3.8 - - event-target-shim@5.0.1: {} - - events@3.3.0: {} - - expect-type@1.2.0: {} - - fast-copy@3.0.2: {} - - fast-deep-equal@3.1.3: {} - - fast-glob@3.3.3: - dependencies: - "@nodelib/fs.stat": 2.0.5 - "@nodelib/fs.walk": 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fast-redact@3.5.0: {} - - fast-safe-stringify@2.1.1: {} - - fastq@1.19.1: - dependencies: - reusify: 1.1.0 - - fflate@0.8.2: {} - - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 - - file-type@20.4.0: - dependencies: - "@tokenizer/inflate": 0.2.7 - strtok3: 10.2.2 - token-types: 6.0.0 - uint8array-extras: 1.4.0 - transitivePeerDependencies: - - supports-color - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat-cache@4.0.1: - dependencies: - flatted: 3.3.3 - keyv: 4.5.4 + '@types/http-cache-semantics@4.0.4': {} - flatted@3.3.3: {} + '@types/node@20.17.27': + dependencies: + undici-types: 6.19.8 - foreground-child@3.3.1: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 + '@types/node@22.13.10': + dependencies: + undici-types: 6.20.0 - form-data-encoder@4.0.2: {} + '@types/sax@1.2.7': + dependencies: + '@types/node': 22.13.10 - from@0.1.7: {} + '@vitest/expect@3.0.8': + dependencies: + '@vitest/spy': 3.0.8 + '@vitest/utils': 3.0.8 + chai: 5.2.0 + tinyrainbow: 2.0.0 - fs-extra@11.3.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 + '@vitest/mocker@3.0.8(vite@6.2.1(@types/node@22.13.10))': + dependencies: + '@vitest/spy': 3.0.8 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 6.2.1(@types/node@22.13.10) - fs-minipass@2.1.0: - dependencies: - minipass: 3.3.6 - optional: true + '@vitest/pretty-format@3.0.8': + dependencies: + tinyrainbow: 2.0.0 - fs.realpath@1.0.0: - optional: true + '@vitest/runner@3.0.8': + dependencies: + '@vitest/utils': 3.0.8 + pathe: 2.0.3 - fsevents@2.3.3: - optional: true + '@vitest/snapshot@3.0.8': + dependencies: + '@vitest/pretty-format': 3.0.8 + magic-string: 0.30.17 + pathe: 2.0.3 - gauge@3.0.2: - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - object-assign: 4.1.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - optional: true + '@vitest/spy@3.0.8': + dependencies: + tinyspy: 3.0.2 - generative-bayesian-network@2.1.62: - dependencies: - adm-zip: 0.5.16 - tslib: 2.8.1 - - get-stream@9.0.1: - dependencies: - "@sec-ant/readable-stream": 0.4.1 - is-stream: 4.0.1 - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - - glob@11.0.1: - dependencies: - foreground-child: 3.3.1 - jackspeak: 4.1.0 - minimatch: 10.0.1 - minipass: 7.1.2 - package-json-from-dist: 1.0.1 - path-scurry: 2.0.0 - - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - optional: true + '@vitest/utils@3.0.8': + dependencies: + '@vitest/pretty-format': 3.0.8 + loupe: 3.1.3 + tinyrainbow: 2.0.0 - globals@14.0.0: {} - - got-scraping@4.1.1: - dependencies: - got: 14.4.6 - header-generator: 2.1.62 - http2-wrapper: 2.2.1 - mimic-response: 4.0.0 - ow: 1.1.1 - quick-lru: 7.0.0 - tslib: 2.8.1 - - got@14.4.6: - dependencies: - "@sindresorhus/is": 7.0.1 - "@szmarczak/http-timer": 5.0.1 - cacheable-lookup: 7.0.0 - cacheable-request: 12.0.1 - decompress-response: 6.0.0 - form-data-encoder: 4.0.2 - http2-wrapper: 2.2.1 - lowercase-keys: 3.0.0 - p-cancelable: 4.0.1 - responselike: 3.0.0 - type-fest: 4.37.0 - - graceful-fs@4.2.11: {} - - graphemer@1.4.0: {} - - has-flag@4.0.0: {} - - has-unicode@2.0.1: - optional: true + '@vladfrangu/async_event_emitter@2.4.6': {} - header-generator@2.1.62: - dependencies: - browserslist: 4.24.4 - generative-bayesian-network: 2.1.62 - ow: 0.28.2 - tslib: 2.8.1 - - help-me@5.0.0: {} - - htmlparser2@8.0.2: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.2.2 - entities: 4.5.0 - - htmlparser2@9.1.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.2.2 - entities: 4.5.0 - - http-cache-semantics@4.1.1: {} - - http2-wrapper@2.2.1: - dependencies: - quick-lru: 5.1.1 - resolve-alpn: 1.2.1 - - https-proxy-agent@5.0.1: - dependencies: - agent-base: 6.0.2 - debug: 4.4.0 - transitivePeerDependencies: - - supports-color - optional: true + abbrev@1.1.1: + optional: true - iconv-lite@0.6.3: - dependencies: - safer-buffer: 2.1.2 + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 - ieee754@1.2.1: {} + adm-zip@0.5.16: {} - ignore@5.3.2: {} + agent-base@6.0.2: + dependencies: + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + optional: true - import-fresh@3.3.1: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 + ansi-colors@4.1.3: {} - imurmurhash@0.1.4: {} + ansi-regex@5.0.1: {} - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - optional: true + ansi-regex@6.1.0: {} - inherits@2.0.4: - optional: true + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 - is-extglob@2.1.1: {} + ansi-styles@6.2.1: {} - is-fullwidth-code-point@3.0.0: {} + aproba@2.0.0: + optional: true - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 + are-we-there-yet@2.0.0: + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + optional: true - is-number@7.0.0: {} + argparse@2.0.1: {} - is-obj@2.0.0: {} + assertion-error@2.0.1: {} - is-stream@4.0.1: {} + asynckit@0.4.0: {} + + atomic-sleep@1.0.0: {} + + balanced-match@1.0.2: {} + + base64-js@1.5.1: {} + + boolbase@1.0.0: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + optional: true + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.24.4: + dependencies: + caniuse-lite: 1.0.30001703 + electron-to-chromium: 1.5.115 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.4) + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + cac@6.7.14: {} + + cacheable-lookup@7.0.0: {} - isexe@2.0.0: {} + cacheable-request@12.0.1: + dependencies: + '@types/http-cache-semantics': 4.0.4 + get-stream: 9.0.1 + http-cache-semantics: 4.1.1 + keyv: 4.5.4 + mimic-response: 4.0.0 + normalize-url: 8.0.1 + responselike: 3.0.0 - jackspeak@4.1.0: - dependencies: - "@isaacs/cliui": 8.0.2 + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 - joycon@3.1.1: {} + callsites@3.1.0: {} - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 + callsites@4.2.0: {} - json-buffer@3.0.1: {} + caniuse-lite@1.0.30001703: {} - json-schema-traverse@0.4.1: {} + canvas@2.11.2: + dependencies: + '@mapbox/node-pre-gyp': 1.0.11 + nan: 2.22.2 + simple-get: 3.1.1 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + chai@5.2.0: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.3 + pathval: 2.0.0 + + chalk-template@1.1.0: + dependencies: + chalk: 5.4.1 + + chalk@5.4.1: {} + + check-error@2.1.1: {} + + cheerio-select@2.1.0: + dependencies: + boolbase: 1.0.0 + css-select: 5.1.0 + css-what: 6.1.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + + cheerio@1.0.0: + dependencies: + cheerio-select: 2.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + domutils: 3.2.2 + encoding-sniffer: 0.2.0 + htmlparser2: 9.1.0 + parse5: 7.2.1 + parse5-htmlparser2-tree-adapter: 7.1.0 + parse5-parser-stream: 7.1.2 + undici: 6.21.1 + whatwg-mimetype: 4.0.0 + + cheerio@1.0.0-rc.12: + dependencies: + cheerio-select: 2.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + domutils: 3.2.2 + htmlparser2: 8.0.2 + parse5: 7.2.1 + parse5-htmlparser2-tree-adapter: 7.1.0 + + chownr@2.0.0: + optional: true + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-spinners@2.9.2: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + color-support@1.1.3: + optional: true + + colorette@2.0.20: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@13.1.0: {} + + concat-map@0.0.1: + optional: true + + console-control-strings@1.1.0: + optional: true + + content-type@1.0.5: {} + + cosmiconfig@9.0.0(typescript@5.5.4): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.5.4 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css-select@5.1.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 - json-stable-stringify-without-jsonify@1.0.1: {} + css-what@6.1.0: {} - json5@2.2.3: {} + csv-stringify@6.5.2: {} - jsonfile@6.1.0: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 + cycletls@1.0.27: + dependencies: + '@types/node': 20.17.27 + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 + dateformat@4.6.3: {} - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 + debug@4.4.0: + dependencies: + ms: 2.1.3 - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 + decompress-response@4.2.1: + dependencies: + mimic-response: 2.1.0 + optional: true - lodash.isequal@4.5.0: {} + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 - lodash.merge@4.6.2: {} + deep-eql@5.0.2: {} - lodash@4.17.21: {} + defer-to-connect@2.0.1: {} - loupe@3.1.3: {} + delayed-stream@1.0.0: {} - lowercase-keys@3.0.0: {} + delegates@1.0.0: + optional: true - lru-cache@11.0.2: {} + detect-libc@2.0.3: + optional: true - magic-string@0.30.17: - dependencies: - "@jridgewell/sourcemap-codec": 1.5.0 + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 - make-dir@3.1.0: - dependencies: - semver: 6.3.1 - optional: true + domelementtype@2.3.0: {} - map-stream@0.1.0: {} + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 - merge2@1.4.1: {} + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 + dot-prop@6.0.1: + dependencies: + is-obj: 2.0.0 - mime-db@1.52.0: {} + dot-prop@7.2.0: + dependencies: + type-fest: 2.19.0 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + duplexer@0.1.2: {} + + eastasianwidth@0.2.0: {} + + effect@3.14.2: + dependencies: + '@standard-schema/spec': 1.0.0 + fast-check: 3.23.2 + + electron-to-chromium@1.5.115: {} + + emoji-regex@10.4.0: {} + + emoji-regex@8.0.0: {} - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 + emoji-regex@9.2.2: {} + + encoding-sniffer@0.2.0: + dependencies: + iconv-lite: 0.6.3 + whatwg-encoding: 3.1.1 + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 - mimic-response@2.1.0: - optional: true + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 - mimic-response@3.1.0: {} + entities@4.5.0: {} - mimic-response@4.0.0: {} + env-paths@2.2.1: {} - minimatch@10.0.1: - dependencies: - brace-expansion: 2.0.1 + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 + es-define-property@1.0.1: {} - minimatch@9.0.5: - dependencies: - brace-expansion: 2.0.1 + es-errors@1.3.0: {} - minimist@1.2.8: {} + es-module-lexer@1.6.0: {} - minipass@3.3.6: - dependencies: - yallist: 4.0.0 - optional: true + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 - minipass@5.0.0: - optional: true + esbuild@0.25.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.1 + '@esbuild/android-arm': 0.25.1 + '@esbuild/android-arm64': 0.25.1 + '@esbuild/android-x64': 0.25.1 + '@esbuild/darwin-arm64': 0.25.1 + '@esbuild/darwin-x64': 0.25.1 + '@esbuild/freebsd-arm64': 0.25.1 + '@esbuild/freebsd-x64': 0.25.1 + '@esbuild/linux-arm': 0.25.1 + '@esbuild/linux-arm64': 0.25.1 + '@esbuild/linux-ia32': 0.25.1 + '@esbuild/linux-loong64': 0.25.1 + '@esbuild/linux-mips64el': 0.25.1 + '@esbuild/linux-ppc64': 0.25.1 + '@esbuild/linux-riscv64': 0.25.1 + '@esbuild/linux-s390x': 0.25.1 + '@esbuild/linux-x64': 0.25.1 + '@esbuild/netbsd-arm64': 0.25.1 + '@esbuild/netbsd-x64': 0.25.1 + '@esbuild/openbsd-arm64': 0.25.1 + '@esbuild/openbsd-x64': 0.25.1 + '@esbuild/sunos-x64': 0.25.1 + '@esbuild/win32-arm64': 0.25.1 + '@esbuild/win32-ia32': 0.25.1 + '@esbuild/win32-x64': 0.25.1 + + escalade@3.2.0: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.6 + + event-stream@3.3.4: + dependencies: + duplexer: 0.1.2 + from: 0.1.7 + map-stream: 0.1.0 + pause-stream: 0.0.11 + split: 0.3.3 + stream-combiner: 0.0.4 + through: 2.3.8 + + event-target-shim@5.0.1: {} + + events@3.3.0: {} + + expect-type@1.2.0: {} + + fast-check@3.23.2: + dependencies: + pure-rand: 6.1.0 + + fast-copy@3.0.2: {} + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-redact@3.5.0: {} + + fast-safe-stringify@2.1.1: {} + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + + fflate@0.8.2: {} + + file-type@20.4.0: + dependencies: + '@tokenizer/inflate': 0.2.7 + strtok3: 10.2.2 + token-types: 6.0.0 + uint8array-extras: 1.4.0 + transitivePeerDependencies: + - supports-color + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data-encoder@4.0.2: {} + + form-data@4.0.2: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + + from@0.1.7: {} + + fs-extra@11.3.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-minipass@2.1.0: + dependencies: + minipass: 3.3.6 + optional: true + + fs.realpath@1.0.0: + optional: true + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gauge@3.0.2: + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + optional: true + + generative-bayesian-network@2.1.62: + dependencies: + adm-zip: 0.5.16 + tslib: 2.8.1 + + get-east-asian-width@1.3.0: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@9.0.1: + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob@11.0.1: + dependencies: + foreground-child: 3.3.1 + jackspeak: 4.1.0 + minimatch: 10.0.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.0 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + optional: true + + globby@14.1.0: + dependencies: + '@sindresorhus/merge-streams': 2.3.0 + fast-glob: 3.3.3 + ignore: 7.0.3 + path-type: 6.0.0 + slash: 5.1.0 + unicorn-magic: 0.3.0 + + gopd@1.2.0: {} + + got-scraping@4.1.1: + dependencies: + got: 14.4.6 + header-generator: 2.1.62 + http2-wrapper: 2.2.1 + mimic-response: 4.0.0 + ow: 1.1.1 + quick-lru: 7.0.0 + tslib: 2.8.1 + + got@14.4.6: + dependencies: + '@sindresorhus/is': 7.0.1 + '@szmarczak/http-timer': 5.0.1 + cacheable-lookup: 7.0.0 + cacheable-request: 12.0.1 + decompress-response: 6.0.0 + form-data-encoder: 4.0.2 + http2-wrapper: 2.2.1 + lowercase-keys: 3.0.0 + p-cancelable: 4.0.1 + responselike: 3.0.0 + type-fest: 4.37.0 + + graceful-fs@4.2.11: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + has-unicode@2.0.1: + optional: true + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + header-generator@2.1.62: + dependencies: + browserslist: 4.24.4 + generative-bayesian-network: 2.1.62 + ow: 0.28.2 + tslib: 2.8.1 + + help-me@5.0.0: {} + + hosted-git-info@8.0.2: + dependencies: + lru-cache: 10.4.3 + + htmlparser2@8.0.2: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 4.5.0 - minipass@7.1.2: {} + htmlparser2@9.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 4.5.0 - minizlib@2.1.2: - dependencies: - minipass: 3.3.6 - yallist: 4.0.0 - optional: true + http-cache-semantics@4.1.1: {} - mkdirp@1.0.4: - optional: true + http2-wrapper@2.2.1: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 - ms@2.1.3: {} + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + optional: true - nan@2.22.2: - optional: true + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 - nanoid@3.3.9: {} + ieee754@1.2.1: {} - natural-compare@1.4.0: {} + ignore@7.0.3: {} - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - optional: true + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 - node-pdf-parser@1.0.3: - dependencies: - pdfjs-dist: 3.11.174 - transitivePeerDependencies: - - encoding - - supports-color + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + optional: true - node-releases@2.0.19: {} + inherits@2.0.4: + optional: true - nopt@5.0.0: - dependencies: - abbrev: 1.1.1 - optional: true + is-arrayish@0.2.1: {} - normalize-url@8.0.1: {} + is-extglob@2.1.1: {} - npmlog@5.0.1: - dependencies: - are-we-there-yet: 2.0.0 - console-control-strings: 1.1.0 - gauge: 3.0.2 - set-blocking: 2.0.0 - optional: true + is-fullwidth-code-point@3.0.0: {} - nth-check@2.1.1: - dependencies: - boolbase: 1.0.0 + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 - object-assign@4.1.1: - optional: true + is-interactive@2.0.0: {} - on-exit-leak-free@2.1.2: {} - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - - ow@0.28.2: - dependencies: - "@sindresorhus/is": 4.6.0 - callsites: 3.1.0 - dot-prop: 6.0.1 - lodash.isequal: 4.5.0 - vali-date: 1.0.0 - - ow@1.1.1: - dependencies: - "@sindresorhus/is": 5.6.0 - callsites: 4.2.0 - dot-prop: 7.2.0 - lodash.isequal: 4.5.0 - vali-date: 1.0.0 - - p-cancelable@4.0.1: {} - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - package-json-from-dist@1.0.1: {} - - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - parse5-htmlparser2-tree-adapter@7.1.0: - dependencies: - domhandler: 5.0.3 - parse5: 7.2.1 - - parse5-parser-stream@7.1.2: - dependencies: - parse5: 7.2.1 - - parse5@7.2.1: - dependencies: - entities: 4.5.0 - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: - optional: true + is-number@7.0.0: {} - path-key@3.1.1: {} + is-obj@2.0.0: {} - path-scurry@2.0.0: - dependencies: - lru-cache: 11.0.2 - minipass: 7.1.2 + is-stream@4.0.1: {} - path2d-polyfill@2.0.1: - optional: true + is-unicode-supported@1.3.0: {} - pathe@2.0.3: {} - - pathval@2.0.0: {} - - pause-stream@0.0.11: - dependencies: - through: 2.3.8 - - pdfjs-dist@3.11.174: - optionalDependencies: - canvas: 2.11.2 - path2d-polyfill: 2.0.1 - transitivePeerDependencies: - - encoding - - supports-color - - peek-readable@7.0.0: {} - - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - pino-abstract-transport@2.0.0: - dependencies: - split2: 4.2.0 - - pino-pretty@11.3.0: - dependencies: - colorette: 2.0.20 - dateformat: 4.6.3 - fast-copy: 3.0.2 - fast-safe-stringify: 2.1.1 - help-me: 5.0.0 - joycon: 3.1.1 - minimist: 1.2.8 - on-exit-leak-free: 2.1.2 - pino-abstract-transport: 2.0.0 - pump: 3.0.2 - readable-stream: 4.7.0 - secure-json-parse: 2.7.0 - sonic-boom: 4.2.0 - strip-json-comments: 3.1.1 - - pino-std-serializers@7.0.0: {} - - pino@9.6.0: - dependencies: - atomic-sleep: 1.0.0 - fast-redact: 3.5.0 - on-exit-leak-free: 2.1.2 - pino-abstract-transport: 2.0.0 - pino-std-serializers: 7.0.0 - process-warning: 4.0.1 - quick-format-unescaped: 4.0.4 - real-require: 0.2.0 - safe-stable-stringify: 2.5.0 - sonic-boom: 4.2.0 - thread-stream: 3.1.0 - - postcss@8.5.3: - dependencies: - nanoid: 3.3.9 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - prelude-ls@1.2.1: {} - - prettier@3.5.3: {} - - process-warning@4.0.1: {} - - process@0.11.10: {} - - proper-lockfile@4.1.2: - dependencies: - graceful-fs: 4.2.11 - retry: 0.12.0 - signal-exit: 3.0.7 - - pump@3.0.2: - dependencies: - end-of-stream: 1.4.4 - once: 1.4.0 - - punycode@2.3.1: {} - - queue-microtask@1.2.3: {} - - quick-format-unescaped@4.0.4: {} - - quick-lru@5.1.1: {} - - quick-lru@7.0.0: {} - - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - optional: true + is-unicode-supported@2.1.0: {} - readable-stream@4.7.0: - dependencies: - abort-controller: 3.0.0 - buffer: 6.0.3 - events: 3.3.0 - process: 0.11.10 - string_decoder: 1.3.0 + isexe@2.0.0: {} - real-require@0.2.0: {} + jackspeak@4.1.0: + dependencies: + '@isaacs/cliui': 8.0.2 - resolve-alpn@1.2.1: {} + joycon@3.1.1: {} - resolve-from@4.0.0: {} + js-tokens@4.0.0: {} - responselike@3.0.0: - dependencies: - lowercase-keys: 3.0.0 + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 - retry@0.12.0: {} + json-buffer@3.0.1: {} - reusify@1.1.0: {} + json-parse-even-better-errors@2.3.1: {} - rimraf@3.0.2: - dependencies: - glob: 7.2.3 - optional: true + json5@2.2.3: {} - rimraf@6.0.1: - dependencies: - glob: 11.0.1 - package-json-from-dist: 1.0.1 - - robots-parser@3.0.1: {} - - rollup@4.35.0: - dependencies: - "@types/estree": 1.0.6 - optionalDependencies: - "@rollup/rollup-android-arm-eabi": 4.35.0 - "@rollup/rollup-android-arm64": 4.35.0 - "@rollup/rollup-darwin-arm64": 4.35.0 - "@rollup/rollup-darwin-x64": 4.35.0 - "@rollup/rollup-freebsd-arm64": 4.35.0 - "@rollup/rollup-freebsd-x64": 4.35.0 - "@rollup/rollup-linux-arm-gnueabihf": 4.35.0 - "@rollup/rollup-linux-arm-musleabihf": 4.35.0 - "@rollup/rollup-linux-arm64-gnu": 4.35.0 - "@rollup/rollup-linux-arm64-musl": 4.35.0 - "@rollup/rollup-linux-loongarch64-gnu": 4.35.0 - "@rollup/rollup-linux-powerpc64le-gnu": 4.35.0 - "@rollup/rollup-linux-riscv64-gnu": 4.35.0 - "@rollup/rollup-linux-s390x-gnu": 4.35.0 - "@rollup/rollup-linux-x64-gnu": 4.35.0 - "@rollup/rollup-linux-x64-musl": 4.35.0 - "@rollup/rollup-win32-arm64-msvc": 4.35.0 - "@rollup/rollup-win32-ia32-msvc": 4.35.0 - "@rollup/rollup-win32-x64-msvc": 4.35.0 - fsevents: 2.3.3 - - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - - safe-buffer@5.2.1: {} - - safe-stable-stringify@2.5.0: {} - - safer-buffer@2.1.2: {} - - sax@1.4.1: {} - - secure-json-parse@2.7.0: {} - - semver@6.3.1: - optional: true + jsonc-parser@3.3.1: {} - semver@7.7.1: {} + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 - set-blocking@2.0.0: - optional: true + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 + kleur@3.0.3: {} - shebang-regex@3.0.0: {} + lines-and-columns@1.2.4: {} - siginfo@2.0.0: {} + lodash.isequal@4.5.0: {} - signal-exit@3.0.7: {} + lodash@4.17.21: {} - signal-exit@4.1.0: {} + log-symbols@6.0.0: + dependencies: + chalk: 5.4.1 + is-unicode-supported: 1.3.0 - simple-concat@1.0.1: - optional: true + loupe@3.1.3: {} - simple-get@3.1.1: - dependencies: - decompress-response: 4.2.1 - once: 1.4.0 - simple-concat: 1.0.1 - optional: true + lowercase-keys@3.0.0: {} - sonic-boom@4.2.0: - dependencies: - atomic-sleep: 1.0.0 + lru-cache@10.4.3: {} - source-map-js@1.2.1: {} + lru-cache@11.0.2: {} - split2@4.2.0: {} + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 - split@0.3.3: - dependencies: - through: 2.3.8 + make-dir@3.1.0: + dependencies: + semver: 6.3.1 + optional: true - stackback@0.0.2: {} + map-stream@0.1.0: {} - std-env@3.8.1: {} + math-intrinsics@1.1.0: {} - stream-chain@2.2.5: {} + merge2@1.4.1: {} - stream-combiner@0.0.4: - dependencies: - duplexer: 0.1.2 + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 - stream-json@1.9.1: - dependencies: - stream-chain: 2.2.5 + mime-db@1.52.0: {} - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 - string-width@5.1.2: - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 + mimic-function@5.0.1: {} - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 + mimic-response@2.1.0: + optional: true - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 + mimic-response@3.1.0: {} - strip-ansi@7.1.0: - dependencies: - ansi-regex: 6.1.0 + mimic-response@4.0.0: {} - strip-json-comments@3.1.1: {} + minimatch@10.0.1: + dependencies: + brace-expansion: 2.0.1 - strtok3@10.2.2: - dependencies: - "@tokenizer/token": 0.3.0 - peek-readable: 7.0.0 + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + optional: true - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 - tar@6.2.1: - dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - optional: true + minimist@1.2.8: {} - thread-stream@3.1.0: - dependencies: - real-require: 0.2.0 + minipass@3.3.6: + dependencies: + yallist: 4.0.0 + optional: true - through@2.3.8: {} + minipass@5.0.0: + optional: true - tinybench@2.9.0: {} + minipass@7.1.2: {} - tinyexec@0.3.2: {} + minizlib@2.1.2: + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + optional: true - tinypool@1.0.2: {} + mkdirp@1.0.4: + optional: true - tinyrainbow@2.0.0: {} + ms@2.1.3: {} - tinyspy@3.0.2: {} + nan@2.22.2: + optional: true - tldts-core@6.1.84: {} + nanoid@3.3.9: {} - tldts@6.1.84: - dependencies: - tldts-core: 6.1.84 + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + optional: true - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 + node-pdf-parser@1.0.3: + dependencies: + pdfjs-dist: 3.11.174 + transitivePeerDependencies: + - encoding + - supports-color - token-types@6.0.0: - dependencies: - "@tokenizer/token": 0.3.0 - ieee754: 1.2.1 + node-releases@2.0.19: {} - tough-cookie@5.1.2: - dependencies: - tldts: 6.1.84 + nopt@5.0.0: + dependencies: + abbrev: 1.1.1 + optional: true - tr46@0.0.3: - optional: true + normalize-url@8.0.1: {} - ts-api-utils@2.0.1(typescript@5.5.4): - dependencies: - typescript: 5.5.4 + npm-package-arg@12.0.2: + dependencies: + hosted-git-info: 8.0.2 + proc-log: 5.0.0 + semver: 7.7.1 + validate-npm-package-name: 6.0.0 - tslib@2.8.1: {} + npmlog@5.0.1: + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 3.0.2 + set-blocking: 2.0.0 + optional: true - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 - type-fest@2.19.0: {} + object-assign@4.1.1: + optional: true - type-fest@4.37.0: {} + on-exit-leak-free@2.1.2: {} - typescript-eslint@8.26.1(eslint@9.22.0)(typescript@5.5.4): - dependencies: - "@typescript-eslint/eslint-plugin": 8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.5.4))(eslint@9.22.0)(typescript@5.5.4) - "@typescript-eslint/parser": 8.26.1(eslint@9.22.0)(typescript@5.5.4) - "@typescript-eslint/utils": 8.26.1(eslint@9.22.0)(typescript@5.5.4) - eslint: 9.22.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color + once@1.4.0: + dependencies: + wrappy: 1.0.2 - typescript@5.5.4: {} + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 - uint8array-extras@1.4.0: {} + ora@8.2.0: + dependencies: + chalk: 5.4.1 + cli-cursor: 5.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 2.1.0 + log-symbols: 6.0.0 + stdin-discarder: 0.2.2 + string-width: 7.2.0 + strip-ansi: 7.1.0 + + ow@0.28.2: + dependencies: + '@sindresorhus/is': 4.6.0 + callsites: 3.1.0 + dot-prop: 6.0.1 + lodash.isequal: 4.5.0 + vali-date: 1.0.0 + + ow@1.1.1: + dependencies: + '@sindresorhus/is': 5.6.0 + callsites: 4.2.0 + dot-prop: 7.2.0 + lodash.isequal: 4.5.0 + vali-date: 1.0.0 + + p-cancelable@4.0.1: {} + + package-json-from-dist@1.0.1: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.26.2 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse5-htmlparser2-tree-adapter@7.1.0: + dependencies: + domhandler: 5.0.3 + parse5: 7.2.1 + + parse5-parser-stream@7.1.2: + dependencies: + parse5: 7.2.1 + + parse5@7.2.1: + dependencies: + entities: 4.5.0 + + path-is-absolute@1.0.1: + optional: true + + path-key@3.1.1: {} + + path-scurry@2.0.0: + dependencies: + lru-cache: 11.0.2 + minipass: 7.1.2 + + path-type@6.0.0: {} + + path2d-polyfill@2.0.1: + optional: true + + pathe@2.0.3: {} + + pathval@2.0.0: {} + + pause-stream@0.0.11: + dependencies: + through: 2.3.8 + + pdfjs-dist@3.11.174: + optionalDependencies: + canvas: 2.11.2 + path2d-polyfill: 2.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + peek-readable@7.0.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-pretty@11.3.0: + dependencies: + colorette: 2.0.20 + dateformat: 4.6.3 + fast-copy: 3.0.2 + fast-safe-stringify: 2.1.1 + help-me: 5.0.0 + joycon: 3.1.1 + minimist: 1.2.8 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pump: 3.0.2 + readable-stream: 4.7.0 + secure-json-parse: 2.7.0 + sonic-boom: 4.2.0 + strip-json-comments: 3.1.1 + + pino-std-serializers@7.0.0: {} + + pino@9.6.0: + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.0.0 + process-warning: 4.0.1 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.0 + thread-stream: 3.1.0 + + postcss@8.5.3: + dependencies: + nanoid: 3.3.9 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + proc-log@5.0.0: {} + + process-warning@4.0.1: {} + + process@0.11.10: {} + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + proper-lockfile@4.1.2: + dependencies: + graceful-fs: 4.2.11 + retry: 0.12.0 + signal-exit: 3.0.7 + + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + pure-rand@6.1.0: {} + + queue-microtask@1.2.3: {} + + quick-format-unescaped@4.0.4: {} + + quick-lru@5.1.1: {} + + quick-lru@7.0.0: {} + + read-yaml-file@2.1.0: + dependencies: + js-yaml: 4.1.0 + strip-bom: 4.0.0 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + optional: true + + readable-stream@4.7.0: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + + real-require@0.2.0: {} + + resolve-alpn@1.2.1: {} + + resolve-from@4.0.0: {} + + responselike@3.0.0: + dependencies: + lowercase-keys: 3.0.0 + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 - undici-types@6.20.0: {} + retry@0.12.0: {} - undici@6.21.1: {} + reusify@1.1.0: {} - universalify@2.0.1: {} + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + optional: true - update-browserslist-db@1.1.3(browserslist@4.24.4): - dependencies: - browserslist: 4.24.4 - escalade: 3.2.0 - picocolors: 1.1.1 + rimraf@6.0.1: + dependencies: + glob: 11.0.1 + package-json-from-dist: 1.0.1 - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 + robots-parser@3.0.1: {} - util-deprecate@1.0.2: - optional: true + rollup@4.35.0: + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.35.0 + '@rollup/rollup-android-arm64': 4.35.0 + '@rollup/rollup-darwin-arm64': 4.35.0 + '@rollup/rollup-darwin-x64': 4.35.0 + '@rollup/rollup-freebsd-arm64': 4.35.0 + '@rollup/rollup-freebsd-x64': 4.35.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.35.0 + '@rollup/rollup-linux-arm-musleabihf': 4.35.0 + '@rollup/rollup-linux-arm64-gnu': 4.35.0 + '@rollup/rollup-linux-arm64-musl': 4.35.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.35.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.35.0 + '@rollup/rollup-linux-riscv64-gnu': 4.35.0 + '@rollup/rollup-linux-s390x-gnu': 4.35.0 + '@rollup/rollup-linux-x64-gnu': 4.35.0 + '@rollup/rollup-linux-x64-musl': 4.35.0 + '@rollup/rollup-win32-arm64-msvc': 4.35.0 + '@rollup/rollup-win32-ia32-msvc': 4.35.0 + '@rollup/rollup-win32-x64-msvc': 4.35.0 + fsevents: 2.3.3 - vali-date@1.0.0: {} - - vite-node@3.0.8(@types/node@22.13.10): - dependencies: - cac: 6.7.14 - debug: 4.4.0 - es-module-lexer: 1.6.0 - pathe: 2.0.3 - vite: 6.2.1(@types/node@22.13.10) - transitivePeerDependencies: - - "@types/node" - - jiti - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - - vite@6.2.1(@types/node@22.13.10): - dependencies: - esbuild: 0.25.1 - postcss: 8.5.3 - rollup: 4.35.0 - optionalDependencies: - "@types/node": 22.13.10 - fsevents: 2.3.3 - - vitest@3.0.8(@types/node@22.13.10): - dependencies: - "@vitest/expect": 3.0.8 - "@vitest/mocker": 3.0.8(vite@6.2.1(@types/node@22.13.10)) - "@vitest/pretty-format": 3.0.8 - "@vitest/runner": 3.0.8 - "@vitest/snapshot": 3.0.8 - "@vitest/spy": 3.0.8 - "@vitest/utils": 3.0.8 - chai: 5.2.0 - debug: 4.4.0 - expect-type: 1.2.0 - magic-string: 0.30.17 - pathe: 2.0.3 - std-env: 3.8.1 - tinybench: 2.9.0 - tinyexec: 0.3.2 - tinypool: 1.0.2 - tinyrainbow: 2.0.0 - vite: 6.2.1(@types/node@22.13.10) - vite-node: 3.0.8(@types/node@22.13.10) - why-is-node-running: 2.3.0 - optionalDependencies: - "@types/node": 22.13.10 - transitivePeerDependencies: - - jiti - - less - - lightningcss - - msw - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - - webidl-conversions@3.0.1: - optional: true + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 - whatwg-encoding@3.1.1: - dependencies: - iconv-lite: 0.6.3 + safe-buffer@5.2.1: {} - whatwg-mimetype@4.0.0: {} + safe-stable-stringify@2.5.0: {} - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - optional: true + safer-buffer@2.1.2: {} - which@2.0.2: - dependencies: - isexe: 2.0.0 + sax@1.4.1: {} - why-is-node-running@2.3.0: - dependencies: - siginfo: 2.0.0 - stackback: 0.0.2 + secure-json-parse@2.7.0: {} - wide-align@1.1.5: - dependencies: - string-width: 4.2.3 - optional: true + semver@6.3.1: + optional: true - word-wrap@1.2.5: {} + semver@7.7.1: {} - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 + set-blocking@2.0.0: + optional: true - wrap-ansi@8.1.0: - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 - wrappy@1.0.2: {} + shebang-regex@3.0.0: {} - yallist@4.0.0: - optional: true + siginfo@2.0.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + simple-concat@1.0.1: + optional: true + + simple-get@3.1.1: + dependencies: + decompress-response: 4.2.1 + once: 1.4.0 + simple-concat: 1.0.1 + optional: true + + sisteransi@1.0.5: {} + + slash@5.1.0: {} + + sonic-boom@4.2.0: + dependencies: + atomic-sleep: 1.0.0 + + source-map-js@1.2.1: {} + + split2@4.2.0: {} + + split@0.3.3: + dependencies: + through: 2.3.8 + + stackback@0.0.2: {} + + std-env@3.8.1: {} + + stdin-discarder@0.2.2: {} + + stream-chain@2.2.5: {} + + stream-combiner@0.0.4: + dependencies: + duplexer: 0.1.2 + + stream-json@1.9.1: + dependencies: + stream-chain: 2.2.5 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.4.0 + get-east-asian-width: 1.3.0 + strip-ansi: 7.1.0 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-bom@4.0.0: {} + + strip-json-comments@3.1.1: {} + + strtok3@10.2.2: + dependencies: + '@tokenizer/token': 0.3.0 + peek-readable: 7.0.0 + + syncpack@13.0.3(typescript@5.5.4): + dependencies: + '@effect/schema': 0.75.5(effect@3.14.2) + chalk: 5.4.1 + chalk-template: 1.1.0 + commander: 13.1.0 + cosmiconfig: 9.0.0(typescript@5.5.4) + effect: 3.14.2 + enquirer: 2.4.1 + fast-check: 3.23.2 + globby: 14.1.0 + jsonc-parser: 3.3.1 + minimatch: 9.0.5 + npm-package-arg: 12.0.2 + ora: 8.2.0 + prompts: 2.4.2 + read-yaml-file: 2.1.0 + semver: 7.7.1 + tightrope: 0.2.0 + ts-toolbelt: 9.6.0 + transitivePeerDependencies: + - typescript + + tar@6.2.1: + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + optional: true + + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + + through@2.3.8: {} + + tightrope@0.2.0: {} - yocto-queue@0.1.0: {} + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + + tinypool@1.0.2: {} + + tinyrainbow@2.0.0: {} + + tinyspy@3.0.2: {} + + tldts-core@6.1.84: {} + + tldts@6.1.84: + dependencies: + tldts-core: 6.1.84 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + token-types@6.0.0: + dependencies: + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + + tough-cookie@5.1.2: + dependencies: + tldts: 6.1.84 + + tr46@0.0.3: + optional: true + + ts-toolbelt@9.6.0: {} + + tslib@2.8.1: {} + + type-fest@2.19.0: {} + + type-fest@4.37.0: {} + + typescript@5.5.4: {} + + uint8array-extras@1.4.0: {} + + undici-types@6.19.8: {} + + undici-types@6.20.0: {} + + undici@6.21.1: {} + + unicorn-magic@0.3.0: {} + + universalify@2.0.1: {} + + update-browserslist-db@1.1.3(browserslist@4.24.4): + dependencies: + browserslist: 4.24.4 + escalade: 3.2.0 + picocolors: 1.1.1 + + util-deprecate@1.0.2: + optional: true + + vali-date@1.0.0: {} + + validate-npm-package-name@6.0.0: {} + + vite-node@3.0.8(@types/node@22.13.10): + dependencies: + cac: 6.7.14 + debug: 4.4.0 + es-module-lexer: 1.6.0 + pathe: 2.0.3 + vite: 6.2.1(@types/node@22.13.10) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite@6.2.1(@types/node@22.13.10): + dependencies: + esbuild: 0.25.1 + postcss: 8.5.3 + rollup: 4.35.0 + optionalDependencies: + '@types/node': 22.13.10 + fsevents: 2.3.3 + + vitest@3.0.8(@types/node@22.13.10): + dependencies: + '@vitest/expect': 3.0.8 + '@vitest/mocker': 3.0.8(vite@6.2.1(@types/node@22.13.10)) + '@vitest/pretty-format': 3.0.8 + '@vitest/runner': 3.0.8 + '@vitest/snapshot': 3.0.8 + '@vitest/spy': 3.0.8 + '@vitest/utils': 3.0.8 + chai: 5.2.0 + debug: 4.4.0 + expect-type: 1.2.0 + magic-string: 0.30.17 + pathe: 2.0.3 + std-env: 3.8.1 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: 6.2.1(@types/node@22.13.10) + vite-node: 3.0.8(@types/node@22.13.10) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.13.10 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + webidl-conversions@3.0.1: + optional: true + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + optional: true + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + wide-align@1.1.5: + dependencies: + string-width: 4.2.3 + optional: true + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + ws@7.5.10: {} + + yallist@4.0.0: + optional: true diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..1ed4e39 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,9 @@ +packages: + - packages/* +catalog: + pino: ^9.6.0 + pino-pretty: ^11.2.2 +onlyBuiltDependencies: + - '@biomejs/biome' + - canvas + - esbuild diff --git a/src/clients/defaults.ts b/src/clients/defaults.ts deleted file mode 100644 index 3020c9c..0000000 --- a/src/clients/defaults.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { FetcherOptions } from "../modules/fetchers"; -import { Logger } from "pino"; -import { GotScrapingClient } from "./got_client"; - -export const getPreferredClient = async (logger?: Logger): Promise => { - return new GotScrapingClient(logger, true); -}; - -export const getDefaultFetcherOptions = async ( - options?: FetcherOptions -): Promise> & Pick> => { - const client = options?.client ?? (await getPreferredClient(options?.logger)); - const teardown = options?.teardown ?? true; - return { client, teardown, logger: options?.logger }; -}; diff --git a/src/clients/fetch_client.ts b/src/clients/fetch_client.ts deleted file mode 100644 index 88348a4..0000000 --- a/src/clients/fetch_client.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Logger } from "pino"; -import { unleak } from "../modules/extractors"; - -export interface FetchClientOptions { - /** - * Optional logger to include - */ - logger?: Logger; -} - -export type FetchClientResponse = { - /** - * Whether the request was successful - */ - ok: boolean; - - /** - * The status of the request - */ - status: number; - - /** - * The response body - */ - body: string; - - /** - * The final url resolved for the request (e.g., redirect urls) - */ - url: string; -}; - -export type FetchHtmlResponse = { - /** - * The HTML obtained from a request - */ - html: string; - - /** - * The final url resolved for the request. - */ - url: string; -}; - -export abstract class FetchClient { - constructor(protected logger?: Logger) {} - - abstract fetch(url: string): Promise; - abstract buffer(url: string): Promise; - abstract teardown(): Promise | void; - - /** - * Utility method for checking if a page exists - * @param url The url to ping - * @returns boolean indicating whether the response was ok - */ - async ping(url: string): Promise { - const response = await this.fetch(url); - return response.ok; - } - /** - * - * @param url The url to get - * @returns The html for the given url - */ - async getHtml(url: string): Promise { - this.logger?.trace(`Fetching HTML from ${url}.`); - - const response = await this.fetch(url); - this.logger?.trace( - { - url, - status: response.status - }, - `Fetch for ${url} returned ${response.status}` - ); - if (!response.ok) { - return null; - } - return { - url: response.url, - html: unleak(response.body) - }; - } -} diff --git a/src/clients/got_client.ts b/src/clients/got_client.ts deleted file mode 100644 index 3c1231c..0000000 --- a/src/clients/got_client.ts +++ /dev/null @@ -1,125 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -// @ts-ignore Okay because we only import a type. -import type { GotScraping, Response } from "got-scraping"; -import { SessionPool } from "@crawlee/core"; -import { FetchClient, FetchClientOptions, FetchClientResponse } from "./fetch_client"; -import { Logger } from "pino"; - -export type BaseGotClientFetchResponse = { - readonly response: Response; -}; - -type InternalGotClientFetchResponse = BaseGotClientFetchResponse & { - badSession: boolean; -}; - -export type GotClientFetchOptions = FetchClientOptions & { - /** - * If a session fails, retry once with a new session before giving up. - */ - trySessionRefresh?: boolean; -}; - -export type GotClientFetchResponse = BaseGotClientFetchResponse & FetchClientResponse; - -// from @crawlee/util -let gotScraping = (async (...args: Parameters) => { - ({ gotScraping } = await import("got-scraping")); - return gotScraping(...args); -}) as GotScraping; - -export class GotScrapingClient extends FetchClient { - private sessionPool: SessionPool | null = null; - - constructor( - logger?: Logger, - private doSessionRefresh?: boolean - ) { - super(logger); - } - - async fetch(url: string): Promise { - const logger = this.logger?.child({ label: "gotScrapingClientFetch" }); - const pool = await this.getSessionPool(); - - const response = await this.getResponse(url, pool); - if (response.badSession && this.doSessionRefresh) { - logger?.info("Retrying request with new session."); - const retry = await this.getResponse(url, pool); - return { - body: retry.response.body, - status: retry.response.statusCode, - ok: retry.response.ok, - response: retry.response, - url: retry.response.url - }; - } - - return { - body: response.response.body, - status: response.response.statusCode, - ok: response.response.ok, - response: response.response, - url: response.response.url - }; - } - - async buffer(url: string, attempts = 0): Promise { - const pool = await this.getSessionPool(); - const { response, badSession } = await this.getResponse(url, pool); - if (badSession && attempts === 0) { - return this.buffer(url, attempts + 1); - } - return response.rawBody.buffer; - } - - teardown(): Promise | void {} - - private async getSessionPool(): Promise { - this.sessionPool ??= await SessionPool.open({ - maxPoolSize: 100, - sessionOptions: { - maxUsageCount: 5 - } - }); - return this.sessionPool; - } - - private async getResponse(url: string, pool: SessionPool, logger?: Logger): Promise { - const session = await pool.getSession(); - let response: Response; - try { - response = await gotScraping(url, { - sessionToken: session, - useHeaderGenerator: true, - headerGeneratorOptions: { - browsersListQuery: "> 5%, not dead", - operatingSystems: ["windows", "linux"] - }, - responseType: "text", - retry: { - limit: 3, - statusCodes: [403] - }, - cookieJar: { - getCookieString: async (url: string) => session.getCookieString(url), - setCookie: async (rawCookie: string, url: string) => session.setCookie(rawCookie, url) - } - }); - } catch (e) { - logger?.trace(`Error fetching ${url}, marking session as bad`); - session.markBad(); - throw e; - } - - logger?.trace(`Got ${response.statusCode} on ${url}`); - const hadBadStatus = session.retireOnBlockedStatusCodes(response.statusCode); - if (hadBadStatus) { - logger?.warn(`Warning: Bad status on ${url}, retiring`); - return { response, badSession: true }; - } else { - session.setCookiesFromResponse(response); - return { response, badSession: false }; - } - } -} diff --git a/src/modules/constants.ts b/src/modules/constants.ts deleted file mode 100644 index cd8c43b..0000000 --- a/src/modules/constants.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Question, Season } from "../types"; - -export interface IConstants { - DEFAULT_SEASONS: Season[]; - START_YEAR: number; - CURRENT_YEAR: number; - QUESTION_PROPERTIES: readonly (keyof Question)[]; - DEFAULT_PROGRAMS: ["V5RC", "VURC", "VIQRC", "Judging"]; -} - -export const Constants: IConstants = { - START_YEAR: 2018, - CURRENT_YEAR: new Date(Date.now()).getFullYear(), - get DEFAULT_SEASONS() { - return Array(this.CURRENT_YEAR - this.START_YEAR + 1) - .fill(0) - .map((_, i) => `${this.START_YEAR + i}-${this.START_YEAR + i + 1}`); - }, - get QUESTION_PROPERTIES() { - return [ - "id", - "url", - "author", - "program", - "title", - "question", - "questionRaw", - "answer", - "answerRaw", - "season", - "askedTimestamp", - "askedTimestampMs", - "answeredTimestamp", - "answeredTimestampMs", - "answered", - "tags" - ] satisfies readonly (keyof Question)[]; - }, - DEFAULT_PROGRAMS: ["V5RC", "VURC", "VIQRC", "Judging"] -}; diff --git a/src/modules/extractors.ts b/src/modules/extractors.ts deleted file mode 100644 index 9bd77c5..0000000 --- a/src/modules/extractors.ts +++ /dev/null @@ -1,95 +0,0 @@ -import * as cheerio from "cheerio"; -import { QnaHomeUrl, QnaIdUrl, QnaPageUrl, parseQnaUrlWithId } from "./parsing"; -import SELECTORS from "../selectors.json"; -import { Question } from "../types"; - -export interface ScrapedPage { - url: U; - html: string; -} - -const unformat = (str: string | undefined | null): string => { - return (str ?? "") - .split(/\n/g) - .map((n) => n.trim()) - .filter(Boolean) - .join(""); -}; - -// https://bugs.chromium.org/p/v8/issues/detail?id=2869 -export const unleak = (str: string | undefined | null): string => { - return (" " + (str ?? "")).slice(1); -}; - -type HtmlPresenceRequired = "Required"; -type HtmlPresenceOptional = "Optional"; -type HtmlPresence = HtmlPresenceRequired | HtmlPresenceOptional; -type SelectHtml = T extends HtmlPresenceRequired ? string : string | null; - -const selectHtml = ($: cheerio.CheerioAPI, selector: Parameters[0]): SelectHtml => { - const text = unleak(unformat($(selector).text())); - return (text.trim() === "" ? null : text) as SelectHtml; -}; - -const selectRawHtml = ($: cheerio.CheerioAPI, selector: Parameters[0]): SelectHtml => { - const html = unleak(unformat($(selector).html())); - return (html.trim() === "" ? null : html) as SelectHtml; -}; - -export const extractPageQuestions = ({ html }: ScrapedPage): QnaIdUrl[] => { - const $ = cheerio.load(html); - return $(SELECTORS.URLS) - .toArray() - .map((el) => $(el).attr("href")) - .filter((s): s is QnaIdUrl => s !== undefined); -}; - -export const extractPageCount = ({ html }: ScrapedPage): number => { - const $ = cheerio.load(html); - const el = $(SELECTORS.PAGE_COUNT); - return Number.isNaN(parseInt(el.text())) ? 1 : parseInt(el.text()); -}; - -export const extractQuestion = ({ html, url }: ScrapedPage): Question => { - const $ = cheerio.load(html); - - const { id, program, season } = parseQnaUrlWithId(url); - const author = selectHtml<"Required">($, SELECTORS.AUTHOR); - const title = selectHtml<"Required">($, SELECTORS.TITLE); - const question = selectHtml<"Required">($, SELECTORS.QUESTION); - const questionRaw = selectRawHtml<"Required">($, SELECTORS.QUESTION); - const answer = selectHtml($, SELECTORS.ANSWER); - const answerRaw = selectRawHtml($, SELECTORS.ANSWER); - const askedTimestamp = selectHtml<"Required">($, SELECTORS.ASKED_TIMESTAMP); - const askedTimestampMs = new Date(askedTimestamp).getTime(); - const answeredTimestamp = selectHtml($, SELECTORS.ANSWERED_TIMESTAMP); - const answeredTimestampMs = answeredTimestamp !== null ? new Date(answeredTimestamp).getTime() : null; - const answered = answer !== null; - const tags = $(SELECTORS.TAGS) - .map((_i, el) => unleak($(el).text().trim())) - .get(); - - return { - id, - url, - program, - season, - author, - title, - question, - questionRaw, - answer, - answerRaw, - askedTimestamp, - askedTimestampMs, - answeredTimestamp, - answeredTimestampMs, - answered, - tags - }; -}; - -export const extractReadOnly = ({ html }: ScrapedPage): boolean => { - const $ = cheerio.load(html); - return selectHtml($, SELECTORS.READONLY) !== null; -}; diff --git a/src/modules/fetchers.ts b/src/modules/fetchers.ts deleted file mode 100644 index 0af3433..0000000 --- a/src/modules/fetchers.ts +++ /dev/null @@ -1,357 +0,0 @@ -import { Logger } from "pino"; -import { FetchClient, FetchClientOptions, FetchClientResponse, getDefaultFetcherOptions } from "../clients"; -import { Question, Season } from "../types"; -import { attempt, AttemptResult, nsToMsElapsed, sleep } from "../util"; -import { Constants } from "./constants"; -import { extractPageCount, extractPageQuestions, extractQuestion, extractReadOnly } from "./extractors"; -import { buildHomeQnaUrl, buildQnaUrlWithId, buildQnaUrlWithPage, QnaHomeUrl, QnaIdUrl, QnaPageUrl } from "./parsing"; - -export interface FetcherOptions { - client?: FetchClient; - logger?: Logger; - teardown?: boolean; -} - -/** - * Fetches the page count for the given Q&A - * @param url The Q&A to fetch the page count from - * @param logger Optional {@link Logger} - * @returns The page count for the given Q&A - */ -export const fetchPageCount = async (url: QnaHomeUrl, options?: FetcherOptions): Promise => { - const { client, teardown } = await getDefaultFetcherOptions(options); - const html = await client.getHtml(url); - if (html === null) { - return null; - } - const pageCount = extractPageCount({ - url, - html: html.html - }); - options?.logger?.trace( - { - label: "fetchPageCount", - pageCount, - url - }, - `Page count for ${url}: ${pageCount}` - ); - if (teardown) { - await client.teardown(); - } - return pageCount; -}; - -/** - * Checks whether a Q&A for a given program and seasons exists - * @param program The program of the Q&A to ping - * @param season The season of the Q&A to ping - * @param logger Optional {@link Logger} - * @returns true if the Q&A exists, false if it does not - */ -export const pingQna = async (program: string, season: string, options?: FetcherOptions): Promise => { - const { client, teardown } = await getDefaultFetcherOptions(options); - const url = buildHomeQnaUrl({ program, season }); - const ok = client.ping(url); - options?.logger?.trace({ - exists: ok, - label: "pingQna", - program, - season - }); - if (teardown) { - await client.teardown(); - } - return ok; -}; - -/** - * Fetches data for a given Q&A - * @param url The url of the Q&A - * @param logger Optional {@link Logger} - * @returns The Q&A data from the page - */ -export const fetchQuestion = async (url: QnaIdUrl, options?: FetcherOptions): Promise => { - const { client, teardown } = await getDefaultFetcherOptions(options); - const html = await client.getHtml(url); - if (html === null) { - if (teardown) { - await client.teardown(); - } - return null; - } - if (teardown) { - await client.teardown(); - } - return extractQuestion({ url, html: html.html }); -}; - -/** - * Fetches the current season. - * @param logger Optional {@link Logger} - * @returns The current season - */ -export const fetchCurrentSeason = async (options?: FetcherOptions): Promise => { - const newSeason = await pingQna("V5RC", `${Constants.CURRENT_YEAR}-${Constants.CURRENT_YEAR + 1}`, options); - const currentSeason: Season = newSeason - ? `${Constants.CURRENT_YEAR}-${Constants.CURRENT_YEAR + 1}` - : `${Constants.CURRENT_YEAR - 1}-${Constants.CURRENT_YEAR}`; - options?.logger?.trace( - { - label: "fetchCurrentSeason", - currentSeason - }, - `Current season: ${currentSeason}` - ); - return currentSeason; -}; - -/** - * Generates a list of all seasons to date - * @param logger Optional {@link Logger} - * @returns A list of all seasons to date - */ -export const fetchAllSeasons = async (options?: FetcherOptions): Promise => { - const allSeasons: Season[] = []; - const [start] = (await fetchCurrentSeason(options)).split("-"); - const startYear = parseInt(start); - for (let year = 2018; year <= startYear; year++) { - allSeasons.push(`${year}-${year + 1}`); - } - options?.logger?.trace({ allSeasons }, "Fetched all seasons"); - return allSeasons; -}; - -/** - * Generates a list of urls with the given program and list of seasons - * @param program The program to generate pages with - * @param seasons The seasons to generate pages with - * @param logger Optional {@link Logger} - * @returns A list of urls corresponding to the given program and seasons - */ -export const fetchPagesForSeasons = async (program: string, seasons: Season[], options?: FetchClientOptions): Promise => { - const urls: QnaPageUrl[] = []; - for (const season of seasons) { - const url = buildHomeQnaUrl({ program, season }); - const pageCount = await fetchPageCount(url, options); - if (pageCount === null) { - options?.logger?.warn(`Warning: unable to retrieve page count for ${url}`); - continue; - } - for (let page = 1; page <= pageCount; page++) { - urls.push(buildQnaUrlWithPage({ program, season, page })); - } - } - return urls; -}; - -export type PageQuestionsResults = [Question[], string[]]; - -/** - * Fetches Q&A data from the given url - * @param url The Q&A page url to extract data from - * @param logger Optional {@link Logger} - * @returns Q&A data from the given page - */ -export const fetchQuestionsFromPage = async (url: QnaPageUrl, options?: FetcherOptions): Promise => { - const { client, teardown } = await getDefaultFetcherOptions(options); - const html = await client.getHtml(url); - if (html === null) { - return null; - } - const urls = extractPageQuestions({ url, html: html.html }); - options?.logger?.trace({ urls }, `Extracted ${urls.length} urls from ${url}`); - const results = await Promise.allSettled(urls.map((u) => fetchQuestion(u, options))); - const passed: Question[] = [], - failed: QnaIdUrl[] = []; - results.forEach((result, i) => { - if (result.status === "fulfilled" && result.value !== null) { - passed.push(result.value); - } else { - failed.push(urls[i]); - } - }); - if (teardown) { - await client.teardown(); - } - return [passed, failed]; -}; - -type Job = { - name: string; - job: T; -}; - -/** - * Fetches Q&A data from a list of urls - * @param urls The urls to fetch Q&A data from - * @param logger Optional {@link Logger} - * @param interval Time in milliseconds to wait in between requests - * @returns All Q&A data from the specified pages - */ -export const fetchQuestionsFromPages = async (urls: QnaPageUrl[], options?: FetcherOptions, interval = 1500): Promise => { - const { client, teardown } = await getDefaultFetcherOptions(options); - const jobs: Job>>[] = []; - const startTime = process.hrtime.bigint(); - - for (const url of urls) { - const job = { - name: url, - job: attempt({ - attempts: 3, - callback: () => fetchQuestionsFromPage(url, { client, teardown: false }), - logger: options?.logger - }) - }; - jobs.push(job); - await sleep(interval); - } - - const jobResults = await Promise.all(jobs.map((j) => j.job)); - const elapsed = new Date(nsToMsElapsed(startTime)); - const success: Question[] = [], - failedQuestions: string[] = [], - failedPages: string[] = []; - jobResults.forEach((job, i) => { - if (job.status === "success" && job.value !== null) { - const [passed, failed] = job.value; - success.push(...passed); - failedQuestions.push(...failed); - } else { - failedPages.push(jobs[i].name); - } - }); - - options?.logger?.info( - { - failedQuestions, - failedPages - }, - `${success.length} succeeded, ${failedQuestions.length} questions failed, ${failedPages.length} question pages failed.` - ); - options?.logger?.info(`Completed in ${elapsed.getMinutes()}min ${elapsed.getSeconds()}s ${elapsed.getMilliseconds()}ms`); - if (teardown) { - await client.teardown(); - } - return success; -}; - -export const fetchQuestionRange = async (ids: number[], options?: FetcherOptions): Promise => { - const { client, teardown } = await getDefaultFetcherOptions(options); - const range = ids.map(async (id) => { - const url = buildQnaUrlWithId({ - program: "V5RC", - season: "2020-2021", - id: `${id}` - }); - const page = await client.getHtml(url); - if (page === null) { - return null; - } - - return extractQuestion({ - html: page.html, - url: page.url as QnaIdUrl - }); - }); - const results = await Promise.allSettled(range); - if (teardown) { - await client.teardown(); - } - return handleIterativeBatch(ids, results); -}; - -export const ITERATIVE_BATCH_COUNT = 10; -export const ITERATIVE_INTERVAL = 10; - -export type IterativeFetchResult = { - /** - * The list of questions fetched - */ - questions: Question[]; - - /** - * The ids of the questions that could not be retrieved - */ - failures: string[]; -}; - -export type IterativeFetchOptions = FetcherOptions & { - /** - * The ID to start scraping questions from - */ - start?: number; -}; - -export type IterativeBatchResult = { - questions: Question[]; - failed: boolean; - failures: string[]; -}; - -export const handleIterativeBatch = (range: number[], results: PromiseSettledResult[]): IterativeBatchResult => { - const questions: Question[] = []; - const failures: string[] = []; - for (let i = 0; i < results.length; i++) { - const result = results[i]; - if (result.status === "rejected" || result.value === null) { - failures.push(`${range[i]}`); - continue; - } - questions.push(result.value); - } - return { questions, failed: failures.length === results.length, failures }; -}; - -/** - * Fetches questions iteratively. Instead of generating a list of urls to scrape, we iterate through IDs in batches - * until a batch fails, resulting in faster scraping. Best for when you want a dump of all Q&As. - * @param options Options for defining an optional logger and start point - * @returns Object containing the fecthed Q&As, plus some additional utility data - */ -export const fetchQuestionsIterative = async (options?: IterativeFetchOptions): Promise => { - const { client, teardown } = await getDefaultFetcherOptions(options); - const start = options?.start !== undefined ? Math.max(options.start, 1) : 1; - let batchFailed = false; - let range = [...Array(ITERATIVE_BATCH_COUNT).keys()].map((n) => start + n); - - const questions: Question[] = []; - const failures: string[] = []; - const startTime = process.hrtime.bigint(); - - while (!batchFailed) { - options?.logger?.trace(`Scraping question range ${range[0]}-${range.at(-1)}`); - const { questions: batchQuestions, failed, failures: batchFailures } = await fetchQuestionRange(range, { client, teardown: false }); - questions.push(...batchQuestions); - if (failed) { - options?.logger?.info(`Batch failed for range ${range[0]}-${range.at(-1)}, exiting`); - batchFailed = true; - } else { - failures.push(...batchFailures); - range = range.map((n) => n + ITERATIVE_INTERVAL); - await sleep(1500); - } - } - - const elapsed = new Date(nsToMsElapsed(startTime)); - options?.logger?.info(`Scraped ${questions.length} questions`); - options?.logger?.info(`Failed getting ${failures.length} questions`); - options?.logger?.info(`Completed in ${elapsed.getMinutes()}min ${elapsed.getSeconds()}s ${elapsed.getMilliseconds()}ms`); - - if (teardown) { - await client.teardown(); - } - return { questions, failures }; -}; - -export const checkIfReadOnly = async (program: string, season: Season, options?: FetcherOptions): Promise => { - const { client, teardown } = await getDefaultFetcherOptions(options); - const html = await client.getHtml(buildHomeQnaUrl({ program, season })); - if (html === null) { - return null; - } - if (teardown) { - await client.teardown(); - } - return extractReadOnly({ url: html.url as QnaHomeUrl, html: html.html }); -}; diff --git a/src/modules/generators.ts b/src/modules/generators.ts deleted file mode 100644 index 9ce0c3f..0000000 --- a/src/modules/generators.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { Logger } from "pino"; -import { Program, Season } from "../types"; -import { Constants } from "./constants"; -import { fetchPagesForSeasons, pingQna } from "./fetchers"; -import { QnaPageUrl } from "./parsing"; - -const unique = (arr: T[]): T[] => arr.filter((a, i) => arr.indexOf(a) === i); - -export type YearFilters = Season[]; -export type ProgramFilters = { - [k in Program]?: Season[]; -}; -export type QnaFilters = ProgramFilters | YearFilters; - -export interface GeneratorOptions { - logger?: Logger; -} - -/** - * Verifies that a Q&A exists, actually validating that the program and season is valid before calling {@link pingQna} - * @param program The program of the Q&A to check - * @param season The season of the Q&A to check - */ -export const verifyQnaExists = async (program: string, season: Season): Promise => { - const match = season.match(/(?\d{4})-(?\d{4})/); - if (!match?.groups) { - throw Error(`${season} does not match the format '{year}-{year}'.`); - } - - if (parseInt(match.groups.end) - parseInt(match.groups.start) !== 1) { - throw Error(`${season} does not match the format '{year}-{year + 1}'`); - } - - const exists = await pingQna(program, season); - if (!exists) { - throw Error(`Unable to find a ${program} Q&A for the ${season} season`); - } -}; - -const verifyQnasExist = async (program: string, seasons: Season[]): Promise => { - await Promise.all(seasons.map((s) => verifyQnaExists(program, s))); -}; - -const processFilters = async (filters?: QnaFilters, logger?: Pick): Promise<[string[], Season[][]]> => { - const programs: string[] = []; - const seasons: Season[][] = []; - - if (!filters) { - logger?.trace("No filters provided."); - return [[], []]; - } - - if (Array.isArray(filters)) { - const uniqueSeasons = unique(filters); - for (const program of Constants.DEFAULT_PROGRAMS) { - await verifyQnasExist(program, uniqueSeasons); - if (program === "Judging") { - programs.push(program); - seasons.push([uniqueSeasons[0]]); - } else { - programs.push(program); - seasons.push(uniqueSeasons); - } - } - return [programs, seasons]; - } - - const entries = Object.entries(filters); - for (const [program, entrySeasons] of entries) { - const uniqueSeasons = unique(entrySeasons); - await verifyQnasExist(program, uniqueSeasons); - if (program === "Judging") { - programs.push(program); - seasons.push([uniqueSeasons[0]]); - } else { - programs.push(program); - seasons.push(uniqueSeasons); - } - } - - return [programs, seasons]; -}; - -/** - * Generate a list of urls to scrape based on the given filters - * @param filters The filters to apply - * @returns A list of urls to scrape that match the given filters - */ -export const getScrapingUrls = async (filters?: QnaFilters, options?: GeneratorOptions): Promise => { - const [programs, seasons] = await processFilters(filters, options?.logger); - const urls: QnaPageUrl[] = []; - for (let ci = 0; ci < programs.length; ci++) { - const program = programs[ci]; - const seasonList = seasons[ci]; - const pages = await fetchPagesForSeasons(program, seasonList, options); - urls.push(...pages); - } - options?.logger?.trace({ urls }, `Created ${urls.length} urls that satisfy the provided filters.`); - return urls; -}; diff --git a/src/modules/parsing.ts b/src/modules/parsing.ts deleted file mode 100644 index c4d3aa0..0000000 --- a/src/modules/parsing.ts +++ /dev/null @@ -1,58 +0,0 @@ -interface BaseQnaUrlParams { - program: string; - season: string; -} - -interface QnaUrlIdParams extends BaseQnaUrlParams { - id: string; -} - -interface QnaUrlPageParams extends BaseQnaUrlParams { - page: number; -} - -export type QnaHomeUrl = `https://www.robotevents.com/${string}/${string}/QA`; -export type QnaPageUrl = `${QnaHomeUrl}?page=${string}`; -export type QnaIdUrl = `${QnaHomeUrl}/${string}`; - -export const validateQnaUrl = (url: string): Record => { - const regex = /^https:\/\/www\.robotevents\.com\/(?\w+)\/(?\d{4}-\d{4})\/QA(?:\/(?\d+))?(?:\?page=(?\d+))?$/; - const match = url.match(regex); - if (!match?.groups) { - throw Error(`${url} in unrecognized format.`); - } - return match.groups; -}; - -export const parseQnaUrlWithId = (url: QnaIdUrl): QnaUrlIdParams => { - const parsed = validateQnaUrl(url); - return { - program: parsed.program, - season: parsed.season, - id: parsed.id - }; -}; - -export const parseQnaUrlWithPage = (url: QnaPageUrl): QnaUrlPageParams => { - const parsed = validateQnaUrl(url); - return { - program: parsed.program, - season: parsed.season, - page: parseInt(parsed.page) - }; -}; - -export const buildHomeQnaUrl = (params: BaseQnaUrlParams): QnaHomeUrl => { - const { program, season } = params; - return `https://www.robotevents.com/${program}/${season}/QA`; -}; - -export const buildQnaUrlWithId = (params: QnaUrlIdParams): QnaIdUrl => { - const { program, season, id } = params; - return `https://www.robotevents.com/${program}/${season}/QA/${id}`; -}; - -export const buildQnaUrlWithPage = (params: QnaUrlPageParams): QnaPageUrl => { - const { program, season, page } = params; - return `https://www.robotevents.com/${program}/${season}/QA?page=${page}`; -}; diff --git a/src/modules/query.ts b/src/modules/query.ts deleted file mode 100644 index f9b7fbc..0000000 --- a/src/modules/query.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { Question, Season } from "../types"; -import { - fetchCurrentSeason, - FetcherOptions, - fetchQuestionsFromPages, - fetchQuestionsIterative, - IterativeFetchOptions, - IterativeFetchResult -} from "./fetchers"; -import { QnaFilters, getScrapingUrls } from "./generators"; - -/** - * Utility wrapper around {@link getQuestions} that gets unanswered questions for the current season. - * @param logger Optional {@link Logger} - * @returns All questions that have not been answered. - */ -export const getUnansweredQuestions = async (options?: FetcherOptions): Promise => { - const questions = await getQuestions(undefined, options); - return questions.filter((q) => !q.answered); -}; - -/** - * Get questions with an optional filter. - * @param filters Optional filters to limit the results retreived. Defaults to filtering by current season. - * @param logger Optional {@link Logger} - * @returns All questions that passed the filter. - */ -export const getQuestions = async (filters?: QnaFilters, options?: FetcherOptions): Promise => { - if (filters === undefined) { - filters = [await fetchCurrentSeason(options)]; - } - const urls = await getScrapingUrls(filters, options); - return fetchQuestionsFromPages(urls, options); -}; - -/** - * Gets all questions. Includes questions that may not be shown on the Q&A homepage. - * @param logger Optional {@link Logger} - * @returns All questions from every season - */ -export const getAllQuestions = async (options?: IterativeFetchOptions): Promise => { - return await fetchQuestionsIterative(options); -}; - -/** - * Gets the oldest unanswered question for a given season. - * @param questions The questions to operate on - * @param season The season in which to search in - * @returns The oldest question asked for the given season, if any - */ -export const getOldestUnansweredQuestion = (questions: Question[], season: Season): Question | undefined => { - const data = [...questions]; - data.sort((q1, q2) => q1.askedTimestampMs - q2.askedTimestampMs + (parseInt(q1.id) - parseInt(q2.id))); - return data.find((q) => q.answered === false && q.season === season && !q.title.startsWith("[archived]")); -}; - -/** - * Gets the oldest unanswered question for a given season. - * @param questions The questions to operate on - * @param season The season in which to search in - * @returns The oldest question asked for the given season, if any - */ -export const getOldestQuestion = (questions: Question[], season: Season): Question | undefined => { - const data = [...questions]; - data.sort((q1, q2) => q1.askedTimestampMs - q2.askedTimestampMs + (parseInt(q1.id) - parseInt(q2.id))); - return data.find((q) => q.season === season && !q.title.startsWith("[archived]")); -}; diff --git a/src/modules/rules.ts b/src/modules/rules.ts deleted file mode 100644 index 4d544e0..0000000 --- a/src/modules/rules.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { parsepdf } from "node-pdf-parser"; -import { getDefaultFetcherOptions } from "../clients"; -import { FetcherOptions } from "./fetchers"; - -export const RULE_TABLE_PATTERN = /(?<[A-Z]+\d+>) (?[A-Z](?:.+\.?))+?/g; - -export interface Rule { - name: string; - summary: string; -} - -export const extractRules = async (url: string, options?: FetcherOptions): Promise => { - const logger = options?.logger?.child({ label: "extractRules" }); - const { client, teardown } = await getDefaultFetcherOptions(options); - const buffer = await client.buffer(url); - if (buffer === null) { - return null; - } - const content = await parsepdf(buffer); - const text = content.pages.join("\n"); - const matches = Array.from(text.matchAll(RULE_TABLE_PATTERN)); - const rules: Rule[] = []; - for (const match of matches) { - const name = match.groups?.name; - const summary = match.groups?.summary; - if (name === undefined || summary === undefined || rules.find((r) => r.name === name)) { - logger?.trace(`Already added rule ${name}, skipping.`); - continue; - } - logger?.debug("Adding new rule: ", name); - rules.push({ name, summary }); - } - if (teardown) { - await client.teardown(); - } - logger?.debug(`Found ${rules.length} rules.`); - return rules; -}; diff --git a/src/selectors.json b/src/selectors.json deleted file mode 100644 index 4dbbca9..0000000 --- a/src/selectors.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "URLS": "div.card-body h4.title > a", - "AUTHOR": "div.author", - "TITLE": "div.question > h4", - "QUESTION": "div.content-body:nth-child(4)", - "ANSWER": "div.answer.approved .content-body", - "ASKED_TIMESTAMP": "div.details:nth-child(3) > div:nth-child(2)", - "ANSWERED_TIMESTAMP": "div.pull-right", - "TAGS": "div.tags a", - "PAGE_COUNT": "nav ul.pagination li:nth-last-child(2)", - "READONLY": "div.alert-warning" -} diff --git a/src/types.ts b/src/types.ts deleted file mode 100644 index 872f87f..0000000 --- a/src/types.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Constants } from "./modules/constants"; - -export interface Question { - /** - * The question's numerical ID. - */ - id: string; - - /** - * The url of the question. - */ - url: string; - - /** - * The person who asked the question. - */ - author: string; - - /** - * The program this question was asked in (e.g., V5RC, VURC, etc). - */ - program: string; - - /** - * The title of the question. - */ - title: string; - - /** - * The question content. - */ - question: string; - - /** - * The question content as raw html - */ - questionRaw: string; - - /** - * The answer to the question. - */ - answer: string | null; - - /** - * The answer content as raw html - */ - answerRaw: string | null; - - /** - * The season this question was asked in (e.g., 2022-2023). - */ - season: string; - - /** - * When this question was asked (in the format DD-Mon-YYYY). - */ - askedTimestamp: string; - - /** - * {@link askedTimestamp} in milliseconds. - */ - askedTimestampMs: number; - - /** - * When this question was answered (in the format DD-Mon-YYYY). - */ - answeredTimestamp: string | null; - - /** - * {@link answeredTimestamp} in milliseconds. - */ - answeredTimestampMs: number | null; - - /** - * Whether the question was answered. - */ - answered: boolean; - - /** - * Tags added to this question. - */ - tags: string[]; -} - -export type Season = `${number}-${number}`; - -export type Program = (typeof Constants.DEFAULT_PROGRAMS)[number]; diff --git a/src/util/attempt.ts b/src/util/attempt.ts deleted file mode 100644 index f7f7876..0000000 --- a/src/util/attempt.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Logger } from "pino"; - -export interface AttemptOptions { - callback: () => T | Promise; - onRetry?: (attempts: number) => void; - logger?: Pick; - attempts: number; -} - -export interface AttemptSuccess { - status: "success"; - value: T; -} - -export interface AttemptFailure { - status: "failure"; -} - -export type AttemptResult = AttemptSuccess | AttemptFailure; - -export const attempt = async (options: AttemptOptions): Promise> => { - let result: T | undefined = undefined; - - for (let i = 0; i < options.attempts; i++) { - try { - result = await options.callback(); - return { - status: "success", - value: result - }; - } catch (e) { - options.logger?.error(e); - options.onRetry?.(i); - } - } - - return { - status: "failure" - }; -}; diff --git a/tests/data/test_questions.ts b/tests/data/test_questions.ts deleted file mode 100644 index 3dcad8d..0000000 --- a/tests/data/test_questions.ts +++ /dev/null @@ -1,449 +0,0 @@ -/* eslint-dsiable sonarjs/no-duplicate-string */ - -import { Question } from "../../src"; - -export const TEST_SEASON = "2024-2025"; - -export const OLDEST_TEST_QUESTION_UNIQUE_DATES: Question = { - id: "2059", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2059", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "21-Jul-2024", - askedTimestampMs: 1721545200000, - answeredTimestamp: null, - answeredTimestampMs: null, - answered: false, - tags: ["SG1"] -}; - -export const TEST_QUESTIONS_UNIQUE_DATES: Question[] = [ - { - id: "2057", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2057", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "19-Jul-2024", - askedTimestampMs: 1721372400000, - answeredTimestamp: "19-Jul-2024", - answeredTimestampMs: 1721372400000, - answered: true, - tags: ["SG1"] - }, - { - id: "2058", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2058", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "20-Jul-2024", - askedTimestampMs: 1721458800000, - answeredTimestamp: "20-Jul-2024", - answeredTimestampMs: 1721458800000, - answered: true, - tags: ["SG1"] - }, - { - id: "2059", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2059", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "21-Jul-2024", - askedTimestampMs: 1721545200000, - answeredTimestamp: null, - answeredTimestampMs: null, - answered: false, - tags: ["SG1"] - }, - { - id: "2060", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2060", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "22-Jul-2024", - askedTimestampMs: 1721631600000, - answeredTimestamp: "22-Jul-2024", - answeredTimestampMs: 1721631600000, - answered: true, - tags: ["SG1"] - }, - { - id: "2061", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2061", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "23-Jul-2024", - askedTimestampMs: 1721718000000, - answeredTimestamp: null, - answeredTimestampMs: null, - answered: false, - tags: ["SG1"] - }, - { - id: "2062", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2062", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "24-Jul-2024", - askedTimestampMs: 1721804400000, - answeredTimestamp: null, - answeredTimestampMs: null, - answered: false, - tags: ["SG1"] - }, - { - id: "2063", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2063", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "25-Jul-2024", - askedTimestampMs: 1721890800000, - answeredTimestamp: "25-Jul-2024", - answeredTimestampMs: 1721890800000, - answered: true, - tags: ["SG1"] - } -]; - -export const OLDEST_TEST_QUESTIONS_OVERLAPPING_DATES: Question = { - id: "2058", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2058", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "20-Jul-2024", - askedTimestampMs: 1721458800000, - answeredTimestamp: null, - answeredTimestampMs: null, - answered: false, - tags: ["SG1"] -}; - -export const TEST_QUESTIONS_OVERLAPPING_DATES: Question[] = [ - { - id: "2057", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2057", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "19-Jul-2024", - askedTimestampMs: 1721372400000, - answeredTimestamp: "19-Jul-2024", - answeredTimestampMs: 1721372400000, - answered: true, - tags: ["SG1"] - }, - { - id: "2060", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2060", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "22-Jul-2024", - askedTimestampMs: 1721631600000, - answeredTimestamp: "22-Jul-2024", - answeredTimestampMs: 1721631600000, - answered: true, - tags: ["SG1"] - }, - { - id: "2061", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2061", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "23-Jul-2024", - askedTimestampMs: 1721718000000, - answeredTimestamp: null, - answeredTimestampMs: null, - answered: false, - tags: ["SG1"] - }, - { - id: "2059", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2059", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "20-Jul-2024", - askedTimestampMs: 1721458800000, - answeredTimestamp: null, - answeredTimestampMs: null, - answered: false, - tags: ["SG1"] - }, - { - id: "2058", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2058", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "20-Jul-2024", - askedTimestampMs: 1721458800000, - answeredTimestamp: null, - answeredTimestampMs: null, - answered: false, - tags: ["SG1"] - }, - { - id: "2062", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2062", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "24-Jul-2024", - askedTimestampMs: 1721804400000, - answeredTimestamp: null, - answeredTimestampMs: null, - answered: false, - tags: ["SG1"] - }, - { - id: "2063", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2063", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "24-Jul-2024", - askedTimestampMs: 1721804400000, - answeredTimestamp: null, - answeredTimestampMs: null, - answered: false, - tags: ["SG1"] - } -]; - -export const OLDEST_TEST_QUESTIONS_MIXED_OVERLAPPING_DATES: Question = { - id: "2061", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2061", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "23-Jul-2024", - askedTimestampMs: 1721718000000, - answeredTimestamp: null, - answeredTimestampMs: null, - answered: false, - tags: ["SG1"] -}; - -export const TEST_QUESTIONS_MIXED_OVERLAPPING_DATES: Question[] = [ - { - id: "2059", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2059", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "20-Jul-2024", - askedTimestampMs: 1721458800000, - answeredTimestamp: "20-Jul-2024", - answeredTimestampMs: 1721458800000, - answered: true, - tags: ["SG1"] - }, - { - id: "2058", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2058", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "20-Jul-2024", - askedTimestampMs: 1721458800000, - answeredTimestamp: "20-Jul-2024", - answeredTimestampMs: 1721458800000, - answered: true, - tags: ["SG1"] - }, - { - id: "2063", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2063", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "24-Jul-2024", - askedTimestampMs: 1721804400000, - answeredTimestamp: null, - answeredTimestampMs: null, - answered: false, - tags: ["SG1"] - }, - { - id: "2060", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2060", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "22-Jul-2024", - askedTimestampMs: 1721631600000, - answeredTimestamp: "22-Jul-2024", - answeredTimestampMs: 1721631600000, - answered: true, - tags: ["SG1"] - }, - { - id: "2062", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2062", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "23-Jul-2024", - askedTimestampMs: 1721718000000, - answeredTimestamp: null, - answeredTimestampMs: null, - answered: false, - tags: ["SG1"] - }, - { - id: "2057", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2057", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "19-Jul-2024", - askedTimestampMs: 1721372400000, - answeredTimestamp: "19-Jul-2024", - answeredTimestampMs: 1721372400000, - answered: true, - tags: ["SG1"] - }, - { - id: "2061", - url: "https://www.robotevents.com/V5RC/2024-2025/QA/2061", - program: "V5RC", - season: "2024-2025", - author: "", - title: "Test 1", - question: "", - questionRaw: "", - answer: "", - answerRaw: "", - askedTimestamp: "23-Jul-2024", - askedTimestampMs: 1721718000000, - answeredTimestamp: null, - answeredTimestampMs: null, - answered: false, - tags: ["SG1"] - } -]; diff --git a/tests/data/v5rc_question_page_json.ts b/tests/data/v5rc_question_page_json.ts deleted file mode 100644 index 6900768..0000000 --- a/tests/data/v5rc_question_page_json.ts +++ /dev/null @@ -1,18 +0,0 @@ -export default { - "id": "1591", - "url": "https://www.robotevents.com/V5RC/2023-2024/QA/1591", - "program": "V5RC", - "season": "2023-2024", - "author": "14316A", - "title": "The position of triballs in Match Load Zone", - "question": "Note: The Triballs which start in each Match Load Zone must be contacting the Match Load Zone at the start of the Match. However, they may be repositioned during pre-Match setup by the Team whose Robot is using the Starting Tiles adjacent to that Match Load Zone. For example, in Figure 26, Red Robot 1 would be permitted to reposition the Triball in the lower-left red Match Load Zone.Is it legal to place the triball which starts in the Match Load Zone as in the photo?", - "questionRaw": "

<SG1>Note: The Triballs which start in each Match Load Zone must be contacting the Match Load Zone at the start of the Match. However, they may be repositioned during pre-Match setup by the Team whose Robot is using the Starting Tiles adjacent to that Match Load Zone. For example, in Figure 26, Red Robot 1 would be permitted to reposition the Triball in the lower-left red Match Load Zone.

Is it legal to place the triball which starts in the Match Load Zone as in the photo?\"img\"

", - "answer": "The Match Load Zone is defined as \"The portion of the floor tile bordered by a Match Load Bar and an inside corner of the Field Perimeter.\" The example you provided--and any other position that meets the requirement of the note in (contacting the Match Load Zone)--is legal for a Triball that begins the Match within a Match Load Zone.", - "answerRaw": "

The Match Load Zone is defined as \"The portion of the floor tile bordered by a Match Load Bar and an inside corner of the Field Perimeter.\" The example you provided--and any other position that meets the requirement of the note in <SG1> (contacting the Match Load Zone)--is legal for a Triball that begins the Match within a Match Load Zone.

", - "askedTimestamp": "18-Jul-2023", - "askedTimestampMs": new Date("18-Jul-2023").getTime(), - "answeredTimestamp": "24-Jul-2023", - "answeredTimestampMs": new Date("24-Jul-2023").getTime(), - "answered": true, - "tags": ["SG1"] -} diff --git a/tests/extractors.test.ts b/tests/extractors.test.ts deleted file mode 100644 index 1c18dc9..0000000 --- a/tests/extractors.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { extractPageCount, extractPageQuestions, extractQuestion, extractReadOnly } from "../src/modules/extractors"; -import judging_home_page from "./data/judging_home_page"; -import vurc_home_page from "./data/vurc_home_page"; -import v5rc_home_page from "./data/v5rc_home_page"; -import v5rc_question_page from "./data/v5rc_question_page"; -import v5rc_question_page_json from "./data/v5rc_question_page_json"; -import v5rc_non_readonly_page from "./data/v5rc_non_readonly_page"; -import { describe, expect, it, test } from "vitest"; - -describe("extractPageCount", () => { - it("shall return the correct page number when the pagination element is present", () => { - const data = extractPageCount(v5rc_home_page); - expect(data).toEqual(28); - }); - - it("shall return '1' when no pagination element is present", () => { - const data = extractPageCount(judging_home_page); - expect(data).toEqual(1); - }); -}); - -describe("extractQuestionData", () => { - it("shall correctly extract data from a question page", () => { - const data = extractQuestion(v5rc_question_page); - expect(data).toStrictEqual(v5rc_question_page_json); - }); -}); - -describe("extractPageQuestions", () => { - it("shall extract questions from a Q&A page", () => { - const data = extractPageQuestions(vurc_home_page); - expect(data).toEqual([ - "https://www.robotevents.com/VURC/2023-2024/QA/1969", - "https://www.robotevents.com/VURC/2023-2024/QA/1946", - "https://www.robotevents.com/VURC/2023-2024/QA/1945", - "https://www.robotevents.com/VURC/2023-2024/QA/1942", - "https://www.robotevents.com/VURC/2023-2024/QA/1932", - "https://www.robotevents.com/VURC/2023-2024/QA/1927", - "https://www.robotevents.com/VURC/2023-2024/QA/1925", - "https://www.robotevents.com/VURC/2023-2024/QA/1924", - "https://www.robotevents.com/VURC/2023-2024/QA/1923", - "https://www.robotevents.com/VURC/2023-2024/QA/1922" - ]); - }); -}); - -describe("extractReadOnly", () => { - it("shall extract the readonly status from a Q&A page", () => { - expect(extractReadOnly(v5rc_home_page)).toBe(true); - expect(extractReadOnly(v5rc_non_readonly_page)).toBe(false); - }) -}) diff --git a/tests/parsing.test.ts b/tests/parsing.test.ts deleted file mode 100644 index 6f75285..0000000 --- a/tests/parsing.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { QnaHomeUrl, QnaIdUrl, QnaPageUrl, buildHomeQnaUrl, buildQnaUrlWithId, buildQnaUrlWithPage, parseQnaUrlWithId, parseQnaUrlWithPage, validateQnaUrl } from "../src/modules/parsing"; -import { describe, expect, it, test } from "vitest"; - -const TEST_SEASON = "2023-2024"; -const TEST_PROGRAM = "V5RC"; -const TEST_QUESTION_ID = "1591"; -const TEST_PAGE_NUM = 1; - -const VALID_HOME_URL: QnaHomeUrl = `https://www.robotevents.com/${TEST_PROGRAM}/${TEST_SEASON}/QA`; -const VALID_QUESTION_URL: QnaIdUrl = `https://www.robotevents.com/${TEST_PROGRAM}/${TEST_SEASON}/QA/${TEST_QUESTION_ID}`; -const VALID_PAGINATED_URL: QnaPageUrl = `https://www.robotevents.com/${TEST_PROGRAM}/${TEST_SEASON}/QA?page=${TEST_PAGE_NUM}`; -const INVALID_URL = "INVALID_URL"; - -describe("validateQnaUrl", () => { - it("shall throw when the url is in an invalid format", () => { - expect(() => validateQnaUrl(INVALID_URL)).toThrow(); - }); - it("shall returned the url as a parsed object when the url is valid", () => { - const parsed = validateQnaUrl(VALID_HOME_URL); - expect(parsed).toEqual({ program: TEST_PROGRAM, season: TEST_SEASON }); - }); -}); - -describe("Parsing Functions", () => { - it("shall parse question page urls", () => { - const parsed = parseQnaUrlWithId(VALID_QUESTION_URL); - expect(parsed).toEqual({ program: TEST_PROGRAM, season: TEST_SEASON, id: TEST_QUESTION_ID }); - }); - - it("shall parse paginated Q&A urls", () => { - const parsed = parseQnaUrlWithPage(VALID_PAGINATED_URL); - expect(parsed).toEqual({ program: TEST_PROGRAM, season: TEST_SEASON, page: TEST_PAGE_NUM }); - }); -}); - -describe("Builder Functions", () => { - it("shall build the correct home url", () => { - const url = buildHomeQnaUrl({ program: TEST_PROGRAM, season: TEST_SEASON }); - expect(url).toEqual(VALID_HOME_URL); - }); - - it("shall build the correct id url", () => { - const url = buildQnaUrlWithId({ program: TEST_PROGRAM, season: TEST_SEASON, id: TEST_QUESTION_ID }); - expect(url).toEqual(VALID_QUESTION_URL); - }); - - it("shall build the correct paginated url", () => { - const url = buildQnaUrlWithPage({ program: TEST_PROGRAM, season: TEST_SEASON, page: TEST_PAGE_NUM }); - expect(url).toEqual(VALID_PAGINATED_URL); - }); -}); diff --git a/tests/query.test.ts b/tests/query.test.ts deleted file mode 100644 index c2dcbfa..0000000 --- a/tests/query.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { getOldestUnansweredQuestion } from "../src/modules/query"; -import { - OLDEST_TEST_QUESTION_UNIQUE_DATES, - OLDEST_TEST_QUESTIONS_MIXED_OVERLAPPING_DATES, - OLDEST_TEST_QUESTIONS_OVERLAPPING_DATES, - TEST_QUESTIONS_MIXED_OVERLAPPING_DATES, - TEST_QUESTIONS_OVERLAPPING_DATES, - TEST_QUESTIONS_UNIQUE_DATES, - TEST_SEASON -} from "./data/test_questions"; -import { describe, expect, it, test } from "vitest"; - -describe("getOldestUnansweredQuestion", () => { - it("should get the oldest unanswered question when dates are unique", () => { - expect(getOldestUnansweredQuestion(TEST_QUESTIONS_UNIQUE_DATES, TEST_SEASON)).toEqual(OLDEST_TEST_QUESTION_UNIQUE_DATES); - }); - - it("should get the oldest unanswered question when dates overlap", () => { - expect(getOldestUnansweredQuestion(TEST_QUESTIONS_OVERLAPPING_DATES, TEST_SEASON)).toEqual(OLDEST_TEST_QUESTIONS_OVERLAPPING_DATES); - }); - - it("should get the oldest unanswered question when the list of questions is out of order", () => { - expect(getOldestUnansweredQuestion(TEST_QUESTIONS_MIXED_OVERLAPPING_DATES, TEST_SEASON)).toEqual(OLDEST_TEST_QUESTIONS_MIXED_OVERLAPPING_DATES); - }); -}); diff --git a/tests/rules.test.ts b/tests/rules.test.ts deleted file mode 100644 index ab95b93..0000000 --- a/tests/rules.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { extractRules } from "../src/modules/rules"; - -const MANUAL_URL = "https://content.vexrobotics.com/docs/23-24/vrc-overunder/VRC-Manual-2023-24-4.0.pdf"; - -describe("extractRules", () => { - it("shall extract all the rules from the game manual", async () => { - const rules = await extractRules(MANUAL_URL); - expect(rules).not.toHaveLength(0); - }) -}); diff --git a/tsconfig.json b/tsconfig.json index ab094fa..92701d7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,22 +1,8 @@ { - "compilerOptions": { - "target": "es2020", - "module": "Node16", - "declaration": true, - "baseUrl": "./src", - "outDir": "dist", - "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "strictFunctionTypes": true, - "strictBindCallApply": true, - "strictPropertyInitialization": true, - "noImplicitThis": true, - "alwaysStrict": true, - "resolveJsonModule": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true - }, - "include": ["src"] + "files": [], + "references": [ + { + "path": "./packages/scraper-strategies" + } + ] } From 0afa4722231e7ef43a5a7a254705211a099710cc Mon Sep 17 00:00:00 2001 From: Battlesquid <25509915+Battlesquid@users.noreply.github.com> Date: Wed, 26 Mar 2025 15:45:05 -0700 Subject: [PATCH 2/7] chore: update scraper-strategies git url --- packages/scraper-strategies/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/scraper-strategies/package.json b/packages/scraper-strategies/package.json index 59dfac9..f6abf20 100644 --- a/packages/scraper-strategies/package.json +++ b/packages/scraper-strategies/package.json @@ -4,7 +4,7 @@ "description": "Request stategies for @qnaplus/scraper", "main": "dist/index.js", "repository": { - "url": "git+ssh://git@github.com/qnaplus/scraper-strategies.git" + "url": "git+ssh://git@github.com/qnaplus/scraper.git" }, "author": "Battlesquid <25509915+Battlesquid@users.noreply.github.com>", "license": "GPL-3.0", From 2f4d24c11bddf7ff62746471c7dd577e82bbcec7 Mon Sep 17 00:00:00 2001 From: Battlesquid <25509915+Battlesquid@users.noreply.github.com> Date: Wed, 26 Mar 2025 15:46:09 -0700 Subject: [PATCH 3/7] chore: make tsconfig private --- packages/typescript-config/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index c9692d9..6f6eabb 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,5 +1,6 @@ { "name": "@qnaplus/typescript-config", + "private": true, "version": "1.0.0", "description": "", "author": "battlesqui_d", From 1509f8c784a028d91941f8d71a0ef707db8b66aa Mon Sep 17 00:00:00 2001 From: Battlesquid <25509915+Battlesquid@users.noreply.github.com> Date: Wed, 26 Mar 2025 15:47:17 -0700 Subject: [PATCH 4/7] chore: bump scraper --- packages/scraper/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/scraper/package.json b/packages/scraper/package.json index 2e373f2..7004142 100644 --- a/packages/scraper/package.json +++ b/packages/scraper/package.json @@ -1,6 +1,6 @@ { "name": "@qnaplus/scraper", - "version": "3.0.0", + "version": "3.1.0", "description": "Utility package to scrape questions from the VEX Robotics Q&A.", "main": "dist/index.js", "repository": { From 0c5ad1d684b34379f016990a2a29dd09de239cb5 Mon Sep 17 00:00:00 2001 From: Battlesquid <25509915+Battlesquid@users.noreply.github.com> Date: Wed, 26 Mar 2025 15:54:05 -0700 Subject: [PATCH 5/7] chore: update pnpm, workflows --- .github/workflows/npm-publish.yml | 4 ++-- .github/workflows/pull-request.yml | 5 ++--- package.json | 8 ++++---- packages/scraper-strategies/package.json | 3 +-- packages/scraper/package.json | 5 ++--- 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 9b6588c..b365870 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v3 - uses: pnpm/action-setup@v4 with: - version: 10 + version: 10.7.0 - uses: actions/setup-node@v3 with: node-version: 22.14.0 @@ -22,6 +22,6 @@ jobs: - run: pnpm i --frozen-lockfile - run: pnpm clean - run: pnpm build - - run: npm publish --access public + - run: pnpm -r publish --access public env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 30fc03e..f96f359 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -13,11 +13,10 @@ jobs: - uses: actions/checkout@v3 - uses: pnpm/action-setup@v4 with: - version: 10 + version: 10.7.0 - uses: actions/setup-node@v3 with: node-version: 22.14.0 - run: pnpm i --frozen-lockfile - - run: pnpm lint - - run: pnpm pretty:check + - run: pnpm neat - run: pnpm test diff --git a/package.json b/package.json index 8e94ee5..9088be5 100644 --- a/package.json +++ b/package.json @@ -15,13 +15,13 @@ "build": "tsc --build", "clean": "pnpm -r clean", "reset": "pnpm -r reset && rimraf node_modules", + "test": "pnpm -r test", "neat": "biome check .", - "neat:fix": "biome check . --write", - "test:scraper": "pnpm --filter=@qnaplus/scraper run test" + "neat:fix": "biome check . --write" }, "volta": { - "pnpm": "10.5.2", + "pnpm": "10.7.0", "node": "22.14.0" }, - "packageManager": "pnpm@10.5.2" + "packageManager": "pnpm@10.7.0" } diff --git a/packages/scraper-strategies/package.json b/packages/scraper-strategies/package.json index f6abf20..354c5c4 100644 --- a/packages/scraper-strategies/package.json +++ b/packages/scraper-strategies/package.json @@ -27,8 +27,7 @@ "pino-pretty": "catalog:" }, "volta": { - "node": "22.14.0", - "pnpm": "10.6.2" + "extends": "../../package.json" }, "files": ["dist"] } diff --git a/packages/scraper/package.json b/packages/scraper/package.json index 7004142..40b5620 100644 --- a/packages/scraper/package.json +++ b/packages/scraper/package.json @@ -11,7 +11,7 @@ "scripts": { "build": "tsc", "build:clean": "pnpm clean && pnpm build", - "test": "vitest", + "test": "vitest --run", "clean": "rimraf dist tsconfig.tsbuildinfo", "reset": "pnpm clean && rimraf node_modules" }, @@ -28,8 +28,7 @@ "vitest": "^3.0.8" }, "volta": { - "node": "22.14.0", - "pnpm": "10.6.2" + "extends": "../../package.json" }, "files": ["dist"], "exports": { From b7256a4dd18da5d4974b1cd4941cd7d4f3520c2b Mon Sep 17 00:00:00 2001 From: Battlesquid <25509915+Battlesquid@users.noreply.github.com> Date: Wed, 26 Mar 2025 15:54:23 -0700 Subject: [PATCH 6/7] chore: neat --- package.json | 2 +- packages/typescript-config/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 9088be5..acb0d3f 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "build": "tsc --build", "clean": "pnpm -r clean", "reset": "pnpm -r reset && rimraf node_modules", - "test": "pnpm -r test", + "test": "pnpm -r test", "neat": "biome check .", "neat:fix": "biome check . --write" }, diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index 6f6eabb..1f3d52c 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,6 +1,6 @@ { "name": "@qnaplus/typescript-config", - "private": true, + "private": true, "version": "1.0.0", "description": "", "author": "battlesqui_d", From 603675476e85232451af7adceee82f9d05219484 Mon Sep 17 00:00:00 2001 From: Battlesquid <25509915+Battlesquid@users.noreply.github.com> Date: Wed, 26 Mar 2025 16:02:52 -0700 Subject: [PATCH 7/7] fix: export selectors --- packages/scraper/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/scraper/src/index.ts b/packages/scraper/src/index.ts index f16b6e2..9e986b2 100644 --- a/packages/scraper/src/index.ts +++ b/packages/scraper/src/index.ts @@ -2,3 +2,4 @@ export * from "./clients"; export * from "./modules"; export * from "./util"; export * from "./types"; +export * from "./selectors";