diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 7e221e5..5eee194 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -53,10 +53,14 @@ jobs: command: yarn install --frozen-lockfile - name: Compile run: npm run build + - name: Unit tests + run: npm test - name: Run example run: cd example && node ../dist/bin.js env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Check plain file was downloaded + run: test -s example/downloaded/LICENSE.txt - name: Install Python uses: actions/setup-python@v5 with: @@ -65,3 +69,5 @@ jobs: run: cd example && node ../dist/bin.js env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Check plain file was downloaded + run: test -s example/downloaded/LICENSE.txt diff --git a/.gitignore b/.gitignore index 594c418..ccc9b20 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ yarn-error.log .idea node_modules -dist \ No newline at end of file +dist +example/downloaded diff --git a/README.md b/README.md index 81d5971..11d7e13 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,46 @@ # Additional +## Downloading plain files (no extraction) + +By default the downloaded file is extracted into the package directory. Whether a file is +an archive is detected automatically from its mime type (resolved from the url via +[mime-types](https://www.npmjs.com/package/mime-types)): `application/gzip`, +`application/x-tar` and `application/zip` (`.tar.gz`, `.tgz`, `.tar`, `.zip`) are +extracted, anything else - a `.jar`, a `.node`, a bare binary - is downloaded as is. + +For a file that is not extracted you must specify `dst` - a destination path relative to +the package directory. Missing directories are created, escaping the package directory is +not allowed. + +```json +{ + "resources": { + "files": [{ + "host": "https://repo1.maven.org/maven2/", + "path": "org/slf4j/slf4j-api/${slf4j_version}/slf4j-api-${slf4j_version}.jar", + "dst": "lib/slf4j.jar" + }] + } +} +``` + +`dst` supports the same variables as `host` & `path`. + +Detection can be overridden with `extract`: + +```json +{ + "host": "https://example.com/", + "path": "bundle.tar.gz", + "extract": false, + "dst": "vendor/bundle.tar.gz" +} +``` + +For archives `dst` is ignored (they are always extracted into the package directory). + + ## Constraints Variables and files supports contstraints, you can define it: diff --git a/example/package.json b/example/package.json index 37add26..a22a7ad 100644 --- a/example/package.json +++ b/example/package.json @@ -34,6 +34,11 @@ "host": "github_artifact://cube-js/post-installer/actions/current", "name": "native-${platform}-${arch}-${libc}-${libpython_version}.node", "not_found": "Your system is not supported by @cubejs-backend/native, some feature will be unavailable." + }, + { + "host": "https://raw.githubusercontent.com/", + "path": "cube-js/post-installer/master/LICENSE", + "dst": "downloaded/LICENSE.txt" } ] } diff --git a/package.json b/package.json index 5e016f7..e8162b5 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "build": "tsc", "tsc": "tsc --build", "tsc:watch": "tsc --build --watch", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "vitest run" }, "engines": { "node": ">=20.0.0" @@ -22,13 +22,16 @@ "license": "Apache-2.0", "devDependencies": { "@tsconfig/node20": "^20.1.6", + "@types/mime-types": "^3.0.1", "@types/node": "^20", - "typescript": "^5.0.4" + "typescript": "^5.0.4", + "vitest": "^3" }, "dependencies": { "@cubejs-backend/shared": "1.7.42", "@octokit/core": "^5", "@octokit/plugin-rest-endpoint-methods": "^10", + "mime-types": "^3.0.2", "source-map-support": "^0.5.21" }, "publishConfig": { diff --git a/src/index.ts b/src/index.ts index 72e84cc..cba6825 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,248 +3,84 @@ import "source-map-support/register"; import { - detectLibc, displayCLIError, displayCLIWarning, downloadAndExtractFile, - libraryExists, - LibraryExistsResult, } from "@cubejs-backend/shared"; import * as process from "process"; import * as fs from "fs"; import * as path from "path"; +import { + resolveConstraints, + resolveDst, + resolvePath, + resolveVars, +} from "./resolve"; const packageContent = fs.readFileSync( path.join(process.cwd(), "package.json"), - "utf8" + "utf8", ); const pkg = JSON.parse(packageContent); -interface UrlVariable { - resolve(url: string): string; -} - -function resolveConstraint(name: string, constraintDetails: any): boolean { - if (name === "platform") { - return constraintDetails.includes(process.platform); - } - - if (name === "arch") { - return constraintDetails.includes(process.arch); - } - - if (name === "platform-arch") { - return constraintDetails.includes(`${process.platform}-${process.arch}`); - } - - displayCLIWarning(`Unknown constraint name: ${name}, pass: false`); - - return false; -} - -function resolveVariableValue(value: any): string | false { - if (Array.isArray(value) && value.length == 2) { - const [valueName, supportedVersions] = value; - if (valueName === "libpython") { - for (const version of supportedVersions) { - if ( - libraryExists(`libpython${version}`) === LibraryExistsResult.Exists - ) { - return version; - } - } - - return false; - } - } - - if (Array.isArray(value) && value.length == 2) { - const [valueName, env_name] = value; - if (valueName === "env") { - return process.env[env_name] || false; - } - } - - if (value === "libc") { - return resolveLibc(); - } - - displayCLIWarning(`Unable to resolve value, unknown value ${value}`); - - return false; -} - -function resolveConstraints(section: any): boolean { - let constraintPass = true; - - if (section.constraints) { - for (const [constraintName, constraintDetails] of Object.entries( - section.constraints - )) { - if (!resolveConstraint(constraintName, constraintDetails)) { - constraintPass = false; - break; - } - } - } - - return constraintPass; -} - -function resolveVars(variables: Record): UrlVariable[] { - const res = []; - - for (const [variableName, variable] of Object.entries(variables)) { - let value: string | null = null; - - let constraintPass = resolveConstraints(variable); - if (constraintPass) { - if (variable.value) { - const resolvedValue = resolveVariableValue(variable.value); - if (resolvedValue) { - value = resolvedValue; - } - } - } - - if (!value) { - if ("default" in variable) { - value = variable["default"]; - } else { - throw new Error(`Unable to resolve variable ${variableName}`); - } - } - - res.push({ - resolve(url: string): string { - url = url.replace("${" + variableName + "}", value as string); - - return url; - }, - }); - } - - return res; -} - -function resolveLibc(): string { - if (process.platform === "linux") { - return detectLibc() === "gnu" ? "glibc" : "musl"; - } - - return "unknown"; -} - -import { Octokit } from "@octokit/core"; -import { restEndpointMethods } from "@octokit/plugin-rest-endpoint-methods"; - -function resolveSimplePath(path: string, variables: UrlVariable[]): string { - path = path.replace("${version}", pkg.version); - path = path.replace("${platform}", process.platform); - path = path.replace("${arch}", process.arch); - path = path.replace("${libc}", resolveLibc()); - - for (const variable of variables) { - path = variable.resolve(path); - } - - return path; -} - -async function resolveGithubArtifactPath( - url: string, - name: string, - variables: UrlVariable[] -): Promise<{ url: string; name: string }> { - const extractParamsRegexp = - /github_artifact:\/\/(?[a-z-]+)\/(?[a-z-]+)\/actions\/(?[a-zA-Z${}]+)/; - - const params = url.match(extractParamsRegexp); - - const MyOctokit = Octokit.plugin(restEndpointMethods); - const ghClient = new MyOctokit({ - auth: process.env.GH_TOKEN, - }); - - if (!params || !("groups" in params)) { - throw new Error("Unable to decode url from github_artifact protocol"); - } - - const listWorkflowRunArtifacts = - await ghClient.rest.actions.listWorkflowRunArtifacts({ - owner: params.groups?.owner as any, - repo: params.groups?.repo as any, - run_id: process.env.GITHUB_RUN_ID as any, - }); - - const resolvedName = resolveSimplePath(name, variables); - const artifactToDownload = listWorkflowRunArtifacts.data.artifacts.find( - (artifact) => artifact.name === resolvedName - ); - if (!artifactToDownload) { - throw new Error(`Artifact '${resolvedName}' doesn't exist`); - } - - const arhiveUrl = await ghClient.rest.actions.downloadArtifact({ - owner: params.groups?.owner as any, - repo: params.groups?.repo as any, - artifact_id: artifactToDownload.id, - archive_format: "zip", - }); - - return { - url: arhiveUrl.url, - name: resolvedName, - }; -} - -async function resolvePath( - file: any, - variables: UrlVariable[] -): Promise<{ url: string; name: string }> { - if (file.host.startsWith("github_artifact://")) { - return resolveGithubArtifactPath(file.host, file.name, variables); - } else if ( - file.host.startsWith("http://") || - file.host.startsWith("https://") - ) { - const url = resolveSimplePath(file.host + file.path, variables); - - return { - url, - // Use the same - name: url, - }; - } else { - throw new Error(`Unsupported protocol in path: ${path}`); - } -} - (async () => { try { if (!pkg.resources) { throw new Error( - "Please defined resources section in package.json file in corresponding package" + "Please defined resources section in package.json file in corresponding package", ); } + const cwd = process.cwd(); const variables = resolveVars(pkg.resources.vars || []); for (const file of pkg.resources.files) { - const toDownload = await resolvePath(file, variables); + if (!resolveConstraints(file)) { + console.log( + `Skiping downloading for ${ + file.name || file.path || file.host + }: constraints failed`, + ); + + continue; + } + + const toDownload = await resolvePath(file, variables, pkg.version); + const dst = resolveDst(file, variables, pkg.version, cwd); + + if (toDownload.extract) { + if (dst) { + displayCLIWarning( + `dst is ignored for ${toDownload.name}, because it is extracted into the package directory`, + ); + } - let constraintPass = resolveConstraints(file); - if (constraintPass) { console.log(`Downloading: ${toDownload.name}`); await downloadAndExtractFile(toDownload.url, { - cwd: process.cwd(), + cwd, showProgress: true, }); } else { - console.log( - `Skiping downloading for ${toDownload.name}: constraints failed` - ); + if (!dst) { + throw new Error( + `dst is required for ${toDownload.name}, because it is downloaded without extraction`, + ); + } + + // downloadAndExtractFile creates cwd, but not subdirectories of dstFileName + fs.mkdirSync(path.dirname(path.resolve(cwd, dst)), { + recursive: true, + }); + + console.log(`Downloading: ${toDownload.name} -> ${dst}`); + + await downloadAndExtractFile(toDownload.url, { + cwd, + showProgress: true, + skipExtract: true, + dstFileName: dst, + }); } } } catch (e: any) { diff --git a/src/resolve.ts b/src/resolve.ts new file mode 100644 index 0000000..9c3883a --- /dev/null +++ b/src/resolve.ts @@ -0,0 +1,323 @@ +import { + detectLibc, + displayCLIWarning, + libraryExists, + LibraryExistsResult, +} from "@cubejs-backend/shared"; +import { Octokit } from "@octokit/core"; +import { restEndpointMethods } from "@octokit/plugin-rest-endpoint-methods"; +import * as process from "process"; +import * as path from "path"; +import { URL } from "url"; +import * as mime from "mime-types"; + +export interface UrlVariable { + resolve(url: string): string; +} + +export interface ResolvedFile { + url: string; + name: string; + extract: boolean; +} + +export function resolveLibc(): string { + if (process.platform === "linux") { + return detectLibc() === "gnu" ? "glibc" : "musl"; + } + + return "unknown"; +} + +export function resolveConstraint( + name: string, + constraintDetails: any, +): boolean { + if (name === "platform") { + return constraintDetails.includes(process.platform); + } + + if (name === "arch") { + return constraintDetails.includes(process.arch); + } + + if (name === "platform-arch") { + return constraintDetails.includes(`${process.platform}-${process.arch}`); + } + + displayCLIWarning(`Unknown constraint name: ${name}, pass: false`); + + return false; +} + +export function resolveConstraints(section: any): boolean { + let constraintPass = true; + + if (section.constraints) { + for (const [constraintName, constraintDetails] of Object.entries( + section.constraints, + )) { + if (!resolveConstraint(constraintName, constraintDetails)) { + constraintPass = false; + break; + } + } + } + + return constraintPass; +} + +export function resolveVariableValue(value: any): string | false { + if (Array.isArray(value) && value.length == 2) { + const [valueName, supportedVersions] = value; + if (valueName === "libpython") { + for (const version of supportedVersions) { + if ( + libraryExists(`libpython${version}`) === LibraryExistsResult.Exists + ) { + return version; + } + } + + return false; + } + } + + if (Array.isArray(value) && value.length == 2) { + const [valueName, env_name] = value; + if (valueName === "env") { + return process.env[env_name] || false; + } + } + + if (value === "libc") { + return resolveLibc(); + } + + displayCLIWarning(`Unable to resolve value, unknown value ${value}`); + + return false; +} + +export function resolveVars(variables: Record): UrlVariable[] { + const res = []; + + for (const [variableName, variable] of Object.entries(variables)) { + let value: string | null = null; + + let constraintPass = resolveConstraints(variable); + if (constraintPass) { + if (variable.value) { + const resolvedValue = resolveVariableValue(variable.value); + if (resolvedValue) { + value = resolvedValue; + } + } + } + + if (!value) { + if ("default" in variable) { + value = variable["default"]; + } else { + throw new Error(`Unable to resolve variable ${variableName}`); + } + } + + res.push({ + resolve(url: string): string { + url = url.replace("${" + variableName + "}", value as string); + + return url; + }, + }); + } + + return res; +} + +export function resolveSimplePath( + input: string, + variables: UrlVariable[], + version: string, +): string { + input = input.replace("${version}", version); + input = input.replace("${platform}", process.platform); + input = input.replace("${arch}", process.arch); + input = input.replace("${libc}", resolveLibc()); + + for (const variable of variables) { + input = variable.resolve(input); + } + + return input; +} + +// mime-db has no entry for the compressed-tar shorthands +const EXTRA_MIME_TYPES: Record = { + tgz: "application/gzip", + tbz2: "application/x-bzip2", + txz: "application/x-xz", +}; + +// Formats extractArchive() from @cubejs-backend/shared is able to unpack. +// Zip containers that are consumed as a single file (jar, whl, apk, ...) are +// deliberately not here, they have their own mime types. +const EXTRACTABLE_MIME_TYPES = [ + "application/gzip", + "application/x-gzip", + "application/x-tar", + "application/zip", +]; + +export function parseUrl(url: string): URL | null { + try { + return new URL(url); + } catch (e) { + return null; + } +} + +export function detectMimeType(url: string): string | false { + // pathname keeps the query string and the hash out of the extension lookup + const parsed = parseUrl(url); + const pathname = parsed ? decodeURIComponent(parsed.pathname) : url; + const extension = path.extname(pathname).toLowerCase().slice(1); + + return EXTRA_MIME_TYPES[extension] || mime.lookup(pathname); +} + +// Detected from the resolved url, because the downloaded file is saved under a +// random name without an extension, and extractArchive throws on anything it +// doesn't recognize as an archive. +export function looksLikeArchive(url: string): boolean { + const mimeType = detectMimeType(url); + + return mimeType !== false && EXTRACTABLE_MIME_TYPES.includes(mimeType); +} + +export function resolveDst( + file: any, + variables: UrlVariable[], + version: string, + cwd: string, +): string | null { + if (!file.dst) { + return null; + } + + const dst = resolveSimplePath(file.dst, variables, version); + const root = path.resolve(cwd); + const target = path.resolve(root, dst); + + if (target === root || !target.startsWith(root + path.sep)) { + throw new Error(`dst must stay inside the package directory, got: ${dst}`); + } + + return dst; +} + +export const GITHUB_ARTIFACT_PROTOCOL = "github_artifact://"; +// WHATWG URL rejects "_" in a scheme, so it is swapped for a valid one before parsing +const GITHUB_ARTIFACT_PARSABLE_PROTOCOL = "github-artifact://"; + +// github_artifact:////actions/ +export function parseGithubArtifactUrl(url: string): { + owner: string; + repo: string; +} { + const parsed = parseUrl( + GITHUB_ARTIFACT_PARSABLE_PROTOCOL + + url.slice(GITHUB_ARTIFACT_PROTOCOL.length), + ); + const segments = parsed ? parsed.pathname.split("/").filter(Boolean) : []; + const owner = parsed?.hostname; + const [repo, actions, workflow] = segments; + + if (!owner || !repo || actions !== "actions" || !workflow) { + throw new Error( + `Unable to decode url from github_artifact protocol, expected ` + + `${GITHUB_ARTIFACT_PROTOCOL}//actions/, got: ${url}`, + ); + } + + return { owner, repo }; +} + +export async function resolveGithubArtifactPath( + url: string, + name: string, + variables: UrlVariable[], + version: string, +): Promise<{ url: string; name: string }> { + const { owner, repo } = parseGithubArtifactUrl(url); + + const MyOctokit = Octokit.plugin(restEndpointMethods); + const ghClient = new MyOctokit({ + auth: process.env.GH_TOKEN, + }); + + const listWorkflowRunArtifacts = + await ghClient.rest.actions.listWorkflowRunArtifacts({ + owner, + repo, + run_id: process.env.GITHUB_RUN_ID as any, + }); + + const resolvedName = resolveSimplePath(name, variables, version); + const artifactToDownload = listWorkflowRunArtifacts.data.artifacts.find( + (artifact) => artifact.name === resolvedName, + ); + if (!artifactToDownload) { + throw new Error(`Artifact '${resolvedName}' doesn't exist`); + } + + const arhiveUrl = await ghClient.rest.actions.downloadArtifact({ + owner, + repo, + artifact_id: artifactToDownload.id, + archive_format: "zip", + }); + + return { + url: arhiveUrl.url, + name: resolvedName, + }; +} + +export async function resolvePath( + file: any, + variables: UrlVariable[], + version: string, +): Promise { + const extractOverride = + typeof file.extract === "boolean" ? file.extract : null; + + if (file.host.startsWith(GITHUB_ARTIFACT_PROTOCOL)) { + const resolved = await resolveGithubArtifactPath( + file.host, + file.name, + variables, + version, + ); + + return { + ...resolved, + // GitHub always packs artifacts into a zip + extract: extractOverride ?? true, + }; + } else if ( + file.host.startsWith("http://") || + file.host.startsWith("https://") + ) { + const url = resolveSimplePath(file.host + file.path, variables, version); + + return { + url, + // Use the same + name: url, + extract: extractOverride ?? looksLikeArchive(url), + }; + } else { + throw new Error(`Unsupported protocol in path: ${file.host}`); + } +} diff --git a/tests/resolve.test.ts b/tests/resolve.test.ts new file mode 100644 index 0000000..d63b4eb --- /dev/null +++ b/tests/resolve.test.ts @@ -0,0 +1,251 @@ +import * as path from "path"; +import { describe, expect, it } from "vitest"; + +import { + detectMimeType, + looksLikeArchive, + parseGithubArtifactUrl, + resolveConstraints, + resolveDst, + resolvePath, + resolveSimplePath, + resolveVars, + UrlVariable, +} from "../src/resolve"; + +const VERSION = "1.2.3"; + +describe("looksLikeArchive", () => { + it.each([ + "https://example.com/native.tar.gz", + "https://example.com/native.tgz", + "https://example.com/native.TGZ", + "https://example.com/native.tar", + "https://example.com/native.zip", + "https://example.com/native.zip?token=secret", + "https://example.com/native.zip#fragment", + ])("extracts %s", (url) => { + expect(looksLikeArchive(url)).toBe(true); + }); + + it.each([ + // a zip container, but consumed as a single file + "https://example.com/driver.jar", + "https://example.com/native.node", + "https://example.com/libnative.so", + "https://example.com/pkg-1.0-py3-none-any.whl", + // no extension at all + "https://example.com/cube-js/post-installer/zip/refs/heads/master", + // supported by neither extractArchive nor us + "https://example.com/native.tar.bz2", + ])("downloads %s as is", (url) => { + expect(looksLikeArchive(url)).toBe(false); + }); + + it("does not take the extension from the query string", () => { + expect(detectMimeType("https://example.com/download?file=x.zip")).toBe( + false, + ); + }); + + it("falls back to the raw string when the url is unparsable", () => { + expect(detectMimeType("not a url at all/native.zip")).toBe( + "application/zip", + ); + }); +}); + +describe("parseGithubArtifactUrl", () => { + it("parses owner and repo", () => { + expect( + parseGithubArtifactUrl( + "github_artifact://cube-js/post-installer/actions/current", + ), + ).toEqual({ owner: "cube-js", repo: "post-installer" }); + }); + + it("keeps uppercase and allows underscores, unlike the previous regexp", () => { + expect( + parseGithubArtifactUrl( + "github_artifact://Cube-JS/post_installer2/actions/current", + ), + ).toEqual({ owner: "Cube-JS", repo: "post_installer2" }); + }); + + it.each([ + "github_artifact://cube-js/post-installer", + "github_artifact://cube-js/post-installer/runs/current", + "github_artifact://cube-js/post-installer/actions", + "github_artifact://", + ])("throws on %s", (url) => { + expect(() => parseGithubArtifactUrl(url)).toThrowError( + /Unable to decode url from github_artifact protocol/, + ); + }); +}); + +describe("resolveSimplePath", () => { + it("substitutes the built-in variables", () => { + expect( + resolveSimplePath( + "native-${version}-${platform}-${arch}.tar.gz", + [], + VERSION, + ), + ).toBe(`native-${VERSION}-${process.platform}-${process.arch}.tar.gz`); + }); + + it("substitutes user defined variables", () => { + const variables = resolveVars({ + libpython_version: { default: "fallback" }, + }); + + expect( + resolveSimplePath("native-${libpython_version}.node", variables, VERSION), + ).toBe("native-fallback.node"); + }); +}); + +describe("resolveVars", () => { + it("falls back to the default when there is no value", () => { + const variables = resolveVars({ feature: { default: "off" } }); + + expect(resolveSimplePath("${feature}", variables, VERSION)).toBe("off"); + }); + + it("reads a value from an env variable", () => { + process.env.POST_INSTALLER_TEST_VAR = "on"; + + try { + const variables = resolveVars({ + feature: { default: "off", value: ["env", "POST_INSTALLER_TEST_VAR"] }, + }); + + expect(resolveSimplePath("${feature}", variables, VERSION)).toBe("on"); + } finally { + delete process.env.POST_INSTALLER_TEST_VAR; + } + }); + + it("uses the default when the constraints do not pass", () => { + const variables = resolveVars({ + feature: { + default: "off", + value: ["env", "PATH"], + constraints: { platform: ["definitely-not-a-platform"] }, + }, + }); + + expect(resolveSimplePath("${feature}", variables, VERSION)).toBe("off"); + }); + + it("throws when a variable cannot be resolved and has no default", () => { + expect(() => + resolveVars({ feature: { value: ["env", "POST_INSTALLER_MISSING"] } }), + ).toThrowError("Unable to resolve variable feature"); + }); +}); + +describe("resolveConstraints", () => { + it("passes when there are no constraints", () => { + expect(resolveConstraints({})).toBe(true); + }); + + it("matches platform, arch and platform-arch", () => { + expect( + resolveConstraints({ + constraints: { + platform: [process.platform], + arch: [process.arch], + "platform-arch": [`${process.platform}-${process.arch}`], + }, + }), + ).toBe(true); + }); + + it("fails when one of the constraints does not match", () => { + expect( + resolveConstraints({ + constraints: { platform: [process.platform], arch: ["pdp11"] }, + }), + ).toBe(false); + }); + + it("fails on an unknown constraint", () => { + expect(resolveConstraints({ constraints: { os: ["linux"] } })).toBe(false); + }); +}); + +describe("resolveDst", () => { + const cwd = path.resolve("/tmp/post-installer-tests"); + + it("returns null when dst is not set", () => { + expect(resolveDst({}, [], VERSION, cwd)).toBeNull(); + }); + + it("substitutes variables", () => { + expect( + resolveDst({ dst: "lib/native-${version}.jar" }, [], VERSION, cwd), + ).toBe(`lib/native-${VERSION}.jar`); + }); + + it.each(["../evil.jar", "lib/../../evil.jar", "/etc/evil.jar", "."])( + "rejects %s", + (dst) => { + expect(() => resolveDst({ dst }, [], VERSION, cwd)).toThrowError( + /dst must stay inside the package directory/, + ); + }, + ); +}); + +describe("resolvePath", () => { + const variables: UrlVariable[] = []; + + it("marks an archive as extractable", async () => { + await expect( + resolvePath( + { host: "https://example.com/", path: "native-${version}.tar.gz" }, + variables, + VERSION, + ), + ).resolves.toEqual({ + url: `https://example.com/native-${VERSION}.tar.gz`, + name: `https://example.com/native-${VERSION}.tar.gz`, + extract: true, + }); + }); + + it("marks a plain file as not extractable", async () => { + const resolved = await resolvePath( + { host: "https://example.com/", path: "driver.jar" }, + variables, + VERSION, + ); + + expect(resolved.extract).toBe(false); + }); + + it.each([ + { extract: false, path: "native.tar.gz" }, + { extract: true, path: "driver.jar" }, + ])("honours an explicit extract: $extract", async ({ extract, path }) => { + const resolved = await resolvePath( + { host: "https://example.com/", path, extract }, + variables, + VERSION, + ); + + expect(resolved.extract).toBe(extract); + }); + + it("throws on an unsupported protocol", async () => { + await expect( + resolvePath( + { host: "ftp://example.com/", path: "x.zip" }, + variables, + VERSION, + ), + ).rejects.toThrowError("Unsupported protocol in path: ftp://example.com/"); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index b0b0e46..04538c7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,6 @@ { "extends": "@tsconfig/node20/tsconfig.json", + "include": ["src"], "compilerOptions": { "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ diff --git a/yarn.lock b/yarn.lock index fd2011f..fe16f2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,6 +25,136 @@ throttle-debounce "^3.0.1" uuid "^11.1.1" +"@esbuild/aix-ppc64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz#bf6e10303bcf2e7c686975fa52f937ec2728d8bc" + integrity sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ== + +"@esbuild/android-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz#0c6246bc8d2c4d172aac2db3fb1190d72bd65504" + integrity sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A== + +"@esbuild/android-arm@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.28.2.tgz#2d84ece6a4e2684d92be26ee13d42757d831c381" + integrity sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg== + +"@esbuild/android-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.28.2.tgz#fc38d4d6358d8dc1cf53f09f7589fe436eb64801" + integrity sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q== + +"@esbuild/darwin-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz#f83afeeac1d7dac01c7a2fd012b3e451a0591fcc" + integrity sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw== + +"@esbuild/darwin-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz#510147c055a795588dbbe14fd6b1b8ad0a2f30de" + integrity sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw== + +"@esbuild/freebsd-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz#093b9200ecf0b115ba4e5e248a7485c9c5f8bd5e" + integrity sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw== + +"@esbuild/freebsd-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz#0be22b6df925d213e841ea87123af5df80b0faf7" + integrity sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg== + +"@esbuild/linux-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz#1bdbc651cda9ba9995c53ed9c71ceaa65094762d" + integrity sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug== + +"@esbuild/linux-arm@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz#beb12ad72b84f72d28488cc1b8ee9f7eb141d753" + integrity sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w== + +"@esbuild/linux-ia32@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz#b81f9d55529b45c206a46a138214b1aa6879696b" + integrity sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ== + +"@esbuild/linux-loong64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz#598667241a04c99b76ed6ef940ac50038c419f98" + integrity sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ== + +"@esbuild/linux-mips64el@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz#1c51eb9cea903f53d97b5af3b1841db70f5596ca" + integrity sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA== + +"@esbuild/linux-ppc64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz#63dd61f17ceb31a81227f413feac8a71bc2c51f2" + integrity sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ== + +"@esbuild/linux-riscv64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz#3763b08fde5cf25ab1facb8e7752edfe45fbfc27" + integrity sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA== + +"@esbuild/linux-s390x@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz#1a137ff293a82906eb3176385bd7e8e0e5cfb7cb" + integrity sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg== + +"@esbuild/linux-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz#268b36211c146ca54f8fe12c578a8d6ef8979485" + integrity sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ== + +"@esbuild/netbsd-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz#22571ad951d62bb6accc82d8d1fad5c8c1ac0ba1" + integrity sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw== + +"@esbuild/netbsd-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz#42fcc57297eb0a0ca3f5fc475291f4c1a3f7c0de" + integrity sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw== + +"@esbuild/openbsd-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz#9eb32af104ac3dacf4edca01f596664aab0c73ef" + integrity sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ== + +"@esbuild/openbsd-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz#febed2402d6088225e91f20fb4ce2522ad0a4efd" + integrity sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw== + +"@esbuild/openharmony-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz#85641c3d466428bfbccea5f21c26836663fef5ce" + integrity sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q== + +"@esbuild/sunos-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz#a736f9d8962481045fc4c3e54f5479f22c870fb4" + integrity sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g== + +"@esbuild/win32-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz#ee5ab40fad186201b652a33f8a5eb149e9e42532" + integrity sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ== + +"@esbuild/win32-ia32@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz#c40d28a6d99a127da6711f2afd74b11cb63b06a7" + integrity sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA== + +"@esbuild/win32-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz#b21affb804cc167c133d95f45b3a1dc1323b9a87" + integrity sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g== + "@isaacs/fs-minipass@^4.0.0": version "4.0.1" resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32" @@ -32,6 +162,16 @@ dependencies: minipass "^7.0.4" +"@jridgewell/sourcemap-codec@^1.5.5": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz#f4c663e862f06dc98ca4d453862c46902789a18d" + integrity sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw== + +"@napi-rs/lzma-linux-x64-gnu@1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz#e57d4306966078662038094fb38eb9146dc3aea9" + integrity sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ== + "@oclif/color@^1.0.0": version "1.0.13" resolved "https://registry.yarnpkg.com/@oclif/color/-/color-1.0.13.tgz#91a5c9c271f686bb72ce013e67fa363ddaab2f43" @@ -128,6 +268,131 @@ dependencies: "@octokit/openapi-types" "^22.2.0" +"@rollup/rollup-android-arm-eabi@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.63.4.tgz#e1d06062fb451578b3fb0bdea3360daaa1395f44" + integrity sha512-I+BSHzTAhKN2n7ZwGZsegGcZjDpLqFOMAtJz/u6uFGe0pUFbq56dEHjqJV/ZUdRJtNXNxA+hREUatZBvMR3Oiw== + +"@rollup/rollup-android-arm64@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.63.4.tgz#2e81dec4e9e879c95c8266e30da67074c4998224" + integrity sha512-pu3BdjS2LtEzRu2elmGzS3fIeWSZy4BMDIaLNwjorO76+k2d0LMluijhsDx3KQyQBQ/lLUZCQA9/s6csvUfuhw== + +"@rollup/rollup-darwin-arm64@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.63.4.tgz#f48f92f44454aed23d013f7cdb6da0dc2cb598ae" + integrity sha512-xfSrj9MHnWK9GaSqT9U0ImHtH/N8WZlHLx4cZHiuLcqs640hvZ3hLPd5UR2AZS57FaE8HrRUSpltbZdWRxHiDA== + +"@rollup/rollup-darwin-x64@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.63.4.tgz#39b0b2ad27c49b40aec71fb20210e2e3be5fdbd0" + integrity sha512-bqU99PLJb/dqb3S0GIMdeuyAEETSUgZBoqXYd3Sd+WCsV+MmPhnN6JrotWyir31+QgH7EvvE5/mwGJlEoci8Fw== + +"@rollup/rollup-freebsd-arm64@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.63.4.tgz#0c85d18f5b9228b7195adbbbc97c1adaf41b8106" + integrity sha512-JinsFZ5G40oXQb+sUuiA5x689vhr6dDYK0H0NL+rwKdL6CqnmYN8PE4ZwfRSoIjrCxqTQG/SLfTtSvHeGxoVlw== + +"@rollup/rollup-freebsd-x64@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.63.4.tgz#0c6c27471ea950213aad76418f075c96f57e9533" + integrity sha512-GAdA4UxpiNm27cLHr2GqXBpAD0x9FqwYBY7/YSP0Ss0/PNi4k8gbviqpIpYbVSRBaS2ZcegXEzgTQMbRNCwxCw== + +"@rollup/rollup-linux-arm-gnueabihf@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.63.4.tgz#28cba40d417fb3d2c1536941b02143a2bdda72be" + integrity sha512-qDd6NoA1znaLjp4jR5U/KWCdLAKDJNB8W9ChbbDaKbo0xA+Atln5HK6LFCZ4oJQpemtRZA288DCirFRjrspptw== + +"@rollup/rollup-linux-arm-musleabihf@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.63.4.tgz#c9f06aa876d6d312012a2048d9e5533c581a7341" + integrity sha512-WtB5Tz5KTNINb8ZA+8sQ7bmjuS1JrRT7YverYIhUGdWWDlpzVWmIwuZE+jidkEXUn1l0zrEkaIMa8dHF3NGcsA== + +"@rollup/rollup-linux-arm64-gnu@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.63.4.tgz#b26376804ca32b3dcc8f68930f765394fb4e4814" + integrity sha512-VcQ3L1tjnkKzWjryAVaFhHEWcqOfICX9uxVVoDzm2t0DpgKRHd2zOpVrJc0xsWeBZcBFyYROCIBdyR/fS174pg== + +"@rollup/rollup-linux-arm64-musl@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.63.4.tgz#65f6f5deee9d30904b4d52ee3d45679055743cd1" + integrity sha512-6+ZQX6P5s0cMDN2Ypb8Lbm2+/sZYmZjdaYny992ujUU9UKi/4CWoJWsl1pNvjWJHNHGK51m+jKGLlh1ylb2ifQ== + +"@rollup/rollup-linux-loong64-gnu@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.63.4.tgz#15d7e44538e967a3d6132f5b9f27f02346df6850" + integrity sha512-D72ZnvkFkBXOfzMMQLcwfPLyGkKb7HZ9/mf97B7v6/P5Lbv4oFOtSY/uHbS8lH6uKUOxoKiuokdb50XZSzzbJw== + +"@rollup/rollup-linux-loong64-musl@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.63.4.tgz#7afad2b9e41941344883154f754b7f772ef16b01" + integrity sha512-piU6BxeqA3O9KSu3kRCIQQtNqFFaTu21SEV4FwaRZowpnj3bLaWPZHw+xFqCs0XlJ+aOH3PTRWGoglH+mKA/OA== + +"@rollup/rollup-linux-ppc64-gnu@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.63.4.tgz#3f3131b1a9585851b2875c86a49f6e6deb9e68e0" + integrity sha512-/5PGpHwqt2EEEOUs1XwzubE/ucr0dWDQ+to3zqi4Ds7EWpwtQ79wXc4JBoxqj/OwpawTsKWzJxHfSuBOq3DrWA== + +"@rollup/rollup-linux-ppc64-musl@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.63.4.tgz#463aeee26c62983c1fc235708d1b41baf4735f98" + integrity sha512-cX3beZDLWt7G2oJF+nhChiT+qtaihs+S2xi7ziGmVB+2pwPng6D0Ed0HmElQOgv2UsUmSJJLGwpBao/3TDx3VA== + +"@rollup/rollup-linux-riscv64-gnu@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.63.4.tgz#cb495bd8cc978e17593e0d323b36fd95b5eab098" + integrity sha512-1uz2mGWHyptR7DgHHrlbdRAjXK7v7elGZ9lMja910/RP+ZYbX6xAmCiU9UZSX4hqmgtHMv6lr5l3kq1HIOpcag== + +"@rollup/rollup-linux-riscv64-musl@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.63.4.tgz#655b69144b1e786e0bf8ac3b727f0d7fee590a08" + integrity sha512-nLS8topojxyz7SRpKR2IODRpQ0XPZ+xaOXvT3+hqK/Uy8Lo5HFgkkIBiIrCu5tL5YqzTvgovGw55PwpahTAGig== + +"@rollup/rollup-linux-s390x-gnu@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.63.4.tgz#70b175b0361a7898acc294a6b14001e2c3ad99be" + integrity sha512-gs7DRKotr3l3q+jGPQBjH0ng1FjlEDm5ueQrkw5JtQvtLyEIcLASqAEaor56BhkKRzk+IcQzrcanBdb/bBQn8g== + +"@rollup/rollup-linux-x64-gnu@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.63.4.tgz#0c68fa212df249f996b2d75e8fbb3766b1582ee8" + integrity sha512-791ET7W17NnScOZM7h4dX5hYspxE28htPFsb1awY/NRR8+PRNkS53e475rDdxXXDrP+kwnCcNWg9CX5ztn/Aqw== + +"@rollup/rollup-linux-x64-musl@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.63.4.tgz#93af6206edf751469a43c3614164360136540838" + integrity sha512-iwZQRcmj7g88g3tzefIrQY7qvmuA/cfYwhrDtTBhsmukO4U2huVO5W+86XacUMRvdSFVAc6kZUZy21JaRwiB9w== + +"@rollup/rollup-openbsd-x64@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.63.4.tgz#7c7680c4004fd602b59cd19f3294fa1b89d0c683" + integrity sha512-dVHFp9gRWrdTpnqQuGfCwd7hOQDatK1VCP2iWhLY/cGrOQs/ucFzJ6A5SRqbXX12ZDI8EUuejSM5kwg+ja7Png== + +"@rollup/rollup-openharmony-arm64@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.63.4.tgz#f389ff4d8ee8a635ff51d76e8ff20b7db2292bce" + integrity sha512-t3NlauOW6gxZVVFcBEnO62Cb4wbyDFL416gTg1uFI/2tgqYQlf69FbSE115Ajre9I+c26Lk4mcmdFUsS/DGifQ== + +"@rollup/rollup-win32-arm64-msvc@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.63.4.tgz#55a286f40f9d03c653ceb7183d6c6179ec312c75" + integrity sha512-xWuIaSye5FWZF8+UYtVEcHtRJDN5kN9Kfgxx3Kq8XIov9KSKbc1fiqQCm90SKrgQbUXZelbnUhnlUJmfSE7P9A== + +"@rollup/rollup-win32-ia32-msvc@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.63.4.tgz#7eb577b64e2a39115182a87a2ea957608d8331f6" + integrity sha512-9ALJJUOg/ZflMJepVo2PlgsGxSaxN7SQ4Z8GoZfVlarWr6r3rkHUNsd/zAio7p4YMtChSMXPionxej4Hkf6CXQ== + +"@rollup/rollup-win32-x64-gnu@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.63.4.tgz#0e7a7cd5f0db2f570fc312687d67baf21283a3f6" + integrity sha512-blj9z5qx/Pv4WU0W1NMFDB97e0JH5ed+aZGywW8WCvp/NhWX/4PFAq5uu6Q0AebNn+Vo6KzUYDT++JzTT5ojlQ== + +"@rollup/rollup-win32-x64-msvc@4.63.4": + version "4.63.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.63.4.tgz#f8e11d8ac827db7695d50f1def4c00a7f3cd1510" + integrity sha512-Erx822VRBwLa124shbj+wNXe//BOgMEctDV0m1aqTQdNO1S69DgNUCFKC1RCeZfixs1J31l6igk1ziyXErbigQ== + "@tootallnate/quickjs-emscripten@^0.23.0": version "0.23.0" resolved "https://registry.yarnpkg.com/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz#db4ecfd499a9765ab24002c3b696d02e6d32a12c" @@ -138,6 +403,29 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node20/-/node20-20.1.10.tgz#e41fb85a1f224b4f0704f7b33df71da8a55891b6" integrity sha512-5OZgdnxbFuvwm05iVwPXMU5/7iPuVDDZzAnxPDLj+kjN7fwQZSSVgHQhKTNkBPOO6Qef2D5MxPAoPLCGqE2VuQ== +"@types/chai@^5.2.2": + version "5.2.3" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.2.3.tgz#8e9cd9e1c3581fa6b341a5aed5588eb285be0b4a" + integrity sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA== + dependencies: + "@types/deep-eql" "*" + assertion-error "^2.0.1" + +"@types/deep-eql@*": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd" + integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== + +"@types/estree@1.0.9", "@types/estree@^1.0.0": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.9.tgz#cf3f0e876d7bee15a93ab925b82bf570a3904a24" + integrity sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg== + +"@types/mime-types@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/mime-types/-/mime-types-3.0.1.tgz#7fb74656179257c27cd48aa503eb918811727115" + integrity sha512-xRMsfuQbnRq1Ef+C+RKaENOxXX87Ygl38W1vDfPHRku02TgQr+Qd8iivLtAMcR0KF5/29xlnFihkTlbqFrGOVQ== + "@types/node@^20": version "20.19.43" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.43.tgz#fcecf580ba42a0db55cf404c372c97973c376c97" @@ -145,6 +433,67 @@ dependencies: undici-types "~6.21.0" +"@vitest/expect@3.2.7": + version "3.2.7" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-3.2.7.tgz#70a34158383d008c3bf5d802e2643317f09df6d8" + integrity sha512-E8eBXaKibuvH2pSZErOjdVb5vF4PbKYcrnluBTYxEk1l/VhhwZg1kZQsdtjq+CsF5CFydf2Rdkz7jDHKSisi3w== + dependencies: + "@types/chai" "^5.2.2" + "@vitest/spy" "3.2.7" + "@vitest/utils" "3.2.7" + chai "^5.2.0" + tinyrainbow "^2.0.0" + +"@vitest/mocker@3.2.7": + version "3.2.7" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-3.2.7.tgz#331be944cb783c642dd42bd743411aca24ea0466" + integrity sha512-Trr0hYO9CM3Wj6ksWHRhK9IZpIY6wTMO5u/MqXurMxT57sWBaOPEtP3Oq60ihZuh5JsiagKfz95OcxdEP6dBrA== + dependencies: + "@vitest/spy" "3.2.7" + estree-walker "^3.0.3" + magic-string "^0.30.17" + +"@vitest/pretty-format@3.2.7", "@vitest/pretty-format@^3.2.7": + version "3.2.7" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-3.2.7.tgz#2a7b593f8e007e9d8ef7e7343aa30ec73fdeaf29" + integrity sha512-KUHlwqVu0sRlhCdyPdQ/wBoTfRahjUky1MubOmYw9fWfIZy1gNoHpuaaQBPAaMaVYdQYHJLurzj8ECCj5OwTqA== + dependencies: + tinyrainbow "^2.0.0" + +"@vitest/runner@3.2.7": + version "3.2.7" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-3.2.7.tgz#c0c080228189f1fa6cda40f59be09d746b0aca51" + integrity sha512-sB9y4ovltoQP+WaUPwmSxO9WIg9Ig694Di5PalVPsYHklAdE027mehpWF2SQSVq+k6sFgaivbTjTJwZLSHbedA== + dependencies: + "@vitest/utils" "3.2.7" + pathe "^2.0.3" + strip-literal "^3.0.0" + +"@vitest/snapshot@3.2.7": + version "3.2.7" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-3.2.7.tgz#a3a7e1950ce99ec4cf02395e20ddca403b6c818e" + integrity sha512-7C+MwShwtBSI5Buwoyg3s/iY1eHL9PKAf+O1wVh/TdnjXUtkoL/9YQtre90i4MtNXM6edP1wJ2zOBpfCyhIS7g== + dependencies: + "@vitest/pretty-format" "3.2.7" + magic-string "^0.30.17" + pathe "^2.0.3" + +"@vitest/spy@3.2.7": + version "3.2.7" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-3.2.7.tgz#ca7fbee44019523ca450395d9a2284ce9ece1f31" + integrity sha512-Q2eQGI6d2L/hBtZ0qNuKcAGid68XK6cv1xsoaIma6PaJhHPoqcEJhYpXZ/5myCMqkNgtP6UKuBhbc0nHKnrkuQ== + dependencies: + tinyspy "^4.0.3" + +"@vitest/utils@3.2.7": + version "3.2.7" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-3.2.7.tgz#302c8126211ac4dfea87b3b5085c098d6d22e89e" + integrity sha512-x6BDOd7dyo3PFLY3I9/HJ25X/6OurhGXk2/B9gOZNPF7XDVjeBK4k01lQE5uvDpbuheErh91qYuE1E2OEjK3Rw== + dependencies: + "@vitest/pretty-format" "3.2.7" + loupe "^3.1.4" + tinyrainbow "^2.0.0" + agent-base@^7.1.0, agent-base@^7.1.2: version "7.1.4" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" @@ -162,6 +511,11 @@ ansi-styles@^4.1.0, ansi-styles@^4.2.1: dependencies: color-convert "^2.0.1" +assertion-error@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" + integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== + ast-types@^0.13.4: version "0.13.4" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782" @@ -202,6 +556,22 @@ bytes@^3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== + +chai@^5.2.0: + version "5.3.3" + resolved "https://registry.yarnpkg.com/chai/-/chai-5.3.3.tgz#dd3da955e270916a4bd3f625f4b919996ada7e06" + integrity sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw== + dependencies: + assertion-error "^2.0.1" + check-error "^2.1.1" + deep-eql "^5.0.1" + loupe "^3.1.0" + pathval "^2.0.0" + chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -210,6 +580,11 @@ chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +check-error@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.3.tgz#2427361117b70cca8dc89680ead32b157019caf5" + integrity sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA== + chownr@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4" @@ -268,13 +643,18 @@ debug@4: dependencies: ms "2.1.2" -debug@^4.3.4: +debug@^4.3.4, debug@^4.4.1: version "4.4.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== dependencies: ms "^2.1.3" +deep-eql@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" + integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== + degenerator@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-5.0.1.tgz#9403bf297c6dad9a1ece409b37db27954f91f2f5" @@ -299,6 +679,11 @@ env-var@^6.3.0: resolved "https://registry.yarnpkg.com/env-var/-/env-var-6.3.0.tgz#b4ace5bcd1d293629a2c509ae7b46f8add2f8892" integrity sha512-gaNzDZuVaJQJlP2SigAZLu/FieZN5MzdN7lgHNehESwlRanHwGQ/WUtJ7q//dhrj3aGBZM45yEaKOuvSJaf4mA== +es-module-lexer@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" + integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== + es5-ext@^0.10.35, es5-ext@^0.10.50: version "0.10.62" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" @@ -325,6 +710,38 @@ es6-symbol@^3.1.0, es6-symbol@^3.1.1, es6-symbol@^3.1.3: d "^1.0.1" ext "^1.1.2" +"esbuild@^0.27.0 || ^0.28.0": + version "0.28.2" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.28.2.tgz#0f43bd1bad955b72d24e2261e3abe5957ccf0816" + integrity sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA== + optionalDependencies: + "@esbuild/aix-ppc64" "0.28.2" + "@esbuild/android-arm" "0.28.2" + "@esbuild/android-arm64" "0.28.2" + "@esbuild/android-x64" "0.28.2" + "@esbuild/darwin-arm64" "0.28.2" + "@esbuild/darwin-x64" "0.28.2" + "@esbuild/freebsd-arm64" "0.28.2" + "@esbuild/freebsd-x64" "0.28.2" + "@esbuild/linux-arm" "0.28.2" + "@esbuild/linux-arm64" "0.28.2" + "@esbuild/linux-ia32" "0.28.2" + "@esbuild/linux-loong64" "0.28.2" + "@esbuild/linux-mips64el" "0.28.2" + "@esbuild/linux-ppc64" "0.28.2" + "@esbuild/linux-riscv64" "0.28.2" + "@esbuild/linux-s390x" "0.28.2" + "@esbuild/linux-x64" "0.28.2" + "@esbuild/netbsd-arm64" "0.28.2" + "@esbuild/netbsd-x64" "0.28.2" + "@esbuild/openbsd-arm64" "0.28.2" + "@esbuild/openbsd-x64" "0.28.2" + "@esbuild/openharmony-arm64" "0.28.2" + "@esbuild/sunos-x64" "0.28.2" + "@esbuild/win32-arm64" "0.28.2" + "@esbuild/win32-ia32" "0.28.2" + "@esbuild/win32-x64" "0.28.2" + escodegen@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" @@ -346,11 +763,23 @@ estraverse@^5.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== +estree-walker@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" + integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== + dependencies: + "@types/estree" "^1.0.0" + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +expect-type@^1.2.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.4.0.tgz#24edf7f0cc69a44d008567ba4594ab96f3c3a3d6" + integrity sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA== + ext@^1.1.2: version "1.7.0" resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" @@ -358,6 +787,11 @@ ext@^1.1.2: dependencies: type "^2.7.2" +fdir@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + fs-extra@^11.1.1: version "11.4.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.4.0.tgz#f88ed6d180ac9e14b61b08e679468f0b1b6b4730" @@ -372,6 +806,11 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -476,6 +915,11 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +js-tokens@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-9.0.1.tgz#2ec43964658435296f6761b34e10671c2d9527f4" + integrity sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ== + jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -485,6 +929,11 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" +loupe@^3.1.0, loupe@^3.1.4: + version "3.2.1" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.2.1.tgz#0095cf56dc5b7a9a7c08ff5b1a8796ec8ad17e76" + integrity sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ== + lru-cache@^11.1.0: version "11.5.2" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.5.2.tgz#00e16665c90c620fba14a3c368732a976493f760" @@ -495,6 +944,25 @@ lru-cache@^7.14.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== +magic-string@^0.30.17: + version "0.30.21" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" + integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.5" + +mime-db@^1.54.0: + version "1.54.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5" + integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== + +mime-types@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-3.0.2.tgz#39002d4182575d5af036ffa118100f2524b2e2ab" + integrity sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A== + dependencies: + mime-db "^1.54.0" + minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -543,6 +1011,11 @@ ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +nanoid@^3.3.18: + version "3.3.19" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.19.tgz#336d4aa4bcd4fb24d2cddede7ffeae40bec03f0a" + integrity sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug== + netmask@^2.0.2: version "2.1.1" resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.1.1.tgz#80043d265b53aa521b3bd01e8fcdf353f9e1e81e" @@ -609,6 +1082,35 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +pathe@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" + integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== + +pathval@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.1.tgz#8855c5a2899af072d6ac05d11e46045ad0dc605d" + integrity sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ== + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^4.0.2, picomatch@^4.0.3, picomatch@^4.0.4: + version "4.0.7" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.7.tgz#6313360034ccb36b3dc61ecbdff78121f90fe21f" + integrity sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA== + +postcss@^8.5.6: + version "8.5.28" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.28.tgz#da4563a99a06e62d6c1cd1acae363224bcaed6e9" + integrity sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A== + dependencies: + nanoid "^3.3.18" + picocolors "^1.1.1" + source-map-js "^1.2.1" + proxy-agent@^6.5.0: version "6.5.0" resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.5.0.tgz#9e49acba8e4ee234aacb539f89ed9c23d02f232d" @@ -644,6 +1146,41 @@ resolve@^1.1.6: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +rollup@^4.43.0: + version "4.63.4" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.63.4.tgz#cff29b8d6d959aee7cb5e44b0dad70074493dbf8" + integrity sha512-4U0liVayNIoLp3GFl1FcI8561WepLnZ1rqfraGh7S9B3Ur5F9S283y8Futii7RUU2C/97tOBmBy7nYvhoiOpbQ== + dependencies: + "@types/estree" "1.0.9" + optionalDependencies: + "@napi-rs/lzma-linux-x64-gnu" "1.5.1" + "@rollup/rollup-android-arm-eabi" "4.63.4" + "@rollup/rollup-android-arm64" "4.63.4" + "@rollup/rollup-darwin-arm64" "4.63.4" + "@rollup/rollup-darwin-x64" "4.63.4" + "@rollup/rollup-freebsd-arm64" "4.63.4" + "@rollup/rollup-freebsd-x64" "4.63.4" + "@rollup/rollup-linux-arm-gnueabihf" "4.63.4" + "@rollup/rollup-linux-arm-musleabihf" "4.63.4" + "@rollup/rollup-linux-arm64-gnu" "4.63.4" + "@rollup/rollup-linux-arm64-musl" "4.63.4" + "@rollup/rollup-linux-loong64-gnu" "4.63.4" + "@rollup/rollup-linux-loong64-musl" "4.63.4" + "@rollup/rollup-linux-ppc64-gnu" "4.63.4" + "@rollup/rollup-linux-ppc64-musl" "4.63.4" + "@rollup/rollup-linux-riscv64-gnu" "4.63.4" + "@rollup/rollup-linux-riscv64-musl" "4.63.4" + "@rollup/rollup-linux-s390x-gnu" "4.63.4" + "@rollup/rollup-linux-x64-gnu" "4.63.4" + "@rollup/rollup-linux-x64-musl" "4.63.4" + "@rollup/rollup-openbsd-x64" "4.63.4" + "@rollup/rollup-openharmony-arm64" "4.63.4" + "@rollup/rollup-win32-arm64-msvc" "4.63.4" + "@rollup/rollup-win32-ia32-msvc" "4.63.4" + "@rollup/rollup-win32-x64-gnu" "4.63.4" + "@rollup/rollup-win32-x64-msvc" "4.63.4" + fsevents "~2.3.2" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -665,6 +1202,11 @@ shelljs@^0.8.5: interpret "^1.0.0" rechoir "^0.6.2" +siginfo@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" + integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== + smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" @@ -687,6 +1229,11 @@ socks@^2.8.3: ip-address "^10.1.1" smart-buffer "^4.2.0" +source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + source-map-support@^0.5.21: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -700,6 +1247,16 @@ source-map@^0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +stackback@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" + integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== + +std-env@^3.9.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.10.0.tgz#d810b27e3a073047b2b5e40034881f5ea6f9c83b" + integrity sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg== + string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -716,6 +1273,13 @@ strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-literal@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-3.1.0.tgz#222b243dd2d49c0bcd0de8906adbd84177196032" + integrity sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg== + dependencies: + js-tokens "^9.0.1" + supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -751,6 +1315,39 @@ throttle-debounce@^3.0.1: resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-3.0.1.tgz#32f94d84dfa894f786c9a1f290e7a645b6a19abb" integrity sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg== +tinybench@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" + integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== + +tinyexec@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2" + integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== + +tinyglobby@^0.2.14, tinyglobby@^0.2.15: + version "0.2.17" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.17.tgz#562a9a6c9eb2b3b123d39719f9af5bb44fcd7631" + integrity sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g== + dependencies: + fdir "^6.5.0" + picomatch "^4.0.4" + +tinypool@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.1.1.tgz#059f2d042bd37567fbc017d3d426bdd2a2612591" + integrity sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg== + +tinyrainbow@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-2.0.0.tgz#9509b2162436315e80e3eee0fcce4474d2444294" + integrity sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw== + +tinyspy@^4.0.3: + version "4.0.6" + resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-4.0.6.tgz#68e278e20287f37beb5f4b0a4db211d280400562" + integrity sha512-u8KszXvGfU68hVcZpRHKG28T0krMuv2G5nDhiHaMLen/gIuFEgIJhaJuO69qjnXg5paSrbPMFfx3brNuN8eVSg== + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -796,6 +1393,60 @@ uuid@^11.1.1: resolved "https://registry.yarnpkg.com/uuid/-/uuid-11.1.1.tgz#f6d81d2e1c65d00762e5e29b16c5d2d995e208ad" integrity sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ== +vite-node@3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-3.2.4.tgz#f3676d94c4af1e76898c162c92728bca65f7bb07" + integrity sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg== + dependencies: + cac "^6.7.14" + debug "^4.4.1" + es-module-lexer "^1.7.0" + pathe "^2.0.3" + vite "^5.0.0 || ^6.0.0 || ^7.0.0-0" + +"vite@^5.0.0 || ^6.0.0 || ^7.0.0-0": + version "7.3.6" + resolved "https://registry.yarnpkg.com/vite/-/vite-7.3.6.tgz#0547a395e68d3746e9a505f1fd4469fe09b49cc4" + integrity sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg== + dependencies: + esbuild "^0.27.0 || ^0.28.0" + fdir "^6.5.0" + picomatch "^4.0.3" + postcss "^8.5.6" + rollup "^4.43.0" + tinyglobby "^0.2.15" + optionalDependencies: + fsevents "~2.3.3" + +vitest@^3: + version "3.2.7" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-3.2.7.tgz#1944b6ed013a25fd26a73d18e1af92c10a57af6c" + integrity sha512-KrxIJ62Fd89gfysR4WotlgZABiz2dqFPgqGzX7s+CwsqLFomRH7777ZcrOD6+WVAh7khPQP41A+BKbpcJFrdEg== + dependencies: + "@types/chai" "^5.2.2" + "@vitest/expect" "3.2.7" + "@vitest/mocker" "3.2.7" + "@vitest/pretty-format" "^3.2.7" + "@vitest/runner" "3.2.7" + "@vitest/snapshot" "3.2.7" + "@vitest/spy" "3.2.7" + "@vitest/utils" "3.2.7" + chai "^5.2.0" + debug "^4.4.1" + expect-type "^1.2.1" + magic-string "^0.30.17" + pathe "^2.0.3" + picomatch "^4.0.2" + std-env "^3.9.0" + tinybench "^2.9.0" + tinyexec "^0.3.2" + tinyglobby "^0.2.14" + tinypool "^1.1.1" + tinyrainbow "^2.0.0" + vite "^5.0.0 || ^6.0.0 || ^7.0.0-0" + vite-node "3.2.4" + why-is-node-running "^2.3.0" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -816,6 +1467,14 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +why-is-node-running@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04" + integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w== + dependencies: + siginfo "^2.0.0" + stackback "0.0.2" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"