diff --git a/.github/workflows/e2e-publishing.yml b/.github/workflows/e2e-publishing.yml
index 4dcab4117..35c1596c3 100644
--- a/.github/workflows/e2e-publishing.yml
+++ b/.github/workflows/e2e-publishing.yml
@@ -174,3 +174,115 @@ jobs:
if (-not (Test-Path $path)) {
throw "settings.xml file is not found in expected location"
}
+
+ test-maven-repositories:
+ name: Maven ${{ matrix.repositories }} repositories
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [macos-latest, windows-latest, ubuntu-latest]
+ repositories: [dependencies, plugins, both]
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v7
+ with:
+ persist-credentials: false
+ - name: Prepare Maven model inspection
+ run: |
+ $directory = Join-Path $env:RUNNER_TEMP "maven-repository-test"
+ New-Item -Path $directory -ItemType Directory -Force | Out-Null
+ $pomPath = Join-Path $directory "pom.xml"
+ $warmSettingsPath = Join-Path $directory "warm-settings.xml"
+ $cachePath = Join-Path $directory "repository"
+ $outputPath = Join-Path $directory "warm-effective-pom.xml"
+
+ # This project repository keeps the inspection plugin available offline
+ # after the generated settings disable inherited plugin Central.
+ @'
+
+ 4.0.0
+ setup-java.test
+ repository-settings
+ 1.0
+
+
+ inspection
+ https://repo.maven.apache.org/maven2
+
+
+
+ '@ | Set-Content -Path $pomPath
+ '' | Set-Content -Path $warmSettingsPath
+
+ mvn --batch-mode --no-transfer-progress --settings $warmSettingsPath `
+ "-Dmaven.repo.local=$cachePath" --file $pomPath `
+ org.apache.maven.plugins:maven-help-plugin:3.5.1:effective-pom `
+ "-Doutput=$outputPath"
+ if ($LASTEXITCODE -ne 0) {
+ throw "Could not prepare the Maven Help Plugin"
+ }
+ - name: Configure dependency and plugin repositories
+ uses: ./
+ with:
+ distribution: 'temurin'
+ java-version: '21'
+ settings-path: ${{ runner.temp }}/maven-repository-test/settings
+ mvn-server-credentials: |
+ private:PRIVATE_USERNAME:PRIVATE_TOKEN
+ mvn-repositories: ${{ matrix.repositories != 'plugins' && 'private:https://repo.example.invalid/maven:false' || '' }}
+ mvn-plugin-repositories: ${{ matrix.repositories != 'dependencies' && 'private:https://repo.example.invalid/maven:false' || '' }}
+ mvn-repositories-include-central: false
+ - name: Validate generated settings and effective Maven repositories
+ env:
+ REPOSITORY_CONFIGURATION: ${{ matrix.repositories }}
+ run: |
+ $directory = Join-Path $env:RUNNER_TEMP "maven-repository-test"
+ $settingsPath = Join-Path $directory "settings/settings.xml"
+ [xml]$settings = Get-Content -Path $settingsPath -Raw
+ $profiles = @($settings.settings.profiles.profile)
+ if ($profiles.Count -ne 1 -or $profiles[0].id -ne "setup-java-repositories") {
+ throw "Expected one repository profile"
+ }
+ $activeProfiles = @($settings.settings.activeProfiles.activeProfile)
+ if ($activeProfiles.Count -ne 1 -or $activeProfiles[0] -ne "setup-java-repositories") {
+ throw "Expected one active repository profile"
+ }
+ $server = $settings.settings.servers.server
+ if ($server.id -ne "private" -or $server.username -ne '${env.PRIVATE_USERNAME}' -or $server.password -ne '${env.PRIVATE_TOKEN}') {
+ throw "Repository credentials were not preserved"
+ }
+
+ function Assert-Repositories($repositories, $expectPrivate, $context) {
+ $central = @($repositories | Where-Object { $_.id -eq "central" })
+ if ($central.Count -ne 1 -or $central[0].releases.enabled -ne "false" -or $central[0].snapshots.enabled -ne "false") {
+ throw "$context did not disable inherited Maven Central"
+ }
+ $private = @($repositories | Where-Object { $_.id -eq "private" })
+ $expectedCount = if ($expectPrivate) { 1 } else { 0 }
+ if ($private.Count -ne $expectedCount) {
+ throw "$context has incorrect private repositories"
+ }
+ if ($expectPrivate -and ($private[0].url -ne "https://repo.example.invalid/maven" -or $private[0].snapshots.enabled -ne "false")) {
+ throw "$context has incorrect private repository settings"
+ }
+ }
+
+ $expectDependencies = $env:REPOSITORY_CONFIGURATION -ne "plugins"
+ $expectPlugins = $env:REPOSITORY_CONFIGURATION -ne "dependencies"
+ Assert-Repositories @($profiles[0].repositories.repository) $expectDependencies "Settings dependency repositories"
+ Assert-Repositories @($profiles[0].pluginRepositories.pluginRepository) $expectPlugins "Settings plugin repositories"
+
+ $pomPath = Join-Path $directory "pom.xml"
+ $cachePath = Join-Path $directory "repository"
+ $outputPath = Join-Path $directory "effective-pom.xml"
+ mvn --batch-mode --no-transfer-progress --offline --settings $settingsPath `
+ "-Dmaven.repo.local=$cachePath" --file $pomPath `
+ org.apache.maven.plugins:maven-help-plugin:3.5.1:effective-pom `
+ "-Doutput=$outputPath"
+ if ($LASTEXITCODE -ne 0) {
+ throw "Could not inspect the effective Maven model"
+ }
+ [xml]$effectivePom = Get-Content -Path $outputPath -Raw
+ Assert-Repositories @($effectivePom.project.repositories.repository) $expectDependencies "Effective dependency repositories"
+ Assert-Repositories @($effectivePom.project.pluginRepositories.pluginRepository) $expectPlugins "Effective plugin repositories"
diff --git a/.licenses/npm/brace-expansion.dep.yml b/.licenses/npm/brace-expansion.dep.yml
index 96e6211ba..8a9c0556d 100644
--- a/.licenses/npm/brace-expansion.dep.yml
+++ b/.licenses/npm/brace-expansion.dep.yml
@@ -1,6 +1,6 @@
---
name: brace-expansion
-version: 5.0.9
+version: 5.0.12
type: npm
summary: Brace expansion as known from sh/bash
homepage:
diff --git a/.licenses/npm/fast-xml-parser.dep.yml b/.licenses/npm/fast-xml-parser.dep.yml
index 88bd3e262..84f4dd0b9 100644
--- a/.licenses/npm/fast-xml-parser.dep.yml
+++ b/.licenses/npm/fast-xml-parser.dep.yml
@@ -1,6 +1,6 @@
---
name: fast-xml-parser
-version: 5.11.0
+version: 5.11.1
type: npm
summary: Validate XML, Parse XML, Build XML without C/C++ based libraries
homepage:
diff --git a/.licenses/npm/undici.dep.yml b/.licenses/npm/undici.dep.yml
index b339a4487..336811738 100644
--- a/.licenses/npm/undici.dep.yml
+++ b/.licenses/npm/undici.dep.yml
@@ -1,6 +1,6 @@
---
name: undici
-version: 6.28.0
+version: 6.29.0
type: npm
summary: An HTTP/1.1 client, written from scratch for Node.js
homepage: https://undici.nodejs.org
diff --git a/README.md b/README.md
index f76c65e73..58822e688 100644
--- a/README.md
+++ b/README.md
@@ -150,7 +150,7 @@ steps:
| `java-version-file` | Path to `.java-version`, `.tool-versions`, or `.sdkmanrc`. Used when `java-version` is not set. | |
| `distribution` | Java distribution keyword. Values are case-sensitive and must match one of the supported keywords below. Required unless `java-version-file` points to `.sdkmanrc` with a recognized distribution suffix. | |
| `java-package` | Package variant such as `jdk`, `jre`, `jdk+fx`, `jre+fx`, `jdk+crac`, `jre+crac`, `jdk+jmods`, `jdk+jcef`, `jre+jcef`, `jdk+ft`, or `jre+ft`. Support varies by distribution. | `jdk` |
-| `architecture` | Package architecture. Canonical values are `x86`, `x64`, `armv7`, `aarch64`, `ppc64le`, `ppc64`, and `s390x`. Aliases `ia32`, `amd64`, `arm`, and `arm64` are normalized. | Runner architecture |
+| `architecture` | Package architecture. Canonical values are `x86`, `x64`, `armv7`, `aarch64`, `ppc64le`, `ppc64`, `riscv64`, and `s390x`. Aliases `ia32`, `amd64`, `arm`, and `arm64` are normalized. | Runner architecture |
| `jdk-file` | Local compressed JDK archive. Requires `distribution: jdkfile`. | |
| `check-latest` | Check remote metadata for the latest version satisfying the version spec before using the runner tool cache. | `false` |
| `force-download` | Always download Java and replace any matching version in the tool cache. | `false` |
@@ -168,9 +168,11 @@ steps:
| `server-username-env-var` | Environment variable name for Maven repository username. | `GITHUB_ACTOR` |
| `server-password-env-var` | Environment variable name for Maven repository password or token. | `GITHUB_TOKEN` |
| `mvn-server-credentials` | Multiline Maven server credentials in the format `server-id:USERNAME_ENV:PASSWORD_ENV`. Replaces the single server configured by the three inputs above when set. | |
+| `mvn-server-repository-origins` | Multiline Maven credential origins in the format `server-id:repository-origin`. Each origin must belong to a configured server ID. Requires Maven 3.10+. | |
| `mvn-repositories` | Multiline Maven dependency repositories in the format `repository-id:repository-url:snapshots-enabled`. | |
-| `mvn-repositories-include-central` | Include Maven Central in the generated dependency repositories profile. When `false`, Central is disabled unless an explicit `central` repository is declared. | `true` |
-| `mvn-repositories-prioritize-central` | Place Maven Central before custom dependency repositories. Has no effect when Maven Central is excluded. | `true` |
+| `mvn-plugin-repositories` | Multiline Maven plugin repositories in the format `repository-id:repository-url:snapshots-enabled`. Can be used independently of `mvn-repositories`. | |
+| `mvn-repositories-include-central` | Include Maven Central for dependency and plugin repositories in the generated profile. When `false`, Central is disabled for both types unless that type explicitly declares `central`. Has no effect when neither repository list is configured. | `true` |
+| `mvn-repositories-prioritize-central` | Place Maven Central before custom dependency and plugin repositories. Has no effect when Central is excluded or neither repository list is configured. | `true` |
| `settings-path` | Directory where `settings.xml` is written. | `~/.m2` |
| `overwrite-settings` | Overwrite an existing `settings.xml`. | `true` |
| `gpg-private-key` | GPG private key to import into an isolated temporary keyring. | |
@@ -233,7 +235,7 @@ Additional distribution notes:
| --- | --- |
| Major version | `8`, `11`, `17`, `21`, `25` |
| Specific feature or patch version | `11.0`, `11.0.4`, `17.0`, `8.0.282+8` |
-| JEP 322 multi-field versions | `11.0.9.1`, `18.0.1.1` |
+| JEP 322 multi-field versions | `11.0.9.1`, `18.0.1.1`, `26.0.2.1+1` |
| Early access | `15-ea`, `15.0.0-ea`, `27-ea` |
| Latest stable GA release | `latest` |
@@ -481,10 +483,20 @@ steps:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
-For dependencies hosted outside Maven Central, use `mvn-repositories` to add
-resolution repositories to an active profile in the generated `settings.xml`.
-Repository IDs can match `mvn-server-credentials` IDs when authentication is
-required. See [Resolving Maven dependencies from custom repositories](docs/advanced-usage.md#resolving-maven-dependencies-from-custom-repositories).
+For dependencies hosted outside Maven Central, use `mvn-repositories`; for build
+plugins, use `mvn-plugin-repositories`. Either input adds its own repository type
+to the same active profile in the generated `settings.xml`. Repository IDs can
+match `mvn-server-credentials` IDs when authentication is required.
+See [Resolving Maven dependencies from custom repositories](docs/advanced-usage.md#resolving-maven-dependencies-from-custom-repositories)
+and [Resolving Maven plugins from custom repositories](docs/advanced-usage.md#resolving-maven-plugins-from-custom-repositories).
+
+> [!WARNING]
+> `mvn-repositories-include-central: false` now disables inherited Maven Central
+> for **both dependencies and plugins**, even in existing workflows that only
+> configure `mvn-repositories`. Builds relying on uncached plugins from Central
+> must configure `mvn-plugin-repositories` with an accessible plugin repository
+> or explicitly declare `central` there. Neither repository list configured
+> means the Central controls remain inactive.
### GPG signing
diff --git a/__tests__/auth.test.ts b/__tests__/auth.test.ts
index a169451f4..7af82c8f8 100644
--- a/__tests__/auth.test.ts
+++ b/__tests__/auth.test.ts
@@ -63,12 +63,51 @@ const credentials = (id: string, username: string, password: string) => [
const repositorySettings = (
repositories: auth.MavenRepository[],
includeCentral = true,
- prioritizeCentral = true
+ prioritizeCentral = true,
+ pluginRepositories: auth.MavenRepository[] = []
): auth.MavenRepositorySettings => ({
repositories,
+ pluginRepositories,
includeCentral,
prioritizeCentral
});
+const repositoryInputs = ['mvn-repositories', 'mvn-plugin-repositories'];
+const privateRepository = {
+ id: 'private',
+ url: 'https://repo.example.com/maven',
+ snapshotsEnabled: true
+};
+const privateRepositoryXml = {
+ id: privateRepository.id,
+ url: privateRepository.url,
+ snapshots: {enabled: 'true'}
+};
+const centralRepositoryXml = {
+ id: 'central',
+ url: 'https://repo.maven.apache.org/maven2',
+ snapshots: {enabled: 'false'}
+};
+const disabledCentralRepositoryXml = {
+ ...centralRepositoryXml,
+ releases: {enabled: 'false'}
+};
+const repositoryConfigurations = [
+ {
+ name: 'dependency-only',
+ repositories: [privateRepository],
+ pluginRepositories: []
+ },
+ {
+ name: 'plugin-only',
+ repositories: [],
+ pluginRepositories: [privateRepository]
+ },
+ {
+ name: 'combined',
+ repositories: [privateRepository],
+ pluginRepositories: [privateRepository]
+ }
+];
describe('auth tests', () => {
let spyOSHomedir: any;
@@ -318,6 +357,21 @@ describe('auth tests', () => {
).toEqual(expectedSettings);
});
+ it('generates repository origins for a Maven server', () => {
+ const settings = auth.generate([
+ {
+ id: 'central',
+ usernameEnvVar: 'CENTRAL_USER',
+ passwordEnvVar: 'CENTRAL_PASS',
+ repositoryOrigins: ['https://central.sonatype.com']
+ }
+ ]);
+
+ expect(settings).toContain(`
+ https://central.sonatype.com
+ `);
+ });
+
it('does not add a gpg profile when the passphrase env var is the maven-gpg-plugin default', () => {
const id = 'packages';
const username = 'USER';
@@ -460,6 +514,87 @@ describe('auth tests', () => {
).toEqual(['first', 'second', 'central']);
});
+ it.each([
+ {
+ name: 'Central first by default',
+ prioritizeCentral: undefined,
+ expectedRepositories: [
+ {
+ id: 'central',
+ url: 'https://repo.maven.apache.org/maven2',
+ snapshots: {enabled: 'false'}
+ },
+ {
+ id: 'first',
+ url: 'https://first.example.com/plugins',
+ snapshots: {enabled: 'false'}
+ },
+ {
+ id: 'second',
+ url: 'https://second.example.com/plugins',
+ snapshots: {enabled: 'true'}
+ }
+ ]
+ },
+ {
+ name: 'custom plugins before Central',
+ prioritizeCentral: false,
+ expectedRepositories: [
+ {
+ id: 'first',
+ url: 'https://first.example.com/plugins',
+ snapshots: {enabled: 'false'}
+ },
+ {
+ id: 'second',
+ url: 'https://second.example.com/plugins',
+ snapshots: {enabled: 'true'}
+ },
+ {
+ id: 'central',
+ url: 'https://repo.maven.apache.org/maven2',
+ snapshots: {enabled: 'false'}
+ }
+ ]
+ }
+ ])(
+ 'generates plugin-only settings with $name',
+ ({prioritizeCentral, expectedRepositories}) => {
+ const xml = auth.generate(
+ [],
+ undefined,
+ repositorySettings([], true, prioritizeCentral, [
+ {
+ id: 'first',
+ url: 'https://first.example.com/plugins',
+ snapshotsEnabled: false
+ },
+ {
+ id: 'second',
+ url: 'https://second.example.com/plugins',
+ snapshotsEnabled: true
+ }
+ ])
+ );
+
+ expect(parseXmlObject(xml)).toEqual(
+ expect.objectContaining({
+ settings: expect.objectContaining({
+ profiles: {
+ profile: {
+ id: 'setup-java-repositories',
+ pluginRepositories: {
+ pluginRepository: expectedRepositories
+ }
+ }
+ },
+ activeProfiles: {activeProfile: 'setup-java-repositories'}
+ })
+ })
+ );
+ }
+ );
+
it('excludes Central from the generated repository profile when configured', () => {
const parsed = parseXmlObject(
auth.generate(
@@ -491,6 +626,9 @@ describe('auth tests', () => {
snapshots: {enabled: 'false'}
}
]);
+ expect(
+ parsed.settings.profiles.profile.pluginRepositories.pluginRepository
+ ).toEqual(disabledCentralRepositoryXml);
});
it('combines repository and GPG configuration in shared profile blocks', () => {
@@ -528,6 +666,9 @@ describe('auth tests', () => {
snapshots: {enabled: 'false'}
}
]
+ },
+ pluginRepositories: {
+ pluginRepository: disabledCentralRepositoryXml
}
},
{
@@ -541,6 +682,161 @@ describe('auth tests', () => {
]);
});
+ it.each(
+ repositoryConfigurations.flatMap(configuration =>
+ [
+ {includeCentral: true, prioritizeCentral: true},
+ {includeCentral: true, prioritizeCentral: false},
+ {includeCentral: false, prioritizeCentral: true},
+ {includeCentral: false, prioritizeCentral: false}
+ ].map(controls => ({...configuration, ...controls}))
+ )
+ )(
+ 'generates $name repositories with includeCentral=$includeCentral and prioritizeCentral=$prioritizeCentral',
+ ({repositories, pluginRepositories, includeCentral, prioritizeCentral}) => {
+ const xml = auth.generate(
+ credentials('private', 'USERNAME', 'PASSWORD'),
+ undefined,
+ repositorySettings(
+ repositories,
+ includeCentral,
+ prioritizeCentral,
+ pluginRepositories
+ )
+ );
+ const expectedEntries = (configured: boolean) => {
+ const entries = includeCentral
+ ? configured
+ ? prioritizeCentral
+ ? [centralRepositoryXml, privateRepositoryXml]
+ : [privateRepositoryXml, centralRepositoryXml]
+ : []
+ : configured
+ ? [privateRepositoryXml, disabledCentralRepositoryXml]
+ : [disabledCentralRepositoryXml];
+ return entries.length === 1 ? entries[0] : entries;
+ };
+ const includeRepositories = repositories.length > 0 || !includeCentral;
+ const includePluginRepositories =
+ pluginRepositories.length > 0 || !includeCentral;
+
+ expect(parseXmlObject(xml)).toMatchObject({
+ settings: {
+ profiles: {
+ profile: {
+ id: 'setup-java-repositories',
+ ...(includeRepositories
+ ? {
+ repositories: {
+ repository: expectedEntries(repositories.length > 0)
+ }
+ }
+ : {}),
+ ...(includePluginRepositories
+ ? {
+ pluginRepositories: {
+ pluginRepository: expectedEntries(
+ pluginRepositories.length > 0
+ )
+ }
+ }
+ : {})
+ }
+ },
+ activeProfiles: {activeProfile: 'setup-java-repositories'}
+ }
+ });
+ if (!includeRepositories) {
+ expect(xml).not.toContain('');
+ }
+ if (!includePluginRepositories) {
+ expect(xml).not.toContain('');
+ }
+ }
+ );
+
+ it.each(repositoryConfigurations)(
+ 'handles explicit Central independently for $name repositories',
+ ({repositories, pluginRepositories}) => {
+ const central = {
+ id: 'central',
+ url: 'https://mirror.example.com/maven',
+ snapshotsEnabled: true
+ };
+ const explicitCentralXml = {
+ id: central.id,
+ url: central.url,
+ snapshots: {enabled: 'true'}
+ };
+ const xml = auth.generate(
+ [],
+ undefined,
+ repositorySettings(
+ repositories.length ? [central] : [],
+ false,
+ true,
+ pluginRepositories.length ? [central] : []
+ )
+ );
+
+ expect(parseXmlObject(xml)).toMatchObject({
+ settings: {
+ profiles: {
+ profile: {
+ repositories: {
+ repository: repositories.length
+ ? explicitCentralXml
+ : disabledCentralRepositoryXml
+ },
+ pluginRepositories: {
+ pluginRepository: pluginRepositories.length
+ ? explicitCentralXml
+ : disabledCentralRepositoryXml
+ }
+ }
+ }
+ }
+ });
+ expect(xml.match(/central<\/id>/g)).toHaveLength(2);
+ }
+ );
+
+ it('escapes plugin repository values while preserving parsed semantics', () => {
+ const repository = {
+ id: `private&<>"'é`,
+ url: `https://repo.example.com:8443/a?x=1&y="'é`,
+ snapshotsEnabled: false
+ };
+ const xml = auth.generate(
+ credentials(repository.id, 'USERNAME', 'PASSWORD'),
+ undefined,
+ repositorySettings([], true, true, [repository])
+ );
+
+ expect(parseXmlObject(xml)).toMatchObject({
+ settings: {
+ servers: {server: {id: repository.id}},
+ profiles: {
+ profile: {
+ pluginRepositories: {
+ pluginRepository: [
+ centralRepositoryXml,
+ {
+ id: repository.id,
+ url: repository.url,
+ snapshots: {enabled: 'false'}
+ }
+ ]
+ }
+ }
+ }
+ }
+ });
+ expect(xml).toContain('private&<>');
+ expect(xml).toContain('x=1&y=<value>');
+ expect(xml).not.toContain('');
+ });
+
it('escapes repository values while preserving parsed semantics', () => {
const repository = {
id: `private&<>"'é`,
@@ -586,81 +882,111 @@ describe('auth tests', () => {
]);
});
- it('parses Maven repositories while preserving colons in URLs', () => {
- expect(
- auth.parseMavenRepositories(
- [
- '',
- ' private : https://repo.example.com:8443/maven : true ',
- 'releases:https://repo.example.com/releases:false'
- ],
- true
- )
- ).toEqual([
+ it.each(repositoryInputs)(
+ 'parses %s while preserving colons in URLs',
+ inputName => {
+ expect(
+ auth.parseMavenRepositories(
+ [
+ '',
+ ' private : https://repo.example.com:8443/maven : TRUE ',
+ 'releases:https://repo.example.com/releases:false'
+ ],
+ true,
+ inputName
+ )
+ ).toEqual([
+ {
+ id: 'private',
+ url: 'https://repo.example.com:8443/maven',
+ snapshotsEnabled: true
+ },
+ {
+ id: 'releases',
+ url: 'https://repo.example.com/releases',
+ snapshotsEnabled: false
+ }
+ ]);
+ }
+ );
+
+ it.each(
+ [
{
- id: 'private',
- url: 'https://repo.example.com:8443/maven',
- snapshotsEnabled: true
+ entries: ['private'],
+ error:
+ 'Invalid mvn-repositories entry at line 1. Expected format: repository-id:repository-url:snapshots-enabled'
},
{
- id: 'releases',
- url: 'https://repo.example.com/releases',
- snapshotsEnabled: false
+ entries: ['private:https://repo.example.com'],
+ error:
+ "Invalid snapshots-enabled value '//repo.example.com' in mvn-repositories entry at line 1. Expected true or false"
+ },
+ {
+ entries: ['private::true'],
+ error:
+ 'Invalid mvn-repositories entry at line 1. repository-id, repository URL, and snapshots-enabled are required'
+ },
+ {
+ entries: ['private:https://repo.example.com:'],
+ error:
+ 'Invalid mvn-repositories entry at line 1. repository-id, repository URL, and snapshots-enabled are required'
+ },
+ {
+ entries: ['', 'private:https://repo.example.com:true', ' :url:false'],
+ error:
+ 'Invalid mvn-repositories entry at line 3. repository-id, repository URL, and snapshots-enabled are required'
+ },
+ {
+ entries: ['private:https://repo.example.com:sometimes'],
+ error:
+ "Invalid snapshots-enabled value 'sometimes' in mvn-repositories entry at line 1. Expected true or false"
}
- ]);
- });
-
- it.each([
- {
- entries: ['private'],
- error:
- 'Invalid mvn-repositories entry at line 1. Expected format: repository-id:repository-url:snapshots-enabled'
- },
- {
- entries: ['private:https://repo.example.com'],
- error:
- "Invalid snapshots-enabled value '//repo.example.com' in mvn-repositories entry at line 1. Expected true or false"
- },
- {
- entries: ['private::true'],
- error:
- 'Invalid mvn-repositories entry at line 1. repository-id, repository URL, and snapshots-enabled are required'
- },
- {
- entries: ['private:https://repo.example.com:sometimes'],
- error:
- "Invalid snapshots-enabled value 'sometimes' in mvn-repositories entry at line 1. Expected true or false"
- }
- ])('rejects malformed Maven repositories: $entries', ({entries, error}) => {
- expect(() => auth.parseMavenRepositories(entries, true)).toThrow(error);
+ ].flatMap(testCase =>
+ repositoryInputs.map(inputName => ({
+ ...testCase,
+ inputName,
+ error: testCase.error.replace('mvn-repositories', inputName)
+ }))
+ )
+ )('rejects malformed $inputName: $entries', ({entries, error, inputName}) => {
+ expect(() => auth.parseMavenRepositories(entries, true, inputName)).toThrow(
+ error
+ );
});
- it('rejects duplicate Maven repository ids', () => {
+ it.each(repositoryInputs)('rejects duplicate IDs in %s', inputName => {
expect(() =>
auth.parseMavenRepositories(
[
'private:https://first.example.com:false',
'private:https://second.example.com:true'
],
- true
+ true,
+ inputName
)
- ).toThrow("Duplicate repository-id 'private' in mvn-repositories input");
+ ).toThrow(`Duplicate repository-id 'private' in ${inputName} input`);
});
- it('reserves the Central repository id only when automatic Central inclusion is enabled', () => {
- const central = 'central:https://custom.example.com/maven:false';
-
- expect(() => auth.parseMavenRepositories([central], true)).toThrow(
- "Repository-id 'central' is reserved when mvn-repositories-include-central is enabled"
- );
- expect(auth.parseMavenRepositories([central], false)).toEqual([
- {
- id: 'central',
- url: 'https://custom.example.com/maven',
- snapshotsEnabled: false
- }
- ]);
- });
+ it.each(repositoryInputs)(
+ 'reserves the Central ID in %s only when automatic inclusion is enabled',
+ inputName => {
+ const central = 'central:https://custom.example.com/maven:false';
+
+ expect(() =>
+ auth.parseMavenRepositories([central], true, inputName)
+ ).toThrow(
+ "Repository-id 'central' is reserved when mvn-repositories-include-central is enabled"
+ );
+ expect(auth.parseMavenRepositories([central], false, inputName)).toEqual([
+ {
+ id: 'central',
+ url: 'https://custom.example.com/maven',
+ snapshotsEnabled: false
+ }
+ ]);
+ }
+ );
it('uses an explicit Central repository instead of adding a disabled override', () => {
const parsed = parseXmlObject(
@@ -706,16 +1032,138 @@ describe('auth tests', () => {
snapshotsEnabled: true
}
],
+ pluginRepositories: [],
includeCentral: false,
prioritizeCentral: false
});
});
it('does not read repository controls when no repositories are configured', () => {
+ (
+ core.getInput as jest.MockedFunction
+ ).mockReturnValue('false');
+ expect(auth.getMavenRepositorySettings()).toBeUndefined();
+ expect(core.getInput).not.toHaveBeenCalled();
+ });
+
+ it('ignores blank dependency and plugin repository inputs', () => {
+ (
+ core.getMultilineInput as jest.MockedFunction<
+ typeof core.getMultilineInput
+ >
+ ).mockReturnValue(['', ' ', '\t']);
+
expect(auth.getMavenRepositorySettings()).toBeUndefined();
expect(core.getInput).not.toHaveBeenCalled();
});
+ it.each(repositoryConfigurations)(
+ 'reads $name inputs with default Central controls and shared IDs',
+ ({repositories, pluginRepositories}) => {
+ (
+ core.getInput as jest.MockedFunction
+ ).mockReturnValue('');
+ (
+ core.getMultilineInput as jest.MockedFunction<
+ typeof core.getMultilineInput
+ >
+ ).mockImplementation(name => {
+ const configured =
+ name === 'mvn-repositories' ? repositories : pluginRepositories;
+ return configured.map(
+ repository =>
+ `${repository.id}:${repository.url}:${repository.snapshotsEnabled}`
+ );
+ });
+
+ expect(auth.getMavenRepositorySettings()).toEqual({
+ repositories,
+ pluginRepositories,
+ includeCentral: true,
+ prioritizeCentral: true
+ });
+ }
+ );
+
+ it.each([true, false])(
+ 'configures plugin repositories with credentials, GPG, a custom path, and overwrite=%s',
+ async overwriteSettings => {
+ const directory = path.join(m2Dir, 'custom');
+ const location = path.join(directory, MVN_SETTINGS_FILE);
+ fs.mkdirSync(directory, {recursive: true});
+ fs.writeFileSync(location, 'EXISTING SETTINGS');
+ (
+ core.getInput as jest.MockedFunction
+ ).mockImplementation(name => {
+ const inputs: Record = {
+ 'settings-path': directory,
+ 'overwrite-settings': String(overwriteSettings),
+ 'gpg-passphrase-env-var': 'GPG_PASSPHRASE',
+ 'mvn-repositories-include-central': 'false'
+ };
+ return inputs[name] ?? '';
+ });
+ (
+ core.getMultilineInput as jest.MockedFunction<
+ typeof core.getMultilineInput
+ >
+ ).mockImplementation(name => {
+ const inputs: Record = {
+ 'mvn-server-credentials': ['private:USERNAME:PASSWORD'],
+ 'mvn-server-repository-origins': ['private:https://repo.example.com'],
+ 'mvn-plugin-repositories': [
+ 'private:https://repo.example.com/maven:true'
+ ]
+ };
+ return inputs[name] ?? [];
+ });
+
+ await auth.configureAuthentication();
+
+ const xml = fs.readFileSync(location, 'utf8');
+ if (!overwriteSettings) {
+ expect(xml).toBe('EXISTING SETTINGS');
+ return;
+ }
+ expect(parseXmlObject(xml)).toMatchObject({
+ settings: {
+ servers: {
+ server: {
+ id: 'private',
+ username: '${env.USERNAME}',
+ password: '${env.PASSWORD}',
+ repositoryOrigins: {
+ repositoryOrigin: 'https://repo.example.com'
+ }
+ }
+ },
+ profiles: {
+ profile: [
+ {
+ id: 'setup-java-repositories',
+ repositories: {repository: disabledCentralRepositoryXml},
+ pluginRepositories: {
+ pluginRepository: [
+ privateRepositoryXml,
+ disabledCentralRepositoryXml
+ ]
+ }
+ },
+ {
+ id: 'setup-java-gpg',
+ properties: {'gpg.passphraseEnvName': 'GPG_PASSPHRASE'}
+ }
+ ]
+ },
+ activeProfiles: {
+ activeProfile: ['setup-java-repositories', 'setup-java-gpg']
+ }
+ }
+ });
+ expect(fs.existsSync(settingsFile)).toBe(false);
+ }
+ );
+
it.each([
{
entries: ['releases:RELEASES_USERNAME'],
@@ -749,16 +1197,23 @@ describe('auth tests', () => {
});
it('uses multiline Maven server credentials instead of single-server inputs', () => {
- (core.getMultilineInput as jest.Mock).mockReturnValue([
- 'releases:RELEASES_USERNAME:RELEASES_PASSWORD',
- 'snapshots:SNAPSHOTS_USERNAME:SNAPSHOTS_PASSWORD'
- ]);
+ (core.getMultilineInput as jest.Mock).mockImplementation((name: string) =>
+ name === 'mvn-server-credentials'
+ ? [
+ 'releases:RELEASES_USERNAME:RELEASES_PASSWORD',
+ 'snapshots:SNAPSHOTS_USERNAME:SNAPSHOTS_PASSWORD'
+ ]
+ : name === 'mvn-server-repository-origins'
+ ? ['releases:https://repo.example.com']
+ : []
+ );
expect(auth.getMavenServerSettings()).toEqual([
{
id: 'releases',
usernameEnvVar: 'RELEASES_USERNAME',
- passwordEnvVar: 'RELEASES_PASSWORD'
+ passwordEnvVar: 'RELEASES_PASSWORD',
+ repositoryOrigins: ['https://repo.example.com']
},
{
id: 'snapshots',
@@ -803,6 +1258,106 @@ describe('auth tests', () => {
expect(core.warning).toHaveBeenCalledTimes(2);
});
+ it('adds normalized repository origins to matching Maven servers', () => {
+ expect(
+ auth.addMavenServerRepositoryOrigins(
+ [
+ {
+ id: 'central',
+ usernameEnvVar: 'CENTRAL_USER',
+ passwordEnvVar: 'CENTRAL_PASS'
+ },
+ {
+ id: 'packages',
+ usernameEnvVar: 'GITHUB_ACTOR',
+ passwordEnvVar: 'GITHUB_TOKEN'
+ }
+ ],
+ [
+ 'central:https://central.sonatype.com/',
+ 'central:https://central.sonatype.com',
+ 'central:https://central.sonatype.com:443',
+ 'packages:https://maven.pkg.github.com',
+ 'packages:ssh://packages.example.com:22',
+ 'packages:ftp://packages.example.com:21'
+ ]
+ )
+ ).toEqual([
+ {
+ id: 'central',
+ usernameEnvVar: 'CENTRAL_USER',
+ passwordEnvVar: 'CENTRAL_PASS',
+ repositoryOrigins: ['https://central.sonatype.com']
+ },
+ {
+ id: 'packages',
+ usernameEnvVar: 'GITHUB_ACTOR',
+ passwordEnvVar: 'GITHUB_TOKEN',
+ repositoryOrigins: [
+ 'https://maven.pkg.github.com',
+ 'ssh://packages.example.com:22',
+ 'ftp://packages.example.com:21'
+ ]
+ }
+ ]);
+ });
+
+ it.each([
+ {
+ entries: ['central'],
+ error:
+ 'Invalid mvn-server-repository-origins entry at line 1. Expected format: server-id:repository-origin'
+ },
+ {
+ entries: ['other:https://repo.example.com'],
+ error:
+ "Unknown server-id 'other' in mvn-server-repository-origins at line 1"
+ },
+ {
+ entries: ['central:https://repo.example.com/path'],
+ error:
+ "Invalid repository origin 'https://repo.example.com/path' in mvn-server-repository-origins at line 1"
+ },
+ {
+ entries: ['central:https:repo.example.com'],
+ error:
+ "Invalid repository origin 'https:repo.example.com' in mvn-server-repository-origins at line 1"
+ },
+ {
+ entries: ['central:https:/repo.example.com'],
+ error:
+ "Invalid repository origin 'https:/repo.example.com' in mvn-server-repository-origins at line 1"
+ },
+ {
+ entries: ['central:https://repo.example.com?'],
+ error:
+ "Invalid repository origin 'https://repo.example.com?' in mvn-server-repository-origins at line 1"
+ },
+ {
+ entries: ['central:https://repo.example.com#'],
+ error:
+ "Invalid repository origin 'https://repo.example.com#' in mvn-server-repository-origins at line 1"
+ },
+ {
+ entries: ['central:https://@repo.example.com'],
+ error:
+ "Invalid repository origin 'https://@repo.example.com' in mvn-server-repository-origins at line 1"
+ }
+ ])('rejects invalid Maven server repository origins', ({entries, error}) => {
+ expect(() =>
+ auth.addMavenServerRepositoryOrigins(
+ [
+ {
+ id: 'central',
+ usernameEnvVar: 'CENTRAL_USER',
+ passwordEnvVar: 'CENTRAL_PASS'
+ }
+ ],
+ entries
+ )
+ ).toThrow(error);
+ });
+
function xmlElementText(xml: string, tagName: string): string {
const match = new RegExp(`<${tagName}>([\\s\\S]*?)${tagName}>`).exec(xml);
expect(match).not.toBeNull();
diff --git a/__tests__/distributors/base-installer.test.ts b/__tests__/distributors/base-installer.test.ts
index 281f73e5e..1016a8fe6 100644
--- a/__tests__/distributors/base-installer.test.ts
+++ b/__tests__/distributors/base-installer.test.ts
@@ -1758,6 +1758,8 @@ describe('normalizeVersion', () => {
['11.0.9.1', {version: '11.0.9+1', stable: true, latest: false}],
['12.0.2.1.0', {version: '12.0.2+1.0', stable: true, latest: false}],
['18.0.1.1-ea', {version: '18.0.1+1', stable: false, latest: false}],
+ ['26.0.2.1+1', {version: '26.0.2+1.1', stable: true, latest: false}],
+ ['25.0.4.1+1', {version: '25.0.4+1.1', stable: true, latest: false}],
['latest', {version: 'x', stable: true, latest: true}],
['LATEST', {version: 'x', stable: true, latest: true}],
[' Latest ', {version: 'x', stable: true, latest: true}]
diff --git a/__tests__/distributors/distribution-factory.test.ts b/__tests__/distributors/distribution-factory.test.ts
index c473373a4..c60e7f75b 100644
--- a/__tests__/distributors/distribution-factory.test.ts
+++ b/__tests__/distributors/distribution-factory.test.ts
@@ -82,7 +82,7 @@ describe('getJavaDistribution', () => {
);
});
- it.each(['8', '23.x', '23.0.1.1', '<24'])(
+ it.each(['8', '23.x', '23.0.1.1', '23.0.1.1+1', '<24'])(
"rejects Temurin java-package 'jdk+jmods' for version %s",
async version => {
await expect(
@@ -96,7 +96,7 @@ describe('getJavaDistribution', () => {
}
);
- it.each(['24', '24.0.1.1', '25-ea', '>=21', 'latest'])(
+ it.each(['24', '24.0.1.1', '25.0.4.1+1', '25-ea', '>=21', 'latest'])(
"accepts Temurin java-package 'jdk+jmods' for version %s",
async version => {
expect(
diff --git a/__tests__/distributors/jetbrains-installer.test.ts b/__tests__/distributors/jetbrains-installer.test.ts
index 944a5ce71..ebc393652 100644
--- a/__tests__/distributors/jetbrains-installer.test.ts
+++ b/__tests__/distributors/jetbrains-installer.test.ts
@@ -14,7 +14,6 @@ import type {IncomingMessage} from 'http';
import {Readable} from 'stream';
import manifestData from '../data/jetbrains.json' with {type: 'json'};
-import os from 'os';
// Mock @actions/core before importing source modules that depend on it
jest.unstable_mockModule('@actions/core', () => ({
@@ -81,6 +80,7 @@ describe('getAvailableVersions', () => {
jest.setTimeout(10_000);
let spyHttpClient: any;
+ let spyHttpClientHead: any;
let spyCoreError: any;
const originalGitHubToken = process.env.GITHUB_TOKEN;
@@ -93,6 +93,10 @@ describe('getAvailableVersions', () => {
headers: {},
result: []
});
+ spyHttpClientHead = jest.spyOn(HttpClient.prototype, 'head');
+ spyHttpClientHead.mockResolvedValue({
+ message: {statusCode: 200}
+ } as any);
// Mock core.error to suppress error logs
spyCoreError = core.error as jest.Mock;
@@ -133,9 +137,7 @@ describe('getAvailableVersions', () => {
const availableVersions = await distribution['getAvailableVersions']();
expect(availableVersions).not.toBeNull();
- const length =
- os.platform() === 'win32' ? manifestData.length : manifestData.length + 2;
- expect(availableVersions.length).toBe(length);
+ expect(availableVersions.length).toBe(manifestData.length + 2);
}, 10_000);
it('continues a stable request after an all-prerelease page', async () => {
@@ -358,6 +360,7 @@ describe('getAvailableVersions', () => {
it('retries a GitHub rate limit using Retry-After', async () => {
spyHttpClient.mockRestore();
+ spyHttpClientHead.mockRestore();
const sleep = jest.fn(async () => undefined);
const requestRaw = jest
.spyOn(HttpClient.prototype, 'requestRaw')
diff --git a/__tests__/distributors/liberica-installer.test.ts b/__tests__/distributors/liberica-installer.test.ts
index ab1b72b2d..2005f5343 100644
--- a/__tests__/distributors/liberica-installer.test.ts
+++ b/__tests__/distributors/liberica-installer.test.ts
@@ -253,6 +253,39 @@ describe('findPackageForDownload', () => {
expect(result.version).toBe(expected);
});
+ describe('compound build versions', () => {
+ beforeEach(() => {
+ distribution['getAvailableVersions'] = async () =>
+ ['1', '1.1', '1.2', '1.10'].map(build => ({
+ featureVersion: 25,
+ interimVersion: 0,
+ updateVersion: 4,
+ buildVersion: 1,
+ version: `25.0.4+${build}`,
+ downloadUrl: `https://download.bell-sw.com/java/25.0.4+${build}/bellsoft-jdk25.0.4+${build}-macos-aarch64.tar.gz`
+ }));
+ });
+
+ it.each([
+ ['25.0.4+1.1', '25.0.4+1.1'],
+ ['25.0.4+1', '25.0.4+1'],
+ ['25.0.4', '25.0.4+1.10'],
+ ['25', '25.0.4+1.10']
+ ])('version is %s -> %s', async (input, expected) => {
+ const result = await distribution['findPackageForDownload'](input);
+ expect(result).toEqual({
+ version: expected,
+ url: `https://download.bell-sw.com/java/${expected}/bellsoft-jdk${expected}-macos-aarch64.tar.gz`
+ });
+ });
+
+ it('does not substitute a different compound build', async () => {
+ await expect(
+ distribution['findPackageForDownload']('25.0.4+1.3')
+ ).rejects.toThrow(/No matching version found for SemVer/);
+ });
+ });
+
it('should throw an error', async () => {
await expect(distribution['findPackageForDownload']('17')).rejects.toThrow(
/No matching version found for SemVer/
@@ -335,6 +368,36 @@ describe('convertVersionToSemver', () => {
buildVersion: 13
},
'11.0.0+13'
+ ],
+ [
+ {
+ version: '25.0.4+1.1',
+ featureVersion: 25,
+ interimVersion: 0,
+ updateVersion: 4,
+ buildVersion: 1
+ },
+ '25.0.4+1.1'
+ ],
+ [
+ {
+ version: '25+36',
+ featureVersion: 25,
+ interimVersion: 0,
+ updateVersion: 0,
+ buildVersion: 36
+ },
+ '25.0.0+36'
+ ],
+ [
+ {
+ version: '8u202',
+ featureVersion: 8,
+ interimVersion: 0,
+ updateVersion: 202,
+ buildVersion: 8
+ },
+ '8.0.202+8'
]
])('%s -> %s', (input, expected) => {
const actual = distributions['convertVersionToSemver']({
diff --git a/__tests__/distributors/temurin-installer.test.ts b/__tests__/distributors/temurin-installer.test.ts
index 7606627e6..2d424b33c 100644
--- a/__tests__/distributors/temurin-installer.test.ts
+++ b/__tests__/distributors/temurin-installer.test.ts
@@ -293,7 +293,8 @@ describe('getAvailableVersions', () => {
it.each([
['amd64', 'x64'],
['arm', 'arm'],
- ['arm64', 'aarch64']
+ ['arm64', 'aarch64'],
+ ['riscv64', 'riscv64']
])(
'defaults to os.arch(): %s mapped to distro arch: %s',
async (osArch: string, distroArch: string) => {
@@ -377,6 +378,97 @@ describe('findPackageForDownload', () => {
expect(resolvedVersion.version).toBe('16.0.2+7');
});
+ describe('OpenJDK patch (respin) versions', () => {
+ const makeRelease = (
+ semverVersion: string,
+ openjdkVersion: string,
+ versionData: Record
+ ) => ({
+ binaries: [
+ {
+ package: {
+ link: `https://example.com/${openjdkVersion}.tar.gz`,
+ checksum: `checksum-${openjdkVersion}`,
+ checksum_link: `https://example.com/${openjdkVersion}.sha256.txt`
+ }
+ }
+ ],
+ version_data: {
+ semver: semverVersion,
+ openjdk_version: openjdkVersion,
+ minor: 0,
+ ...versionData
+ }
+ });
+
+ const respinManifest = [
+ makeRelease('26.0.2+101', '26.0.2.1+1', {
+ major: 26,
+ security: 2,
+ patch: 1,
+ build: 1
+ }),
+ makeRelease('26.0.2+10', '26.0.2+10', {
+ major: 26,
+ security: 2,
+ build: 10
+ }),
+ makeRelease('25.0.4+101.0.LTS', '25.0.4.1+1-LTS', {
+ major: 25,
+ security: 4,
+ patch: 1,
+ build: 1
+ }),
+ makeRelease('25.0.4+7.0.LTS', '25.0.4+7-LTS', {
+ major: 25,
+ security: 4,
+ build: 7
+ })
+ ];
+
+ it.each([
+ ['26.0.2.1+1', '26.0.2+101'],
+ ['26.0.2+10', '26.0.2+10'],
+ ['26', '26.0.2+101'],
+ ['26.0.2', '26.0.2+101'],
+ ['25.0.4.1+1', '25.0.4+101.0.LTS'],
+ ['25.0.4+7', '25.0.4+7.0.LTS'],
+ ['25.0.4', '25.0.4+101.0.LTS']
+ ])('%s resolves to %s', async (input, expected) => {
+ const distribution = new TemurinDistribution(
+ {
+ version: input,
+ architecture: 'x64',
+ packageType: 'jdk',
+ checkLatest: false
+ },
+ TemurinImplementation.Hotspot
+ );
+ distribution['getAvailableVersions'] = async () => respinManifest as any;
+ const resolvedVersion = await distribution['findPackageForDownload'](
+ distribution['version']
+ );
+ expect(resolvedVersion.version).toBe(expected);
+ expect(resolvedVersion).not.toHaveProperty('openjdkVersion');
+ });
+
+ it('does not match a non-existent respin', async () => {
+ const distribution = new TemurinDistribution(
+ {
+ version: '26.0.2.2+1',
+ architecture: 'x64',
+ packageType: 'jdk',
+ checkLatest: false
+ },
+ TemurinImplementation.Hotspot
+ );
+ distribution['getAvailableVersions'] = async () => respinManifest as any;
+ await expect(
+ distribution['findPackageForDownload'](distribution['version'])
+ ).rejects.toThrow(/No matching version found for SemVer '26.0.2\+2.1'/);
+ });
+ });
+
it('version is found but binaries list is empty', async () => {
const distribution = new TemurinDistribution(
{
diff --git a/__tests__/distributors/zulu-installer.test.ts b/__tests__/distributors/zulu-installer.test.ts
index 20939cb9a..7b7b1856d 100644
--- a/__tests__/distributors/zulu-installer.test.ts
+++ b/__tests__/distributors/zulu-installer.test.ts
@@ -334,6 +334,69 @@ describe('findPackageForDownload', () => {
);
});
+ describe('hotfix builds with a 4-segment java_version', () => {
+ // Mirrors the Azul Metadata API: 25.0.4.1 hotfix is reported as
+ // java_version=[25,0,4,1], openjdk_build_number=1 (SDKMAN '25.0.4+1.1').
+ const hotfixManifest = [
+ {
+ package_uuid: 'uuid-25.0.4+7',
+ name: 'zulu25.36.15-ca-jdk25.0.4-linux_x64.tar.gz',
+ download_url:
+ 'https://cdn.azul.com/zulu/bin/zulu25.36.15-ca-jdk25.0.4-linux_x64.tar.gz',
+ java_version: [25, 0, 4],
+ openjdk_build_number: 7,
+ distro_version: [25, 36, 15, 0],
+ latest: false,
+ availability_type: 'ca'
+ },
+ {
+ package_uuid: 'uuid-25.0.4+1.1',
+ name: 'zulu25.36.205-ca-jdk25.0.4.1-linux_x64.tar.gz',
+ download_url:
+ 'https://cdn.azul.com/zulu/bin/zulu25.36.205-ca-jdk25.0.4.1-linux_x64.tar.gz',
+ java_version: [25, 0, 4, 1],
+ openjdk_build_number: 1,
+ distro_version: [25, 36, 205, 0],
+ latest: true,
+ availability_type: 'ca'
+ },
+ {
+ package_uuid: 'uuid-25.0.3+9',
+ name: 'zulu25.34.17-ca-jdk25.0.3-linux_x64.tar.gz',
+ download_url:
+ 'https://cdn.azul.com/zulu/bin/zulu25.34.17-ca-jdk25.0.3-linux_x64.tar.gz',
+ java_version: [25, 0, 3],
+ openjdk_build_number: 9,
+ distro_version: [25, 34, 17, 0],
+ latest: false,
+ availability_type: 'ca'
+ }
+ ] as IZuluVersions[];
+
+ it.each([
+ ['25.0.4+1.1', '25.0.4+1.1', 'uuid-25.0.4+1.1'],
+ ['25', '25.0.4+1.1', 'uuid-25.0.4+1.1'],
+ ['25.0.4', '25.0.4+1.1', 'uuid-25.0.4+1.1'],
+ ['25.0.4+7', '25.0.4+7', 'uuid-25.0.4+7'],
+ ['25.0.3', '25.0.3+9', 'uuid-25.0.3+9']
+ ])('version is %s -> %s', async (input, expected, uuid) => {
+ const distribution = new ZuluDistribution({
+ version: input,
+ architecture: 'x64',
+ packageType: 'jdk',
+ checkLatest: false
+ });
+ distribution['getAvailableVersions'] = async () => hotfixManifest;
+ const result = await distribution['findPackageForDownload'](
+ distribution['version']
+ );
+ expect(result.version).toBe(expected);
+ expect(result.url).toBe(
+ hotfixManifest.find(item => item.package_uuid === uuid)!.download_url
+ );
+ });
+ });
+
it('should throw an error', async () => {
const distribution = new ZuluDistribution({
version: '18',
diff --git a/__tests__/gpg.test.ts b/__tests__/gpg.test.ts
index f9a0ca3cc..93c4593a6 100644
--- a/__tests__/gpg.test.ts
+++ b/__tests__/gpg.test.ts
@@ -236,7 +236,12 @@ describe('gpg tests', () => {
process.env['RUNNER_TEMP'] = tempDir;
});
- it.each(['success', 'import failure', 'verification failure'])(
+ it.each([
+ 'success',
+ 'import failure',
+ 'verification failure',
+ 'gpgconf unavailable'
+ ])(
'uses a short macOS home or RUNNER_TEMP elsewhere and cleans up after %s',
async outcome => {
const longRunnerTemp = path.join(
@@ -257,9 +262,16 @@ describe('gpg tests', () => {
fs.writeFileSync(signaturePath, 'signature');
(tc.downloadTool as jest.Mock).mockResolvedValue(signaturePath);
(exec.exec as jest.Mock).mockImplementation(
- async (_command: string, args: string[]) => {
+ async (command: string, args: string[]) => {
gpgHome = path.join(expectedParent, path.posix.basename(args[1]));
expect(args[1]).toBe(gpg.toGpgPath(gpgHome));
+ if (command === 'gpgconf') {
+ expect(fs.existsSync(gpgHome)).toBe(true);
+ if (outcome === 'gpgconf unavailable') {
+ throw new Error('gpgconf unavailable');
+ }
+ return 0;
+ }
if (process.platform === 'darwin') {
expect(
Buffer.byteLength(path.join(gpgHome, 'S.gpg-agent.browser'))
@@ -287,13 +299,18 @@ describe('gpg tests', () => {
'https://example.com/jdk.tar.gz.sig',
'public key'
);
- if (outcome === 'success') {
+ if (outcome === 'success' || outcome === 'gpgconf unavailable') {
await verification;
} else {
await expect(verification).rejects.toThrow(outcome);
}
expect(exec.exec).toHaveBeenCalledTimes(
- outcome === 'import failure' ? 1 : 2
+ outcome === 'import failure' ? 2 : 3
+ );
+ expect(exec.exec).toHaveBeenLastCalledWith(
+ 'gpgconf',
+ ['--homedir', gpg.toGpgPath(gpgHome), '--kill', 'gpg-agent'],
+ {silent: true, ignoreReturnCode: true}
);
expect(fs.existsSync(gpgHome)).toBe(false);
expect(fs.existsSync(signaturePath)).toBe(false);
@@ -368,7 +385,7 @@ describe('gpg tests', () => {
],
expect.objectContaining({silent: true})
);
- expect(exec.exec).toHaveBeenCalledTimes(2);
+ expect(exec.exec).toHaveBeenCalledTimes(3);
});
});
});
diff --git a/__tests__/java-platform-contract.test.ts b/__tests__/java-platform-contract.test.ts
index 187a54a48..57a0df659 100644
--- a/__tests__/java-platform-contract.test.ts
+++ b/__tests__/java-platform-contract.test.ts
@@ -25,6 +25,7 @@ describe('Java platform capabilities', () => {
['aarch64', 'aarch64'],
['arm64', 'aarch64'],
['ppc64le', 'ppc64le'],
+ ['RiScV64', 'riscv64'],
['s390x', 's390x']
])('normalizes architecture %s to %s', (input, expected) => {
expect(normalizeArchitecture(input)).toBe(expected);
@@ -68,6 +69,12 @@ describe('Java platform capabilities', () => {
);
});
+ it('allows Temurin on Linux riscv64', () => {
+ expect(validateJavaPlatform('temurin', 'linux', 'riscv64', '25')).toBe(
+ 'riscv64'
+ );
+ });
+
it('rejects OS-specific restrictions with a consistent diagnostic', () => {
expect(() =>
validateJavaPlatform('oracle', 'win32', 'arm64', '21')
@@ -115,6 +122,7 @@ describe('Java platform capabilities', () => {
'aarch64',
'ppc64le',
'ppc64',
+ 'riscv64',
's390x'
]) {
expect(content).toContain(architecture);
diff --git a/__tests__/util.test.ts b/__tests__/util.test.ts
index 61143a596..87b10b74f 100644
--- a/__tests__/util.test.ts
+++ b/__tests__/util.test.ts
@@ -43,6 +43,7 @@ const core = await import('@actions/core');
const {
convertVersionToSemver,
+ normalizeJavaVersionToSemver,
getNextPageUrlFromLinkHeader,
getVersionFromFileContent,
isVersionSatisfies,
@@ -188,6 +189,22 @@ describe('convertVersionToSemver', () => {
});
});
+describe('normalizeJavaVersionToSemver', () => {
+ it.each([
+ ['17', '17'],
+ ['17.0.8', '17.0.8'],
+ ['17.0.8+7', '17.0.8+7'],
+ ['11.0.9.1', '11.0.9+1'],
+ ['12.0.2.1.0', '12.0.2+1.0'],
+ ['26.0.2.1+1', '26.0.2+1.1'],
+ ['17.0.8.1+1080.1', '17.0.8+1.1080.1'],
+ ['>=11.0.9.1', '>=11.0.9.1'],
+ ['17.x', '17.x']
+ ])('%s -> %s', (input: string, expected: string) => {
+ expect(normalizeJavaVersionToSemver(input)).toBe(expected);
+ });
+});
+
describe('getNextPageUrlFromLinkHeader', () => {
it.each([
[
@@ -276,6 +293,8 @@ describe('getVersionFromFileContent', () => {
['java=21.0.5-graal', '21.0.5', 'graalvm'],
['java=17.0.9-graalce', '17.0.9', 'graalvm'],
['java=11.0.25-librca', '11.0.25', 'liberica'],
+ ['java=25.0.4+1.1-librca', '25.0.4+1.1', 'liberica'],
+ ['java=25.0.4+1.1-zulu', '25.0.4+1.1', 'zulu'],
['java=11.0.25-ms', '11.0.25', 'microsoft'],
['java=21.0.5-oracle', '21.0.5', 'oracle'],
['java=11.0.25-sapmchn', '11.0.25', 'sapmachine'],
diff --git a/action.yml b/action.yml
index 1f244a223..eb32ec42c 100644
--- a/action.yml
+++ b/action.yml
@@ -17,7 +17,7 @@ inputs:
required: false
default: 'jdk'
architecture:
- description: "The architecture of the package (`x86`, `x64`, `armv7`, `aarch64`, `ppc64le`, `ppc64`, or `s390x`). Aliases `ia32`, `amd64`, `arm`, and `arm64` are normalized to `x86`, `x64`, `armv7`, and `aarch64`. Supported values vary by distribution and operating system. Defaults to the action runner's architecture."
+ description: "The architecture of the package (`x86`, `x64`, `armv7`, `aarch64`, `ppc64le`, `ppc64`, `riscv64`, or `s390x`). Aliases `ia32`, `amd64`, `arm`, and `arm64` are normalized to `x86`, `x64`, `armv7`, and `aarch64`. Supported values vary by distribution and operating system. Defaults to the action runner's architecture."
required: false
jdk-file:
description: 'Path to where the compressed JDK is located'
@@ -66,15 +66,21 @@ inputs:
mvn-server-credentials:
description: 'Multiline list of Maven server credentials in the format `server-id:USERNAME_ENV:PASSWORD_ENV`. When set, replaces the single server configured by server-id, server-username-env-var, and server-password-env-var.'
required: false
+ mvn-server-repository-origins:
+ description: 'Multiline list of Maven credential origins in the format `server-id:repository-origin`. Each origin must belong to a configured server ID. Requires Maven 3.10+.'
+ required: false
mvn-repositories:
description: 'Multiline list of Maven dependency repositories in the format `repository-id:repository-url:snapshots-enabled`.'
required: false
+ mvn-plugin-repositories:
+ description: 'Multiline list of Maven plugin repositories in the format `repository-id:repository-url:snapshots-enabled`.'
+ required: false
mvn-repositories-include-central:
- description: 'Include Maven Central in the generated dependency repositories profile. When false, Central is disabled unless an explicit repository with ID `central` is declared.'
+ description: 'Include Maven Central for dependency and plugin repositories in the generated profile. When false, Central is disabled for both types unless that type explicitly declares ID `central`. Has no effect when neither repository list is configured.'
required: false
default: true
mvn-repositories-prioritize-central:
- description: 'Place Maven Central before custom dependency repositories. Has no effect when Maven Central is excluded.'
+ description: 'Place Maven Central before custom dependency and plugin repositories. Has no effect when Maven Central is excluded or neither repository list is configured.'
required: false
default: true
settings-path:
diff --git a/dist/cleanup/767.index.js b/dist/cleanup/767.index.js
index 35dd21b98..2fe79f8a6 100644
--- a/dist/cleanup/767.index.js
+++ b/dist/cleanup/767.index.js
@@ -18360,9 +18360,102 @@ function readAttributeStr(xmlData, i) {
}
/**
- * Select all the attributes whether valid or invalid.
- */
-const validAttrStrRegxp = new RegExp('(\\s*)([^\\s=]+)(\\s*=)?(\\s*([\'"])(([\\s\\S])*?)\\5)?', 'g');
+ * Walk `attrStr` once, left to right, splitting it into attribute tokens.
+ *
+ * This replaces a regex that used to do the same job
+ * (`(\s*)([^\s=]+)(\s*=)?(\s*(['"])(([\s\S])*?)\5)?`). That regex led with an
+ * optional whitespace group followed by a required "non-whitespace" group.
+ * On a long run of whitespace that never resolves into an attribute name
+ * (e.g. a tag with thousands of trailing spaces before `>`), the engine
+ * backtracks the whitespace group one character at a time before giving up
+ * and moving to the next starting position — one full backtrack per
+ * position, which is quadratic in the length of the run.
+ *
+ * A single forward-only scan can never backtrack, so it can't be made slow
+ * this way no matter how much whitespace the input contains — it's always
+ * proportional to the length of the string, once.
+ *
+ * Each returned token mirrors the shape the old regex match array had, so
+ * the validation logic below (which reads token[1]..token[6]) didn't need
+ * to change:
+ * token.startIndex - where this token begins in attrStr
+ * token[1] - leading whitespace before the name
+ * token[2] - the attribute name
+ * token[3] - whitespace + '=' if present, else undefined
+ * token[4] - marker (any defined value) if a quoted value was found
+ * token[5] - the quote character used ('"' or "'")
+ * token[6] - the value's text, without the surrounding quotes
+ *
+ * A malformed leading character (e.g. a stray '=' with no name before it)
+ * is simply skipped over, one character at a time — the same outcome the
+ * old regex produced by failing to match at that position and retrying at
+ * the next one.
+ */
+function scanAttributeTokens(attrStr) {
+ const tokens = [];
+ const len = attrStr.length;
+ let i = 0;
+
+ while (i < len) {
+ const tokenStart = i;
+
+ // Leading whitespace before the name.
+ while (i < len && isWhiteSpace(attrStr[i])) i++;
+ if (i >= len) break; // trailing whitespace only — nothing left to read
+
+ if (attrStr[i] === '=') {
+ // No name before this '=' — not a valid attribute start. Move past
+ // just this one character and try again from the next position.
+ i = tokenStart + 1;
+ continue;
+ }
+
+ const leadingWs = attrStr.slice(tokenStart, i);
+
+ // Attribute name — everything up to the next whitespace or '='.
+ const nameStart = i;
+ while (i < len && !isWhiteSpace(attrStr[i]) && attrStr[i] !== '=') i++;
+ const name = attrStr.slice(nameStart, i);
+
+ // Optional whitespace + '='.
+ let equalsGroup; // whitespace + '=' text, or undefined if absent
+ let j = i;
+ while (j < len && isWhiteSpace(attrStr[j])) j++;
+ if (j < len && attrStr[j] === '=') {
+ equalsGroup = attrStr.slice(i, j + 1);
+ i = j + 1;
+ }
+
+ // Optional whitespace + quoted value.
+ let quoteChar;
+ let value;
+ let k = i;
+ while (k < len && isWhiteSpace(attrStr[k])) k++;
+ if (k < len && (attrStr[k] === '"' || attrStr[k] === "'")) {
+ const valueStart = k + 1;
+ const closeIdx = attrStr.indexOf(attrStr[k], valueStart);
+ if (closeIdx !== -1) {
+ quoteChar = attrStr[k];
+ value = attrStr.slice(valueStart, closeIdx);
+ i = closeIdx + 1;
+ }
+ // No closing quote found anywhere in the rest of the string — leave
+ // quoteChar/value undefined, same as the old regex's group failing
+ // to match a backreference-less run.
+ }
+
+ const token = { startIndex: tokenStart };
+ token[1] = leadingWs;
+ token[2] = name;
+ token[3] = equalsGroup;
+ token[4] = quoteChar !== undefined ? true : undefined;
+ token[5] = quoteChar;
+ token[6] = value;
+ tokens.push(token);
+ }
+
+ return tokens;
+}
//attr, ="sd", a="amit's", a="sd"b="saf", ab cd=""
@@ -18371,7 +18464,7 @@ function validateAttributeString(attrStr, options) {
//if(attrStr.trim().length === 0) return true; //empty string
- const matches = getAllMatches(attrStr, validAttrStrRegxp);
+ const matches = scanAttributeTokens(attrStr);
const attrNames = {};
for (let i = 0; i < matches.length; i++) {
@@ -18473,7 +18566,6 @@ function getLineNumberForPosition(xmlData, index) {
function getPositionFromMatch(match) {
return match.startIndex + match[1].length;
}
-
;// CONCATENATED MODULE: ./node_modules/fast-xml-parser/src/fxp.js
@@ -59498,6 +59590,24 @@ const EXPANSION_MAX = 100_000;
// realistic expansion (100k results hitting `EXPANSION_MAX` measure ~1M
// characters) so legitimate input is unaffected.
const EXPANSION_MAX_LENGTH = 4_000_000;
+// `expand_` recurses once per level of brace *nesting* - both when expanding a
+// set's comma members and when re-wrapping a set whose body is a single part.
+// The CVE-2026-14257 fix made the *tail* iterative (recursion on `m.post`, one
+// level per chained group), which left nesting depth unbounded: about 3,100
+// levels of `{{{...a,b...}}}` - only ~6KB of input - exhausted the native stack
+// and crashed the process. `EXPANSION_MAX_DEPTH` bounds how deep the parser
+// will follow nesting. It sits far above any realistic pattern and well below
+// the depth at which the stack runs out.
+const EXPANSION_MAX_DEPTH = 1_000;
+// Bash keeps a quirk where a brace group followed by a comma set still expands
+// (`{a},b}`). The parser implements it by rewriting the string and restarting
+// the scan, absorbing one `}` per pass. `n` trailing braces therefore cost `n`
+// full passes over a string that itself grows by one `escClose` sentinel each
+// time - quadratic in `n`, with a ~26x constant from the sentinel's length.
+// 128KB of `'{a}' + '}'.repeat(n) + ',z}'` blocked the event loop for 27
+// seconds to produce two results. `EXPANSION_MAX_REWRITES` bounds how many
+// times the scan may restart. Real `{a},b}` input needs a handful.
+const EXPANSION_MAX_REWRITES = 1_000;
function numeric(str) {
return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
}
@@ -59517,37 +59627,52 @@ function unescapeBraces(str) {
.replace(escCommaPattern, ',')
.replace(escPeriodPattern, '.');
}
+// Like `target.push(...items)` but doesn't overflow the stack
+function pushAll(target, items) {
+ for (let i = 0; i < items.length; i++) {
+ target.push(items[i]);
+ }
+}
/**
* Basically just str.split(","), but handling cases
* where we have nested braced sections, which should be
* treated as individual members, like {a,{b,c},d}
*/
function parseCommaParts(str) {
- if (!str) {
- return [''];
- }
const parts = [];
- const m = balanced('{', '}', str);
- if (!m) {
- return str.split(',');
- }
- const { pre, body, post } = m;
- const p = pre.split(',');
- p[p.length - 1] += '{' + body + '}';
- const postParts = parseCommaParts(post);
- if (post.length) {
- ;
- p[p.length - 1] += postParts.shift();
- p.push.apply(p, postParts);
- }
- parts.push.apply(parts, p);
- return parts;
+ // Walk the brace groups iteratively. Recursing on `post` once per group let a
+ // chain of them exhaust the stack - the parsing-side counterpart to
+ // the `expand_` overflow fixed for CVE-2026-14257, and not something `max` or
+ // `maxLength` can bound, since it happens before expansion.
+ //
+ // The part the next chunk continues
+ let carry = '';
+ for (;;) {
+ const m = balanced('{', '}', str);
+ if (!m) {
+ const tail = str.split(',');
+ tail[0] = carry + tail[0];
+ pushAll(parts, tail);
+ return parts;
+ }
+ const { pre, body, post } = m;
+ const p = pre.split(',');
+ p[0] = carry + p[0];
+ p[p.length - 1] += '{' + body + '}';
+ if (!post.length) {
+ pushAll(parts, p);
+ return parts;
+ }
+ carry = p.pop();
+ pushAll(parts, p);
+ str = post;
+ }
}
function expand(str, options = {}) {
if (!str) {
return [];
}
- const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH } = options;
+ const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH, maxDepth = EXPANSION_MAX_DEPTH, maxRewrites = EXPANSION_MAX_REWRITES, } = options;
// I don't know why Bash 4.3 does this, but it does.
// Anything starting with {} will have the first two bytes preserved
// but *only* at the top level, so {},a}b will not expand to anything,
@@ -59557,7 +59682,7 @@ function expand(str, options = {}) {
if (str.slice(0, 2) === '{}') {
str = '\\{\\}' + str.slice(2);
}
- return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
+ return expand_(escapeBraces(str), max, maxLength, maxDepth, 0, maxRewrites, true).map(unescapeBraces);
}
function embrace(str) {
return '{' + str + '}';
@@ -59652,7 +59777,13 @@ function expandSequence(body, isAlphaSequence, max, maxLength) {
}
return N;
}
-function expand_(str, max, maxLength, isTop) {
+function expand_(str, max, maxLength, maxDepth, depth, maxRewrites, isTop) {
+ // Too deeply nested to keep following: treat the rest as literal, the same
+ // way a group that cannot expand is already handled. Truncating rather than
+ // throwing keeps `expand` total, matching `max` and `maxLength`.
+ if (depth > maxDepth) {
+ return [str];
+ }
// Consume the string's top-level brace groups left to right, threading a
// running set of combined prefixes (`acc`). Expanding the tail iteratively -
// rather than recursing on `m.post` once per group - keeps the native stack
@@ -59664,6 +59795,9 @@ function expand_(str, max, maxLength, isTop) {
// comma set - a sequence like `{a..\}` may legitimately yield ''. The drop
// is on the final strings, so it is applied to whichever `combine` produces
// them (the one with no brace set left in the tail).
+ // How many times the `{a},b}` rewrite below has restarted the scan. Each pass
+ // re-reads the whole string, so leaving this unbounded is quadratic.
+ let rewrites = 0;
let dropEmpties = false;
let firstGroup = true;
for (;;) {
@@ -59688,7 +59822,8 @@ function expand_(str, max, maxLength, isTop) {
const isOptions = m.body.indexOf(',') >= 0;
if (!isSequence && !isOptions) {
// {a},b}
- if (m.post.match(/,(?!,).*\}/)) {
+ if (rewrites < maxRewrites && m.post.match(/,(?!,).*\}/)) {
+ rewrites++;
str = m.pre + '{' + m.body + escClose + m.post;
isTop = true;
continue;
@@ -59708,7 +59843,7 @@ function expand_(str, max, maxLength, isTop) {
let n = parseCommaParts(m.body);
if (n.length === 1 && n[0] !== undefined) {
// x{{a,b}}y ==> x{a}y x{b}y
- n = expand_(n[0], max, maxLength, false).map(embrace);
+ n = expand_(n[0], max, maxLength, maxDepth, depth + 1, maxRewrites, false).map(embrace);
//XXX is this necessary? Can't seem to hit it in tests.
/* c8 ignore start */
if (n.length === 1) {
@@ -59734,12 +59869,13 @@ function expand_(str, max, maxLength, isTop) {
values = [];
let valuesLength = 0;
outer: for (let j = 0; j < n.length; j++) {
- const expanded = expand_(n[j], max, maxLength, false);
+ const expanded = expand_(n[j], max, maxLength, maxDepth, depth + 1, maxRewrites, false);
for (let k = 0; k < expanded.length; k++) {
const v = expanded[k];
if (dropsEmpties && !v)
continue;
- if (values.length >= max || valuesLength + v.length > maxLength) {
+ if (values.length >= max ||
+ valuesLength + v.length > maxLength) {
break outer;
}
values.push(v);
diff --git a/dist/cleanup/index.js b/dist/cleanup/index.js
index 00ad7724f..03ab6fe1f 100644
--- a/dist/cleanup/index.js
+++ b/dist/cleanup/index.js
@@ -6009,11 +6009,77 @@ class Request {
}
}
- onUpgrade (statusCode, headers, socket) {
+ /**
+ * @param {number|null} statusCode
+ * @param {Buffer[]|null} headers
+ * @param {import('node:stream').Duplex} socket
+ * @param {string} [statusText]
+ */
+ onUpgrade (statusCode, headers, socket, statusText = '') {
+ this.onFinally()
+
assert(!this.aborted)
assert(!this.completed)
- return this[kHandler].onUpgrade(statusCode, headers, socket)
+ if (statusCode !== null) {
+ this.#publishUpgradeHeaders(statusCode, headers, statusText)
+ }
+
+ const result = this[kHandler].onUpgrade(statusCode, headers, socket)
+
+ if (!this.aborted) {
+ this.completed = true
+ if (statusCode !== null) {
+ this.#publishUpgradeTrailers()
+ }
+ }
+
+ return result
+ }
+
+ /**
+ * @param {number} statusCode
+ * @param {import('node:http2').IncomingHttpHeaders} headers
+ * @param {(headers: import('node:http2').IncomingHttpHeaders) => Buffer[]} parseHeaders
+ * @param {string} [statusText]
+ */
+ onUpgradeResponse (statusCode, headers, parseHeaders, statusText = '') {
+ assert(!this.aborted)
+ assert(this.completed)
+
+ if (channels.headers.hasSubscribers) {
+ this.#publishUpgradeHeaders(statusCode, parseHeaders(headers), statusText)
+ }
+ this.#publishUpgradeTrailers()
+ }
+
+ /**
+ * @param {Error} error
+ */
+ onUpgradeError (error) {
+ assert(!this.aborted)
+ assert(this.completed)
+
+ if (channels.error.hasSubscribers) {
+ channels.error.publish({ request: this, error })
+ }
+ }
+
+ /**
+ * @param {number} statusCode
+ * @param {Buffer[]} headers
+ * @param {string} statusText
+ */
+ #publishUpgradeHeaders (statusCode, headers, statusText) {
+ if (channels.headers.hasSubscribers) {
+ channels.headers.publish({ request: this, response: { statusCode, headers, statusText } })
+ }
+ }
+
+ #publishUpgradeTrailers () {
+ if (channels.trailers.hasSubscribers) {
+ channels.trailers.publish({ request: this, trailers: [] })
+ }
}
onComplete (trailers) {
@@ -7912,7 +7978,7 @@ class Parser {
}
onUpgrade (head) {
- const { upgrade, client, socket, headers, statusCode } = this
+ const { upgrade, client, socket, headers, statusCode, statusText } = this
assert(upgrade)
assert(client[kSocket] === socket)
@@ -7947,9 +8013,10 @@ class Parser {
client.emit('disconnect', client[kUrl], [client], new InformationalError('upgrade'))
try {
- request.onUpgrade(statusCode, headers, socket)
- } catch (err) {
- util.destroy(socket, err)
+ request.onUpgrade(statusCode, headers, socket, statusText)
+ } catch (error) {
+ util.errorRequest(client, request, error)
+ util.destroy(socket, error)
}
client[kResume]()
@@ -8356,7 +8423,7 @@ async function connectH1 (client, socket) {
function clearIdleSocketValidation (socket) {
if (socket[kIdleSocketValidationTimeout]) {
- clearTimeout(socket[kIdleSocketValidationTimeout])
+ clearImmediate(socket[kIdleSocketValidationTimeout])
socket[kIdleSocketValidationTimeout] = null
}
@@ -8365,15 +8432,23 @@ function clearIdleSocketValidation (socket) {
function scheduleIdleSocketValidation (client, socket) {
socket[kIdleSocketValidation] = 1
- socket[kIdleSocketValidationTimeout] = setTimeout(() => {
+ // Yield to the check phase (after poll) so unsolicited bytes / FIN / RST
+ // already pending on this idle keep-alive socket are processed before the
+ // next request is written (GHSA-35p6-xmwp-9g52).
+ //
+ // setTimeout(0) pays Node's ~1ms timer floor on every sequential reuse
+ // (#5493). setImmediate avoids that, but an *unref'd* Immediate lets poll
+ // block for ~500ms when the event loop is otherwise idle (#5600 / #5606).
+ // A ref'd Immediate both keeps the pending request alive and makes poll
+ // return immediately — the hybrid those issues asked for.
+ socket[kIdleSocketValidationTimeout] = setImmediate(() => {
socket[kIdleSocketValidationTimeout] = null
socket[kIdleSocketValidation] = 2
if (client[kSocket] === socket && !socket.destroyed) {
client[kResume]()
}
- }, 0)
- socket[kIdleSocketValidationTimeout].unref?.()
+ })
}
/**
@@ -8522,12 +8597,22 @@ function writeH1 (client, request) {
const socket = client[kSocket]
clearIdleSocketValidation(socket)
- const abort = (err) => {
- if (request.aborted || request.completed) {
+ /**
+ * @param {Error} [error]
+ */
+ const abort = (error) => {
+ if (request.aborted) {
return
}
- util.errorRequest(client, request, err || new RequestAbortedError())
+ if (request.completed) {
+ if (request.upgrade || request.method === 'CONNECT') {
+ util.destroy(socket, new InformationalError('aborted'))
+ }
+ return
+ }
+
+ util.errorRequest(client, request, error || new RequestAbortedError())
util.destroy(body)
util.destroy(socket, new InformationalError('aborted'))
@@ -8984,6 +9069,7 @@ module.exports = connectH1
const assert = __nccwpck_require__(4589)
+const { errorMonitor } = __nccwpck_require__(8474)
const { pipeline } = __nccwpck_require__(7075)
const util = __nccwpck_require__(3440)
const {
@@ -9060,6 +9146,15 @@ function parseH2Headers (headers) {
return result
}
+/**
+ * @param {import('node:http2').IncomingHttpHeaders} headers
+ * @returns {Buffer[]}
+ */
+function parseH2ResponseHeaders (headers) {
+ const { [HTTP2_HEADER_STATUS]: _statusCode, ...realHeaders } = headers
+ return parseH2Headers(realHeaders)
+}
+
async function connectH2 (client, socket) {
client[kSocket] = socket
@@ -9280,22 +9375,32 @@ function writeH2 (client, request) {
headers[HTTP2_HEADER_AUTHORITY] = host || `${hostname}${port ? `:${port}` : ''}`
headers[HTTP2_HEADER_METHOD] = method
- const abort = (err) => {
- if (request.aborted || request.completed) {
+ /**
+ * @param {Error} [error]
+ */
+ const abort = (error) => {
+ if (request.aborted) {
return
}
- err = err || new RequestAbortedError()
+ if (request.completed) {
+ if (method === 'CONNECT' && stream != null) {
+ util.destroy(stream, error || new RequestAbortedError())
+ }
+ return
+ }
- util.errorRequest(client, request, err)
+ error = error || new RequestAbortedError()
+
+ util.errorRequest(client, request, error)
if (stream != null) {
- util.destroy(stream, err)
+ util.destroy(stream, error)
}
// We do not destroy the socket as we can continue using the session
// the stream get's destroyed and the session remains to create new streams
- util.destroy(body, err)
+ util.destroy(body, error)
client[kQueue][client[kRunningIdx]++] = null
client[kResume]()
}
@@ -9314,25 +9419,57 @@ function writeH2 (client, request) {
if (method === 'CONNECT') {
session.ref()
- // We are already connected, streams are pending, first request
- // will create a new stream. We trigger a request to create the stream and wait until
- // `ready` event is triggered
// We disabled endStream to allow the user to write to the stream
stream = session.request(headers, { endStream: false, signal })
+ let upgradeResponseFinished = false
- if (stream.id && !stream.pending) {
- request.onUpgrade(null, null, stream)
- ++session[kOpenStreams]
- client[kQueue][client[kRunningIdx]++] = null
- } else {
- stream.once('ready', () => {
+ /**
+ * @param {import('node:http2').IncomingHttpHeaders} headers
+ */
+ const onResponse = (headers) => {
+ upgradeResponseFinished = true
+ stream.off(errorMonitor, onUpgradeError)
+ request.onUpgradeResponse(Number(headers[HTTP2_HEADER_STATUS]), headers, parseH2ResponseHeaders)
+ }
+
+ /**
+ * @param {Error} error
+ */
+ const onUpgradeError = (error) => {
+ upgradeResponseFinished = true
+ stream.off('response', onResponse)
+ request.onUpgradeError(error)
+ }
+
+ const onReady = () => {
+ try {
request.onUpgrade(null, null, stream)
- ++session[kOpenStreams]
- client[kQueue][client[kRunningIdx]++] = null
- })
+ } catch (error) {
+ stream.off('response', onResponse)
+ abort(error)
+ return
+ }
+
+ if (request.aborted) {
+ return
+ }
+
+ stream.off('error', abort)
+ stream.once(errorMonitor, onUpgradeError)
+ client[kQueue][client[kRunningIdx]++] = null
}
+ stream.once('response', onResponse)
+ stream.once('error', abort)
+ ++session[kOpenStreams]
+ onReady()
+
stream.once('close', () => {
+ if (!upgradeResponseFinished && request.completed) {
+ stream.off('response', onResponse)
+ stream.off(errorMonitor, onUpgradeError)
+ request.onUpgradeError(new InformationalError(`HTTP/2: "stream error" received - code ${stream.rstCode}`))
+ }
session[kOpenStreams] -= 1
if (session[kOpenStreams] === 0) session.unref()
})
@@ -12031,6 +12168,7 @@ class RetryHandler {
this.end = null
this.etag = null
this.resume = null
+ this.headersSent = false
// Handle possible onConnect duplication
this.handler.onConnect(reason => {
@@ -12043,6 +12181,20 @@ class RetryHandler {
})
}
+ checkpointResponseEnd (headers, resume) {
+ if (this.end == null && this.opts.method !== 'HEAD') {
+ const contentLength = headers['content-length']
+ this.end = contentLength != null ? Number(contentLength) - 1 : null
+
+ assert(
+ this.end == null || Number.isFinite(this.end),
+ 'invalid content-length'
+ )
+ }
+
+ this.resume = this.end != null ? resume : null
+ }
+
onRequestSent () {
if (this.handler.onRequestSent) {
this.handler.onRequestSent()
@@ -12131,7 +12283,12 @@ class RetryHandler {
this.retryCount += 1
if (statusCode >= 300) {
- if (this.retryOpts.statusCodes.includes(statusCode) === false) {
+ // Only expose a response if no earlier attempt has reached the caller.
+ // Otherwise abort this attempt so the error settles the existing body
+ // instead of replacing it with a new response.
+ if (!this.headersSent && this.retryOpts.statusCodes.includes(statusCode) === false) {
+ this.headersSent = true
+ this.checkpointResponseEnd(headers, resume)
return this.handler.onHeaders(
statusCode,
rawHeaders,
@@ -12200,8 +12357,15 @@ class RetryHandler {
const { start, size, end = size - 1 } = contentRange
- assert(this.start === start, 'content-range mismatch')
- assert(this.end == null || this.end === end, 'content-range mismatch')
+ if (this.start !== start || (this.end != null && this.end !== end)) {
+ this.abort(
+ new RequestRetryError('Content-Range mismatch', statusCode, {
+ headers,
+ data: { count: this.retryCount }
+ })
+ )
+ return false
+ }
this.resume = resume
return true
@@ -12213,6 +12377,7 @@ class RetryHandler {
const range = parseRangeHeader(headers['content-range'])
if (range == null) {
+ this.headersSent = true
return this.handler.onHeaders(
statusCode,
rawHeaders,
@@ -12251,6 +12416,7 @@ class RetryHandler {
)
this.resume = resume
+ this.headersSent = true
this.etag = headers.etag != null ? headers.etag : null
// Weak etags are not useful for comparison nor cache
@@ -12290,7 +12456,7 @@ class RetryHandler {
}
onError (err) {
- if (this.aborted || isDisturbed(this.opts.body)) {
+ if (this.aborted || isDisturbed(this.opts.body) || (this.headersSent && this.resume == null)) {
return this.handler.onError(err)
}
@@ -16748,6 +16914,49 @@ const COLON = 0x3A
*/
const SPACE = 0x20
+const DATA = Buffer.from('data')
+const EVENT = Buffer.from('event')
+const ID = Buffer.from('id')
+const RETRY = Buffer.from('retry')
+
+function isASCIINumberBytes (buffer, start) {
+ if (start >= buffer.length) {
+ return false
+ }
+
+ for (let i = start; i < buffer.length; i++) {
+ if (buffer[i] < 0x30 || buffer[i] > 0x39) {
+ return false
+ }
+ }
+
+ return true
+}
+
+function isValidLastEventIdBytes (buffer, start) {
+ for (let i = start; i < buffer.length; i++) {
+ if (buffer[i] === 0x00) {
+ return false
+ }
+ }
+
+ return true
+}
+
+function isFieldName (line, length, field) {
+ if (length !== field.length) {
+ return false
+ }
+
+ for (let i = 0; i < length; i++) {
+ if (line[i] !== field[i]) {
+ return false
+ }
+ }
+
+ return true
+}
+
/**
* @typedef {object} EventSourceStreamEvent
* @type {object}
@@ -16788,11 +16997,14 @@ class EventSourceStream extends Transform {
eventEndCheck = false
/**
- * @type {Buffer}
+ * @type {Buffer[]}
*/
- buffer = null
+ chunks = []
+ chunkIndex = 0
pos = 0
+ lineChunkIndex = 0
+ linePos = 0
event = {
data: undefined,
@@ -16831,92 +17043,20 @@ class EventSourceStream extends Transform {
return
}
- // Cache the chunk in the buffer, as the data might not be complete while
- // processing it
- // TODO: Investigate if there is a more performant way to handle
- // incoming chunks
- // see: https://github.com/nodejs/undici/issues/2630
- if (this.buffer) {
- this.buffer = Buffer.concat([this.buffer, chunk])
- } else {
- this.buffer = chunk
- }
+ this.chunks.push(chunk)
// Strip leading byte-order-mark if we opened the stream and started
// the processing of the incoming data
if (this.checkBOM) {
- switch (this.buffer.length) {
- case 1:
- // Check if the first byte is the same as the first byte of the BOM
- if (this.buffer[0] === BOM[0]) {
- // If it is, we need to wait for more data
- callback()
- return
- }
- // Set the checkBOM flag to false as we don't need to check for the
- // BOM anymore
- this.checkBOM = false
-
- // The buffer only contains one byte so we need to wait for more data
- callback()
- return
- case 2:
- // Check if the first two bytes are the same as the first two bytes
- // of the BOM
- if (
- this.buffer[0] === BOM[0] &&
- this.buffer[1] === BOM[1]
- ) {
- // If it is, we need to wait for more data, because the third byte
- // is needed to determine if it is the BOM or not
- callback()
- return
- }
-
- // Set the checkBOM flag to false as we don't need to check for the
- // BOM anymore
- this.checkBOM = false
- break
- case 3:
- // Check if the first three bytes are the same as the first three
- // bytes of the BOM
- if (
- this.buffer[0] === BOM[0] &&
- this.buffer[1] === BOM[1] &&
- this.buffer[2] === BOM[2]
- ) {
- // If it is, we can drop the buffered data, as it is only the BOM
- this.buffer = Buffer.alloc(0)
- // Set the checkBOM flag to false as we don't need to check for the
- // BOM anymore
- this.checkBOM = false
-
- // Await more data
- callback()
- return
- }
- // If it is not the BOM, we can start processing the data
- this.checkBOM = false
- break
- default:
- // The buffer is longer than 3 bytes, so we can drop the BOM if it is
- // present
- if (
- this.buffer[0] === BOM[0] &&
- this.buffer[1] === BOM[1] &&
- this.buffer[2] === BOM[2]
- ) {
- // Remove the BOM from the buffer
- this.buffer = this.buffer.subarray(3)
- }
-
- // Set the checkBOM flag to false as we don't need to check for the
- this.checkBOM = false
- break
+ if (this.handleBOM()) {
+ callback()
+ return
}
}
- while (this.pos < this.buffer.length) {
+ while (this.hasCurrentByte()) {
+ const byte = this.currentByte()
+
// If the previous line ended with an end-of-line, we need to check
// if the next character is also an end-of-line.
if (this.eventEndCheck) {
@@ -16929,10 +17069,9 @@ class EventSourceStream extends Transform {
if (this.crlfCheck) {
// If the current character is a line feed, we can remove it
// from the buffer and reset the crlfCheck flag
- if (this.buffer[this.pos] === LF) {
- this.buffer = this.buffer.subarray(this.pos + 1)
- this.pos = 0
+ if (byte === LF) {
this.crlfCheck = false
+ this.consumeCurrentByte()
// It is possible that the line feed is not the end of the
// event. We need to check if the next character is an
@@ -16948,19 +17087,17 @@ class EventSourceStream extends Transform {
this.crlfCheck = false
}
- if (this.buffer[this.pos] === LF || this.buffer[this.pos] === CR) {
+ if (byte === LF || byte === CR) {
// If the current character is a carriage return, we need to
// set the crlfCheck flag to true, as we need to check if the
// next character is a line feed so we can remove it from the
// buffer
- if (this.buffer[this.pos] === CR) {
+ if (byte === CR) {
this.crlfCheck = true
}
- this.buffer = this.buffer.subarray(this.pos + 1)
- this.pos = 0
- if (
- this.event.data !== undefined || this.event.event || this.event.id || this.event.retry) {
+ this.consumeCurrentByte()
+ if (this.hasPendingEvent()) {
this.processEvent(this.event)
}
this.clearEvent()
@@ -16974,22 +17111,18 @@ class EventSourceStream extends Transform {
// If the current character is an end-of-line, we can process the
// line
- if (this.buffer[this.pos] === LF || this.buffer[this.pos] === CR) {
+ if (byte === LF || byte === CR) {
// If the current character is a carriage return, we need to
// set the crlfCheck flag to true, as we need to check if the
// next character is a line feed
- if (this.buffer[this.pos] === CR) {
+ if (byte === CR) {
this.crlfCheck = true
}
// In any case, we can process the line as we reached an
// end-of-line character
- this.parseLine(this.buffer.subarray(0, this.pos), this.event)
-
- // Remove the processed line from the buffer
- this.buffer = this.buffer.subarray(this.pos + 1)
- // Reset the position as we removed the processed line from the buffer
- this.pos = 0
+ this.parseLine(this.readLine(), this.event)
+ this.consumeCurrentByte()
// A line was processed and this could be the end of the event. We need
// to check if the next line is empty to determine if the event is
// finished.
@@ -16997,7 +17130,7 @@ class EventSourceStream extends Transform {
continue
}
- this.pos++
+ this.advanceCursor()
}
callback()
@@ -17022,64 +17155,53 @@ class EventSourceStream extends Transform {
return
}
- let field = ''
- let value = ''
+ let fieldLength = line.length
+ let valueStart = line.length
// If the line contains a U+003A COLON character (:)
if (colonPosition !== -1) {
- // Collect the characters on the line before the first U+003A COLON
- // character (:), and let field be that string.
- // TODO: Investigate if there is a more performant way to extract the
- // field
- // see: https://github.com/nodejs/undici/issues/2630
- field = line.subarray(0, colonPosition).toString('utf8')
+ fieldLength = colonPosition
// Collect the characters on the line after the first U+003A COLON
// character (:), and let value be that string.
// If value starts with a U+0020 SPACE character, remove it from value.
- let valueStart = colonPosition + 1
+ valueStart = colonPosition + 1
if (line[valueStart] === SPACE) {
++valueStart
}
- // TODO: Investigate if there is a more performant way to extract the
- // value
- // see: https://github.com/nodejs/undici/issues/2630
- value = line.subarray(valueStart).toString('utf8')
+ }
- // Otherwise, the string is not empty but does not contain a U+003A COLON
- // character (:)
- } else {
- // Process the field using the steps described below, using the whole
- // line as the field name, and the empty string as the field value.
- field = line.toString('utf8')
- value = ''
- }
-
- // Modify the event with the field name and value. The value is also
- // decoded as UTF-8
- switch (field) {
- case 'data':
- if (event[field] === undefined) {
- event[field] = value
- } else {
- event[field] += `\n${value}`
- }
- break
- case 'retry':
- if (isASCIINumber(value)) {
- event[field] = value
- }
- break
- case 'id':
- if (isValidLastEventId(value)) {
- event[field] = value
- }
- break
- case 'event':
- if (value.length > 0) {
- event[field] = value
- }
- break
+ if (isFieldName(line, fieldLength, DATA)) {
+ const value = line.toString('utf8', valueStart)
+
+ if (event.data === undefined) {
+ event.data = value
+ } else {
+ event.data += `\n${value}`
+ }
+ return
+ }
+
+ if (isFieldName(line, fieldLength, RETRY)) {
+ if (isASCIINumberBytes(line, valueStart)) {
+ event.retry = line.toString('utf8', valueStart)
+ }
+ return
+ }
+
+ if (isFieldName(line, fieldLength, ID)) {
+ if (isValidLastEventIdBytes(line, valueStart)) {
+ event.id = line.toString('utf8', valueStart)
+ }
+ return
+ }
+
+ if (isFieldName(line, fieldLength, EVENT)) {
+ const value = line.toString('utf8', valueStart)
+
+ if (value.length > 0) {
+ event.event = value
+ }
}
}
@@ -17109,13 +17231,152 @@ class EventSourceStream extends Transform {
}
clearEvent () {
- this.event = {
- data: undefined,
- event: undefined,
- id: undefined,
- retry: undefined
+ this.event.data = undefined
+ this.event.event = undefined
+ this.event.id = undefined
+ this.event.retry = undefined
+ }
+
+ hasPendingEvent () {
+ return this.event.data !== undefined ||
+ this.event.event !== undefined ||
+ this.event.id !== undefined ||
+ this.event.retry !== undefined
+ }
+
+ hasCurrentByte () {
+ return this.chunkIndex < this.chunks.length &&
+ this.pos < this.chunks[this.chunkIndex].length
+ }
+
+ currentByte () {
+ return this.chunks[this.chunkIndex][this.pos]
+ }
+
+ consumeCurrentByte () {
+ this.advanceCursor()
+ this.syncLineStartToCursor()
+ }
+
+ advanceCursor () {
+ this.pos++
+
+ while (this.chunkIndex < this.chunks.length && this.pos >= this.chunks[this.chunkIndex].length) {
+ this.chunkIndex++
+ this.pos = 0
+ }
+ }
+
+ syncLineStartToCursor () {
+ this.lineChunkIndex = this.chunkIndex
+ this.linePos = this.pos
+ this.dropConsumedChunks()
+ }
+
+ dropConsumedChunks () {
+ while (this.lineChunkIndex > 0) {
+ this.chunks.shift()
+ this.lineChunkIndex--
+ this.chunkIndex--
+ }
+
+ if (this.chunkIndex === this.chunks.length) {
+ this.chunks.length = 0
+ this.chunkIndex = 0
+ this.pos = 0
+ this.lineChunkIndex = 0
+ this.linePos = 0
+ }
+ }
+
+ readLine () {
+ if (this.lineChunkIndex === this.chunkIndex) {
+ return this.chunks[this.chunkIndex].subarray(this.linePos, this.pos)
+ }
+
+ const chunks = []
+ let length = 0
+
+ for (let i = this.lineChunkIndex; i <= this.chunkIndex; i++) {
+ const chunk = this.chunks[i]
+ const start = i === this.lineChunkIndex ? this.linePos : 0
+ const end = i === this.chunkIndex ? this.pos : chunk.length
+ const slice = chunk.subarray(start, end)
+ length += slice.length
+ chunks.push(slice)
+ }
+
+ return Buffer.concat(chunks, length)
+ }
+
+ peekBufferedByte (offset) {
+ let chunkIndex = this.lineChunkIndex
+ let pos = this.linePos
+
+ while (chunkIndex < this.chunks.length) {
+ const chunk = this.chunks[chunkIndex]
+ const remaining = chunk.length - pos
+
+ if (offset < remaining) {
+ return chunk[pos + offset]
+ }
+
+ offset -= remaining
+ chunkIndex++
+ pos = 0
}
}
+
+ discardLeadingBytes (count) {
+ while (count > 0 && this.lineChunkIndex < this.chunks.length) {
+ const chunk = this.chunks[this.lineChunkIndex]
+ const remaining = chunk.length - this.linePos
+
+ if (count < remaining) {
+ this.linePos += count
+ count = 0
+ } else {
+ count -= remaining
+ this.lineChunkIndex++
+ this.linePos = 0
+ }
+ }
+
+ this.chunkIndex = this.lineChunkIndex
+ this.pos = this.linePos
+ this.dropConsumedChunks()
+ }
+
+ handleBOM () {
+ const first = this.peekBufferedByte(0)
+ const second = this.peekBufferedByte(1)
+ const third = this.peekBufferedByte(2)
+
+ if (second === undefined) {
+ if (first === BOM[0]) {
+ return true
+ }
+
+ this.checkBOM = false
+ return true
+ }
+
+ if (third === undefined) {
+ if (first === BOM[0] && second === BOM[1]) {
+ return true
+ }
+
+ this.checkBOM = false
+ return false
+ }
+
+ if (first === BOM[0] && second === BOM[1] && third === BOM[2]) {
+ this.discardLeadingBytes(3)
+ }
+
+ this.checkBOM = false
+ return !this.hasCurrentByte()
+ }
}
module.exports = {
@@ -28383,7 +28644,7 @@ function establishWebSocketConnection (url, protocols, client, ws, onEstablish,
// is specified, the server needs to include the same field and one of
// the selected subprotocol values in its response for the connection to
// be established.
- if (!requestProtocols.includes(secProtocol)) {
+ if (requestProtocols === null || !requestProtocols.includes(secProtocol)) {
failWebsocketConnection(ws, 'Protocol was not set in the opening handshake.')
return
}
@@ -29144,7 +29405,12 @@ class PerMessageDeflate {
if (this.#maxPayloadSize > 0 && this.#inflate[kLength] > this.#maxPayloadSize) {
callback(new MessageSizeExceededError())
+ // The inflater may still hold buffered input that can emit a late
+ // zlib error. Remove the data listener, then deterministically stop
+ // the stream so a subsequent 'error' cannot fire without a listener
+ // (which would terminate the process as an unhandled error event).
this.#inflate.removeAllListeners()
+ this.#inflate.destroy()
this.#inflate = null
return
}
@@ -30774,7 +31040,7 @@ module.exports = {
/* harmony export */ gk: () => (/* binding */ INPUT_CACHE),
/* harmony export */ wG: () => (/* binding */ INPUT_JOB_STATUS)
/* harmony export */ });
-/* unused harmony exports MACOS_JAVA_CONTENT_POSTFIX, INPUT_JAVA_VERSION, INPUT_JAVA_VERSION_FILE, INPUT_ARCHITECTURE, INPUT_JAVA_PACKAGE, INPUT_DISTRIBUTION, INPUT_JDK_FILE, INPUT_JDK_FILE_DEPRECATED, INPUT_CHECK_LATEST, INPUT_FORCE_DOWNLOAD, INPUT_SET_DEFAULT, INPUT_PROBLEM_MATCHER, INPUT_VERIFY_SIGNATURE, INPUT_VERIFY_SIGNATURE_PUBLIC_KEY, SIGNATURE_VERIFICATION_DOCUMENTATION_URL, SIGNATURE_VERIFICATION_FAILURE_HELP, INPUT_MVN_SERVER_CREDENTIALS, INPUT_MVN_REPOSITORIES, INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL, INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL, INPUT_SERVER_ID, INPUT_SERVER_USERNAME_ENV_VAR, INPUT_SERVER_PASSWORD_ENV_VAR, INPUT_SERVER_USERNAME_DEPRECATED, INPUT_SERVER_PASSWORD_DEPRECATED, INPUT_SETTINGS_PATH, INPUT_OVERWRITE_SETTINGS, INPUT_GPG_PRIVATE_KEY, INPUT_GPG_PASSPHRASE_ENV_VAR, INPUT_GPG_PASSPHRASE_DEPRECATED, INPUT_DEFAULT_SERVER_USERNAME, INPUT_DEFAULT_SERVER_PASSWORD, INPUT_DEFAULT_GPG_PRIVATE_KEY, INPUT_DEFAULT_GPG_PASSPHRASE, MAVEN_GPG_PASSPHRASE_DEFAULT_ENV, GPG_PASSPHRASE_PROFILE_ID, MAVEN_REPOSITORIES_PROFILE_ID, MAVEN_CENTRAL_REPOSITORY_ID, MAVEN_CENTRAL_REPOSITORY_URL, INPUT_CACHE_DEPENDENCY_PATH, INPUT_CACHE_PATH, M2_DIR, MVN_SETTINGS_FILE, MVN_TOOLCHAINS_FILE, INPUT_MVN_TOOLCHAIN_ID, INPUT_MVN_TOOLCHAIN_VENDOR, INPUT_SHOW_DOWNLOAD_PROGRESS, MAVEN_ARGS_ENV, MAVEN_NO_TRANSFER_PROGRESS_FLAG, MAVEN_NO_TRANSFER_PROGRESS_LONG_FLAG, DISTRIBUTIONS_ONLY_MAJOR_VERSION */
+/* unused harmony exports MACOS_JAVA_CONTENT_POSTFIX, INPUT_JAVA_VERSION, INPUT_JAVA_VERSION_FILE, INPUT_ARCHITECTURE, INPUT_JAVA_PACKAGE, INPUT_DISTRIBUTION, INPUT_JDK_FILE, INPUT_JDK_FILE_DEPRECATED, INPUT_CHECK_LATEST, INPUT_FORCE_DOWNLOAD, INPUT_SET_DEFAULT, INPUT_PROBLEM_MATCHER, INPUT_VERIFY_SIGNATURE, INPUT_VERIFY_SIGNATURE_PUBLIC_KEY, SIGNATURE_VERIFICATION_DOCUMENTATION_URL, SIGNATURE_VERIFICATION_FAILURE_HELP, INPUT_MVN_SERVER_CREDENTIALS, INPUT_MVN_SERVER_REPOSITORY_ORIGINS, INPUT_MVN_REPOSITORIES, INPUT_MVN_PLUGIN_REPOSITORIES, INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL, INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL, INPUT_SERVER_ID, INPUT_SERVER_USERNAME_ENV_VAR, INPUT_SERVER_PASSWORD_ENV_VAR, INPUT_SERVER_USERNAME_DEPRECATED, INPUT_SERVER_PASSWORD_DEPRECATED, INPUT_SETTINGS_PATH, INPUT_OVERWRITE_SETTINGS, INPUT_GPG_PRIVATE_KEY, INPUT_GPG_PASSPHRASE_ENV_VAR, INPUT_GPG_PASSPHRASE_DEPRECATED, INPUT_DEFAULT_SERVER_USERNAME, INPUT_DEFAULT_SERVER_PASSWORD, INPUT_DEFAULT_GPG_PRIVATE_KEY, INPUT_DEFAULT_GPG_PASSPHRASE, MAVEN_GPG_PASSPHRASE_DEFAULT_ENV, GPG_PASSPHRASE_PROFILE_ID, MAVEN_REPOSITORIES_PROFILE_ID, MAVEN_CENTRAL_REPOSITORY_ID, MAVEN_CENTRAL_REPOSITORY_URL, INPUT_CACHE_DEPENDENCY_PATH, INPUT_CACHE_PATH, M2_DIR, MVN_SETTINGS_FILE, MVN_TOOLCHAINS_FILE, INPUT_MVN_TOOLCHAIN_ID, INPUT_MVN_TOOLCHAIN_VENDOR, INPUT_SHOW_DOWNLOAD_PROGRESS, MAVEN_ARGS_ENV, MAVEN_NO_TRANSFER_PROGRESS_FLAG, MAVEN_NO_TRANSFER_PROGRESS_LONG_FLAG, DISTRIBUTIONS_ONLY_MAJOR_VERSION */
const MACOS_JAVA_CONTENT_POSTFIX = 'Contents/Home';
const INPUT_JAVA_VERSION = 'java-version';
const INPUT_JAVA_VERSION_FILE = 'java-version-file';
@@ -30792,7 +31058,9 @@ const INPUT_VERIFY_SIGNATURE_PUBLIC_KEY = 'verify-signature-public-key';
const SIGNATURE_VERIFICATION_DOCUMENTATION_URL = 'https://github.com/actions/setup-java#download-integrity-and-signatures';
const SIGNATURE_VERIFICATION_FAILURE_HELP = (/* unused pure expression or super */ null && (`If this is a legitimate vendor signing-key rotation, see ${SIGNATURE_VERIFICATION_DOCUMENTATION_URL} for instructions to configure the updated public key or temporarily disable signature verification.`));
const INPUT_MVN_SERVER_CREDENTIALS = 'mvn-server-credentials';
+const INPUT_MVN_SERVER_REPOSITORY_ORIGINS = 'mvn-server-repository-origins';
const INPUT_MVN_REPOSITORIES = 'mvn-repositories';
+const INPUT_MVN_PLUGIN_REPOSITORIES = 'mvn-plugin-repositories';
const INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL = 'mvn-repositories-include-central';
const INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL = 'mvn-repositories-prioritize-central';
const INPUT_SERVER_ID = 'server-id';
@@ -30848,7 +31116,7 @@ const DISTRIBUTIONS_ONLY_MAJOR_VERSION = (/* unused pure expression or super */
/* harmony export */ Vt: () => (/* binding */ getBooleanInput),
/* harmony export */ lN: () => (/* binding */ isJdkCacheEnabled)
/* harmony export */ });
-/* unused harmony exports getVersionFromToolcachePath, extractJdkFile, cacheJdkDir, getJavaVersionFromReleaseFile, getDownloadArchiveExtension, isVersionSatisfies, getToolcachePath, isGhes, getVersionFromFileContent, convertVersionToSemver, getArtifactFingerprint, getGitHubToken, getGitHubHttpHeaders, MAX_PAGINATION_PAGES, getNextPageUrlFromLinkHeader, validatePaginationUrl, renameWinArchive, getLatestMajorVersion */
+/* unused harmony exports getVersionFromToolcachePath, extractJdkFile, cacheJdkDir, getJavaVersionFromReleaseFile, getDownloadArchiveExtension, isVersionSatisfies, getToolcachePath, isGhes, getVersionFromFileContent, convertVersionToSemver, normalizeJavaVersionToSemver, getArtifactFingerprint, getGitHubToken, getGitHubHttpHeaders, MAX_PAGINATION_PAGES, getNextPageUrlFromLinkHeader, validatePaginationUrl, renameWinArchive, getLatestMajorVersion */
/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_0__ = __nccwpck_require__(857);
/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__nccwpck_require__.n(os__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __nccwpck_require__(6928);
@@ -31247,6 +31515,20 @@ function convertVersionToSemver(version) {
}
return mainVersion;
}
+/**
+ * Java versions (JEP 322) can contain more numeric fields than SemVer allows,
+ * e.g. '11.0.9.1' or Temurin respins such as '26.0.2.1+1'. Move the extra
+ * fields into SemVer build metadata ('11.0.9+1', '26.0.2+1.1'). Any other
+ * input (ranges, regular SemVer versions) is returned unchanged.
+ */
+function normalizeJavaVersionToSemver(version) {
+ const match = /^(\d+(?:\.\d+){3,})(?:\+([0-9A-Za-z.-]+))?$/.exec(version);
+ if (!match) {
+ return version;
+ }
+ const converted = convertVersionToSemver(match[1]);
+ return match[2] ? `${converted}.${match[2]}` : converted;
+}
/**
* Builds a validator for the bytes currently served by a URL from the response
* headers of a HEAD request. A vendor's `/latest/` URL never changes, so this
@@ -35832,13 +36114,16 @@ async function removeGpgHome(gpgHome) {
if (!external_fs_.existsSync(resolvedGpgHome)) {
return;
}
+ await stopGpgAgent(resolvedGpgHome);
+ await lib_io/* rmRF */.Yz(resolvedGpgHome);
+}
+async function stopGpgAgent(gpgHome) {
try {
- await lib_exec/* exec */.m('gpgconf', ['--homedir', toGpgPath(resolvedGpgHome), '--kill', 'gpg-agent'], { silent: true, ignoreReturnCode: true });
+ await lib_exec/* exec */.m('gpgconf', ['--homedir', toGpgPath(gpgHome), '--kill', 'gpg-agent'], { silent: true, ignoreReturnCode: true });
}
catch {
// gpgconf may be unavailable, but directory removal must still be attempted.
}
- await lib_io/* rmRF */.Yz(resolvedGpgHome);
}
async function verifyPackageSignature(archivePath, signatureUrl, publicKeyContent) {
const signaturePath = await tc.downloadTool(signatureUrl);
@@ -35884,6 +36169,7 @@ async function verifyPackageSignature(archivePath, signatureUrl, publicKeyConten
], options);
}
finally {
+ await stopGpgAgent(gpgHome);
await io.rmRF(signaturePath);
await io.rmRF(gpgHome);
}
diff --git a/dist/setup/220.index.js b/dist/setup/220.index.js
index f5cfebc79..d1ae361fb 100644
--- a/dist/setup/220.index.js
+++ b/dist/setup/220.index.js
@@ -263,13 +263,16 @@ async function removeGpgHome(gpgHome) {
if (!fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(resolvedGpgHome)) {
return;
}
+ await stopGpgAgent(resolvedGpgHome);
+ await _actions_io__WEBPACK_IMPORTED_MODULE_3__/* .rmRF */ .Yz(resolvedGpgHome);
+}
+async function stopGpgAgent(gpgHome) {
try {
- await _actions_exec__WEBPACK_IMPORTED_MODULE_4__/* .exec */ .m('gpgconf', ['--homedir', toGpgPath(resolvedGpgHome), '--kill', 'gpg-agent'], { silent: true, ignoreReturnCode: true });
+ await _actions_exec__WEBPACK_IMPORTED_MODULE_4__/* .exec */ .m('gpgconf', ['--homedir', toGpgPath(gpgHome), '--kill', 'gpg-agent'], { silent: true, ignoreReturnCode: true });
}
catch {
// gpgconf may be unavailable, but directory removal must still be attempted.
}
- await _actions_io__WEBPACK_IMPORTED_MODULE_3__/* .rmRF */ .Yz(resolvedGpgHome);
}
async function verifyPackageSignature(archivePath, signatureUrl, publicKeyContent) {
const signaturePath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_5__/* .downloadTool */ .bq(signatureUrl);
@@ -315,6 +318,7 @@ async function verifyPackageSignature(archivePath, signatureUrl, publicKeyConten
], options);
}
finally {
+ await stopGpgAgent(gpgHome);
await _actions_io__WEBPACK_IMPORTED_MODULE_3__/* .rmRF */ .Yz(signaturePath);
await _actions_io__WEBPACK_IMPORTED_MODULE_3__/* .rmRF */ .Yz(gpgHome);
}
diff --git a/dist/setup/242.index.js b/dist/setup/242.index.js
index 12e3d457d..1b0369a65 100644
--- a/dist/setup/242.index.js
+++ b/dist/setup/242.index.js
@@ -730,12 +730,9 @@ class JavaBase {
}
// Java uses a versioning scheme (JEP 322) that can contain more numeric
// fields than SemVer allows, e.g. '18.0.1.1' or '11.0.9.1'. Convert such
- // exact versions to SemVer build notation ('18.0.1+1') so they are
- // accepted. Ranges and versions that already carry build metadata are
- // left untouched.
- if (/^\d+(\.\d+){3,}$/.test(version)) {
- version = (0,util/* convertVersionToSemver */.ZY)(version);
- }
+ // exact versions to SemVer build notation ('18.0.1+1', or '26.0.2+1.1'
+ // for '26.0.2.1+1') so they are accepted. Ranges are left untouched.
+ version = (0,util/* normalizeJavaVersionToSemver */.zZ)(version);
if (!semver_default().validRange(version)) {
throw new Error(`The string '${version}' is not valid SemVer notation for a Java version. Please check README file for code snippets and more detailed information`);
}
diff --git a/dist/setup/463.index.js b/dist/setup/463.index.js
index 02b5bfc93..5267d4c81 100644
--- a/dist/setup/463.index.js
+++ b/dist/setup/463.index.js
@@ -109,7 +109,7 @@ class TemurinDistribution extends base_installer/* JavaBase */.O {
const formattedVersion = this.stable
? item.version_data.semver
: item.version_data.semver.replace('-beta+', '+');
- return {
+ const release = {
version: formattedVersion,
url: item.binaries[0].package.link,
signatureUrl: item.binaries[0].package.signature_link,
@@ -119,15 +119,29 @@ class TemurinDistribution extends base_installer/* JavaBase */.O {
source: item.binaries[0].package.checksum_link
}
};
+ return {
+ release,
+ openjdkVersion: getOpenJdkSemverVersion(item.version_data)
+ };
});
+ // The Adoptium API `semver` folds the JEP 322 patch field into the build
+ // number ('26.0.2.1+1' -> '26.0.2+101') and appends extra metadata for LTS
+ // releases ('25.0.4+7' -> '25.0.4+7.0.LTS'). Exact versions requested by
+ // users follow the OpenJDK notation instead, so also match them against a
+ // key derived from the OpenJDK version fields ('26.0.2+1.1', '25.0.4+7').
+ const isExactBuildRequest = (semver_default().parse(version)?.build.length ?? 0) > 0;
const satisfiedVersions = availableVersionsWithBinaries
- .filter(item => (0,util/* isVersionSatisfies */.y)(version, item.version))
+ .filter(({ release, openjdkVersion }) => (0,util/* isVersionSatisfies */.y)(version, release.version) ||
+ (isExactBuildRequest &&
+ openjdkVersion !== null &&
+ semver_default().compareBuild(version, openjdkVersion) === 0))
+ .map(({ release }) => release)
.sort((a, b) => {
return -semver_default().compareBuild(a.version, b.version);
});
const resolvedFullVersion = satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
if (!resolvedFullVersion) {
- const availableVersionStrings = availableVersionsWithBinaries.map(item => item.version);
+ const availableVersionStrings = availableVersionsWithBinaries.map(({ release }) => release.version);
throw this.createVersionNotFoundError(version, availableVersionStrings);
}
return resolvedFullVersion;
@@ -279,6 +293,20 @@ class TemurinDistribution extends base_installer/* JavaBase */.O {
return architecture === 'armv7' ? 'arm' : architecture;
}
}
+/**
+ * Builds a SemVer version from the OpenJDK version fields reported by the
+ * Adoptium API, e.g. '26.0.2.1+1' -> '26.0.2+1.1' and '25.0.4+7-LTS' ->
+ * '25.0.4+7'. Returns null if the fields cannot form a valid SemVer version.
+ */
+function getOpenJdkSemverVersion(versionData) {
+ const { major, minor, security, patch, build } = versionData;
+ if (build === undefined || build === null) {
+ return null;
+ }
+ const buildMetadata = patch ? `${patch}.${build}` : `${build}`;
+ const version = `${major}.${minor}.${security}+${buildMetadata}`;
+ return semver_default().valid(version) ? version : null;
+}
/***/ }),
@@ -375,13 +403,16 @@ async function removeGpgHome(gpgHome) {
if (!fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(resolvedGpgHome)) {
return;
}
+ await stopGpgAgent(resolvedGpgHome);
+ await _actions_io__WEBPACK_IMPORTED_MODULE_3__/* .rmRF */ .Yz(resolvedGpgHome);
+}
+async function stopGpgAgent(gpgHome) {
try {
- await _actions_exec__WEBPACK_IMPORTED_MODULE_4__/* .exec */ .m('gpgconf', ['--homedir', toGpgPath(resolvedGpgHome), '--kill', 'gpg-agent'], { silent: true, ignoreReturnCode: true });
+ await _actions_exec__WEBPACK_IMPORTED_MODULE_4__/* .exec */ .m('gpgconf', ['--homedir', toGpgPath(gpgHome), '--kill', 'gpg-agent'], { silent: true, ignoreReturnCode: true });
}
catch {
// gpgconf may be unavailable, but directory removal must still be attempted.
}
- await _actions_io__WEBPACK_IMPORTED_MODULE_3__/* .rmRF */ .Yz(resolvedGpgHome);
}
async function verifyPackageSignature(archivePath, signatureUrl, publicKeyContent) {
const signaturePath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_5__/* .downloadTool */ .bq(signatureUrl);
@@ -427,6 +458,7 @@ async function verifyPackageSignature(archivePath, signatureUrl, publicKeyConten
], options);
}
finally {
+ await stopGpgAgent(gpgHome);
await _actions_io__WEBPACK_IMPORTED_MODULE_3__/* .rmRF */ .Yz(signaturePath);
await _actions_io__WEBPACK_IMPORTED_MODULE_3__/* .rmRF */ .Yz(gpgHome);
}
diff --git a/dist/setup/63.index.js b/dist/setup/63.index.js
index b441e4523..3b8ac9758 100644
--- a/dist/setup/63.index.js
+++ b/dist/setup/63.index.js
@@ -128,7 +128,8 @@ class LibericaDistributions extends _base_installer_js__WEBPACK_IMPORTED_MODULE_
}
}
convertVersionToSemver(version) {
- const { buildVersion, featureVersion, interimVersion, updateVersion } = version;
+ const { featureVersion, interimVersion, updateVersion } = version;
+ const buildVersion = version.version.split('+')[1] || version.buildVersion;
const mainVersion = [featureVersion, interimVersion, updateVersion].join('.');
if (buildVersion != 0) {
return `${mainVersion}+${buildVersion}`;
diff --git a/dist/setup/81.index.js b/dist/setup/81.index.js
index 3ac82d8fc..39f98e377 100644
--- a/dist/setup/81.index.js
+++ b/dist/setup/81.index.js
@@ -7,6 +7,7 @@ export const modules = {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */ addMavenServerRepositoryOrigins: () => (/* binding */ addMavenServerRepositoryOrigins),
/* harmony export */ configureAuthentication: () => (/* binding */ configureAuthentication),
/* harmony export */ createAuthenticationSettings: () => (/* binding */ createAuthenticationSettings),
/* harmony export */ generate: () => (/* binding */ generate),
@@ -37,6 +38,7 @@ __webpack_require__.r(__webpack_exports__);
+const MAVEN_REPOSITORY_ORIGIN = /^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^/?#@]+\/?$/;
async function configureAuthentication() {
const servers = getMavenServerSettings();
const repositorySettings = getMavenRepositorySettings();
@@ -74,16 +76,16 @@ function getInputWithDeprecatedAlias(inputName, deprecatedInputName, defaultValu
// only exported for testing purposes
function getMavenServerSettings() {
const entries = _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getMultilineInput */ .q3(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_SERVER_CREDENTIALS */ .MM);
- if (entries.some(entry => entry.trim())) {
- return parseMavenServerCredentials(entries);
- }
- return [
- {
- id: _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getInput */ .V4(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_ID */ .fd),
- usernameEnvVar: getInputWithDeprecatedAlias(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_USERNAME_ENV_VAR */ .sc, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_USERNAME_DEPRECATED */ .sp, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_DEFAULT_SERVER_USERNAME */ .Wj),
- passwordEnvVar: getInputWithDeprecatedAlias(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_PASSWORD_ENV_VAR */ .r4, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_PASSWORD_DEPRECATED */ .Vt, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_DEFAULT_SERVER_PASSWORD */ .xp)
- }
- ];
+ const servers = entries.some(entry => entry.trim())
+ ? parseMavenServerCredentials(entries)
+ : [
+ {
+ id: _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getInput */ .V4(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_ID */ .fd),
+ usernameEnvVar: getInputWithDeprecatedAlias(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_USERNAME_ENV_VAR */ .sc, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_USERNAME_DEPRECATED */ .sp, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_DEFAULT_SERVER_USERNAME */ .Wj),
+ passwordEnvVar: getInputWithDeprecatedAlias(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_PASSWORD_ENV_VAR */ .r4, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_PASSWORD_DEPRECATED */ .Vt, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_DEFAULT_SERVER_PASSWORD */ .xp)
+ }
+ ];
+ return addMavenServerRepositoryOrigins(servers, _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getMultilineInput */ .q3(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_SERVER_REPOSITORY_ORIGINS */ .Pt));
}
// only exported for testing purposes
function parseMavenServerCredentials(entries) {
@@ -110,20 +112,78 @@ function parseMavenServerCredentials(entries) {
return servers;
}
// only exported for testing purposes
+function addMavenServerRepositoryOrigins(servers, entries) {
+ const serverIds = new Set(servers.map(server => server.id));
+ const originsByServer = new Map();
+ entries.forEach((entry, index) => {
+ if (!entry.trim()) {
+ return;
+ }
+ const separator = entry.indexOf(':');
+ if (separator <= 0 || separator === entry.length - 1) {
+ throw new Error(`Invalid mvn-server-repository-origins entry at line ${index + 1}. Expected format: server-id:repository-origin`);
+ }
+ const id = entry.slice(0, separator).trim();
+ const value = entry.slice(separator + 1).trim();
+ if (!id || !value) {
+ throw new Error(`Invalid mvn-server-repository-origins entry at line ${index + 1}. Server ID and repository origin are required`);
+ }
+ if (!serverIds.has(id)) {
+ throw new Error(`Unknown server-id '${id}' in mvn-server-repository-origins at line ${index + 1}`);
+ }
+ let url;
+ try {
+ if (!MAVEN_REPOSITORY_ORIGIN.test(value)) {
+ throw new Error();
+ }
+ url = new URL(value);
+ }
+ catch {
+ throw new Error(`Invalid repository origin '${value}' in mvn-server-repository-origins at line ${index + 1}`);
+ }
+ if (!url.host ||
+ url.username ||
+ url.password ||
+ (url.pathname !== '' && url.pathname !== '/') ||
+ url.search ||
+ url.hash) {
+ throw new Error(`Invalid repository origin '${value}' in mvn-server-repository-origins at line ${index + 1}`);
+ }
+ const explicitPort = /:(\d+)\/?$/.exec(value)?.[1];
+ const port = explicitPort ? Number.parseInt(explicitPort, 10) : undefined;
+ const includePort = port !== undefined &&
+ !((url.protocol === 'http:' && port === 80) ||
+ (url.protocol === 'https:' && port === 443));
+ const origin = `${url.protocol}//${url.hostname}${includePort ? `:${port}` : ''}`;
+ const origins = originsByServer.get(id) || [];
+ if (!origins.includes(origin)) {
+ origins.push(origin);
+ originsByServer.set(id, origins);
+ }
+ });
+ return servers.map(server => {
+ const repositoryOrigins = originsByServer.get(server.id);
+ return repositoryOrigins ? { ...server, repositoryOrigins } : server;
+ });
+}
+// only exported for testing purposes
function getMavenRepositorySettings() {
const entries = _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getMultilineInput */ .q3(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_REPOSITORIES */ .W2);
- if (!entries.some(entry => entry.trim())) {
+ const pluginEntries = _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getMultilineInput */ .q3(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_PLUGIN_REPOSITORIES */ .gR);
+ if (!entries.some(entry => entry.trim()) &&
+ !pluginEntries.some(entry => entry.trim())) {
return undefined;
}
const includeCentral = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getBooleanInput */ .Vt)(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL */ .H5, true);
return {
repositories: parseMavenRepositories(entries, includeCentral),
+ pluginRepositories: parseMavenRepositories(pluginEntries, includeCentral, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_PLUGIN_REPOSITORIES */ .gR),
includeCentral,
prioritizeCentral: (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getBooleanInput */ .Vt)(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL */ .OT, true)
};
}
// only exported for testing purposes
-function parseMavenRepositories(entries, includeCentral) {
+function parseMavenRepositories(entries, includeCentral, inputName = _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_REPOSITORIES */ .W2) {
const repositories = [];
const repositoryIds = new Set();
entries.forEach((entry, index) => {
@@ -133,7 +193,7 @@ function parseMavenRepositories(entries, includeCentral) {
const firstSeparator = entry.indexOf(':');
const lastSeparator = entry.lastIndexOf(':');
if (firstSeparator <= 0 || lastSeparator <= firstSeparator) {
- throw new Error(`Invalid mvn-repositories entry at line ${index + 1}. Expected format: repository-id:repository-url:snapshots-enabled`);
+ throw new Error(`Invalid ${inputName} entry at line ${index + 1}. Expected format: repository-id:repository-url:snapshots-enabled`);
}
const id = entry.slice(0, firstSeparator).trim();
const url = entry.slice(firstSeparator + 1, lastSeparator).trim();
@@ -142,13 +202,13 @@ function parseMavenRepositories(entries, includeCentral) {
.trim()
.toLowerCase();
if (!id || !url || !snapshotsValue) {
- throw new Error(`Invalid mvn-repositories entry at line ${index + 1}. repository-id, repository URL, and snapshots-enabled are required`);
+ throw new Error(`Invalid ${inputName} entry at line ${index + 1}. repository-id, repository URL, and snapshots-enabled are required`);
}
if (snapshotsValue !== 'true' && snapshotsValue !== 'false') {
- throw new Error(`Invalid snapshots-enabled value '${snapshotsValue}' in mvn-repositories entry at line ${index + 1}. Expected true or false`);
+ throw new Error(`Invalid snapshots-enabled value '${snapshotsValue}' in ${inputName} entry at line ${index + 1}. Expected true or false`);
}
if (repositoryIds.has(id)) {
- throw new Error(`Duplicate repository-id '${id}' in mvn-repositories input`);
+ throw new Error(`Duplicate repository-id '${id}' in ${inputName} input`);
}
if (includeCentral && id === _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_ID */ .xg) {
throw new Error(`Repository-id '${_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_ID */ .xg}' is reserved when ${_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL */ .H5} is enabled`);
@@ -162,6 +222,37 @@ function parseMavenRepositories(entries, includeCentral) {
});
return repositories;
}
+function generateRepositorySection(customRepositories, settings, element) {
+ if (!customRepositories.length && settings.includeCentral) {
+ return [];
+ }
+ const centralRepository = {
+ id: _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_ID */ .xg,
+ url: _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_URL */ .jv,
+ snapshotsEnabled: false
+ };
+ const customCentralConfigured = customRepositories.some(repository => repository.id === _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_ID */ .xg);
+ const repositories = settings.includeCentral
+ ? settings.prioritizeCentral
+ ? [centralRepository, ...customRepositories]
+ : [...customRepositories, centralRepository]
+ : customCentralConfigured
+ ? customRepositories
+ : [...customRepositories, { ...centralRepository, releasesEnabled: false }];
+ const container = element === 'repository' ? 'repositories' : 'pluginRepositories';
+ const lines = [` <${container}>`];
+ for (const repository of repositories) {
+ lines.push(` <${element}>`, ` ${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(repository.id)}`, ` ${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(repository.url)}`, ...(repository.releasesEnabled === undefined
+ ? []
+ : [
+ ' ',
+ ` ${repository.releasesEnabled}`,
+ ' '
+ ]), ' ', ` ${repository.snapshotsEnabled}`, ' ', ` ${element}>`);
+ }
+ lines.push(` ${container}>`);
+ return lines;
+}
async function createAuthenticationSettings(servers, settingsDirectory, overwriteSettings, gpgPassphraseEnvVar = undefined, repositorySettings = undefined) {
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .info */ .pq(`Creating ${_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MVN_SETTINGS_FILE */ .vO} with server-id: ${servers.map(server => server.id).join(', ')}`);
// when an alternate m2 location is specified use only that location (no .m2 directory)
@@ -187,39 +278,21 @@ function generate(servers, gpgPassphraseEnvVar, repositorySettings) {
' '
];
for (const server of servers) {
- lines.push(' ', ` ${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(server.id)}`, ` ${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(`\${env.${server.usernameEnvVar}}`)}`, ` ${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(`\${env.${server.passwordEnvVar}}`)}`, ' ');
+ lines.push(' ', ` ${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(server.id)}`, ` ${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(`\${env.${server.usernameEnvVar}}`)}`, ` ${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(`\${env.${server.passwordEnvVar}}`)}`);
+ if (server.repositoryOrigins) {
+ lines.push(' ');
+ for (const origin of server.repositoryOrigins) {
+ lines.push(` ${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(origin)}`);
+ }
+ lines.push(' ');
+ }
+ lines.push(' ');
}
lines.push(' ');
if (repositorySettings || includeGpgPassphraseProfile) {
lines.push(' ');
if (repositorySettings) {
- const centralRepository = {
- id: _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_ID */ .xg,
- url: _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_URL */ .jv,
- snapshotsEnabled: false
- };
- const customCentralConfigured = repositorySettings.repositories.some(repository => repository.id === _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_ID */ .xg);
- const repositories = repositorySettings.includeCentral
- ? repositorySettings.prioritizeCentral
- ? [centralRepository, ...repositorySettings.repositories]
- : [...repositorySettings.repositories, centralRepository]
- : customCentralConfigured
- ? repositorySettings.repositories
- : [
- ...repositorySettings.repositories,
- { ...centralRepository, releasesEnabled: false }
- ];
- lines.push(' ', ` ${_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_REPOSITORIES_PROFILE_ID */ .hq}`, ' ');
- for (const repository of repositories) {
- lines.push(' ', ` ${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(repository.id)}`, ` ${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(repository.url)}`, ...(repository.releasesEnabled === undefined
- ? []
- : [
- ' ',
- ` ${repository.releasesEnabled}`,
- ' '
- ]), ' ', ` ${repository.snapshotsEnabled}`, ' ', ' ');
- }
- lines.push(' ', ' ');
+ lines.push(' ', ` ${_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_REPOSITORIES_PROFILE_ID */ .hq}`, ...generateRepositorySection(repositorySettings.repositories, repositorySettings, 'repository'), ...generateRepositorySection(repositorySettings.pluginRepositories ?? [], repositorySettings, 'pluginRepository'), ' ');
}
if (includeGpgPassphraseProfile) {
lines.push(' ', ` ${_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .GPG_PASSPHRASE_PROFILE_ID */ .K$}`, ' ', ` ${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(gpgPassphraseEnvVar)}`, ' ', ' ');
@@ -350,13 +423,16 @@ async function removeGpgHome(gpgHome) {
if (!fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(resolvedGpgHome)) {
return;
}
+ await stopGpgAgent(resolvedGpgHome);
+ await _actions_io__WEBPACK_IMPORTED_MODULE_3__/* .rmRF */ .Yz(resolvedGpgHome);
+}
+async function stopGpgAgent(gpgHome) {
try {
- await _actions_exec__WEBPACK_IMPORTED_MODULE_4__/* .exec */ .m('gpgconf', ['--homedir', toGpgPath(resolvedGpgHome), '--kill', 'gpg-agent'], { silent: true, ignoreReturnCode: true });
+ await _actions_exec__WEBPACK_IMPORTED_MODULE_4__/* .exec */ .m('gpgconf', ['--homedir', toGpgPath(gpgHome), '--kill', 'gpg-agent'], { silent: true, ignoreReturnCode: true });
}
catch {
// gpgconf may be unavailable, but directory removal must still be attempted.
}
- await _actions_io__WEBPACK_IMPORTED_MODULE_3__/* .rmRF */ .Yz(resolvedGpgHome);
}
async function verifyPackageSignature(archivePath, signatureUrl, publicKeyContent) {
const signaturePath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_5__/* .downloadTool */ .bq(signatureUrl);
@@ -402,6 +478,7 @@ async function verifyPackageSignature(archivePath, signatureUrl, publicKeyConten
], options);
}
finally {
+ await stopGpgAgent(gpgHome);
await _actions_io__WEBPACK_IMPORTED_MODULE_3__/* .rmRF */ .Yz(signaturePath);
await _actions_io__WEBPACK_IMPORTED_MODULE_3__/* .rmRF */ .Yz(gpgHome);
}
diff --git a/dist/setup/824.index.js b/dist/setup/824.index.js
index 8e59e5d18..05b97c697 100644
--- a/dist/setup/824.index.js
+++ b/dist/setup/824.index.js
@@ -418,9 +418,102 @@ function readAttributeStr(xmlData, i) {
}
/**
- * Select all the attributes whether valid or invalid.
+ * Walk `attrStr` once, left to right, splitting it into attribute tokens.
+ *
+ * This replaces a regex that used to do the same job
+ * (`(\s*)([^\s=]+)(\s*=)?(\s*(['"])(([\s\S])*?)\5)?`). That regex led with an
+ * optional whitespace group followed by a required "non-whitespace" group.
+ * On a long run of whitespace that never resolves into an attribute name
+ * (e.g. a tag with thousands of trailing spaces before `>`), the engine
+ * backtracks the whitespace group one character at a time before giving up
+ * and moving to the next starting position — one full backtrack per
+ * position, which is quadratic in the length of the run.
+ *
+ * A single forward-only scan can never backtrack, so it can't be made slow
+ * this way no matter how much whitespace the input contains — it's always
+ * proportional to the length of the string, once.
+ *
+ * Each returned token mirrors the shape the old regex match array had, so
+ * the validation logic below (which reads token[1]..token[6]) didn't need
+ * to change:
+ * token.startIndex - where this token begins in attrStr
+ * token[1] - leading whitespace before the name
+ * token[2] - the attribute name
+ * token[3] - whitespace + '=' if present, else undefined
+ * token[4] - marker (any defined value) if a quoted value was found
+ * token[5] - the quote character used ('"' or "'")
+ * token[6] - the value's text, without the surrounding quotes
+ *
+ * A malformed leading character (e.g. a stray '=' with no name before it)
+ * is simply skipped over, one character at a time — the same outcome the
+ * old regex produced by failing to match at that position and retrying at
+ * the next one.
*/
-const validAttrStrRegxp = new RegExp('(\\s*)([^\\s=]+)(\\s*=)?(\\s*([\'"])(([\\s\\S])*?)\\5)?', 'g');
+function scanAttributeTokens(attrStr) {
+ const tokens = [];
+ const len = attrStr.length;
+ let i = 0;
+
+ while (i < len) {
+ const tokenStart = i;
+
+ // Leading whitespace before the name.
+ while (i < len && isWhiteSpace(attrStr[i])) i++;
+ if (i >= len) break; // trailing whitespace only — nothing left to read
+
+ if (attrStr[i] === '=') {
+ // No name before this '=' — not a valid attribute start. Move past
+ // just this one character and try again from the next position.
+ i = tokenStart + 1;
+ continue;
+ }
+
+ const leadingWs = attrStr.slice(tokenStart, i);
+
+ // Attribute name — everything up to the next whitespace or '='.
+ const nameStart = i;
+ while (i < len && !isWhiteSpace(attrStr[i]) && attrStr[i] !== '=') i++;
+ const name = attrStr.slice(nameStart, i);
+
+ // Optional whitespace + '='.
+ let equalsGroup; // whitespace + '=' text, or undefined if absent
+ let j = i;
+ while (j < len && isWhiteSpace(attrStr[j])) j++;
+ if (j < len && attrStr[j] === '=') {
+ equalsGroup = attrStr.slice(i, j + 1);
+ i = j + 1;
+ }
+
+ // Optional whitespace + quoted value.
+ let quoteChar;
+ let value;
+ let k = i;
+ while (k < len && isWhiteSpace(attrStr[k])) k++;
+ if (k < len && (attrStr[k] === '"' || attrStr[k] === "'")) {
+ const valueStart = k + 1;
+ const closeIdx = attrStr.indexOf(attrStr[k], valueStart);
+ if (closeIdx !== -1) {
+ quoteChar = attrStr[k];
+ value = attrStr.slice(valueStart, closeIdx);
+ i = closeIdx + 1;
+ }
+ // No closing quote found anywhere in the rest of the string — leave
+ // quoteChar/value undefined, same as the old regex's group failing
+ // to match a backreference-less run.
+ }
+
+ const token = { startIndex: tokenStart };
+ token[1] = leadingWs;
+ token[2] = name;
+ token[3] = equalsGroup;
+ token[4] = quoteChar !== undefined ? true : undefined;
+ token[5] = quoteChar;
+ token[6] = value;
+ tokens.push(token);
+ }
+
+ return tokens;
+}
//attr, ="sd", a="amit's", a="sd"b="saf", ab cd=""
@@ -429,7 +522,7 @@ function validateAttributeString(attrStr, options) {
//if(attrStr.trim().length === 0) return true; //empty string
- const matches = (0,_util_js__WEBPACK_IMPORTED_MODULE_0__/* .getAllMatches */ .Xe)(attrStr, validAttrStrRegxp);
+ const matches = scanAttributeTokens(attrStr);
const attrNames = {};
for (let i = 0; i < matches.length; i++) {
@@ -532,7 +625,6 @@ function getPositionFromMatch(match) {
return match.startIndex + match[1].length;
}
-
/***/ }),
/***/ 6009:
diff --git a/dist/setup/971.index.js b/dist/setup/971.index.js
index f83b7ac85..3a70aef00 100644
--- a/dist/setup/971.index.js
+++ b/dist/setup/971.index.js
@@ -52431,6 +52431,24 @@ const EXPANSION_MAX = 100_000;
// realistic expansion (100k results hitting `EXPANSION_MAX` measure ~1M
// characters) so legitimate input is unaffected.
const EXPANSION_MAX_LENGTH = 4_000_000;
+// `expand_` recurses once per level of brace *nesting* - both when expanding a
+// set's comma members and when re-wrapping a set whose body is a single part.
+// The CVE-2026-14257 fix made the *tail* iterative (recursion on `m.post`, one
+// level per chained group), which left nesting depth unbounded: about 3,100
+// levels of `{{{...a,b...}}}` - only ~6KB of input - exhausted the native stack
+// and crashed the process. `EXPANSION_MAX_DEPTH` bounds how deep the parser
+// will follow nesting. It sits far above any realistic pattern and well below
+// the depth at which the stack runs out.
+const EXPANSION_MAX_DEPTH = 1_000;
+// Bash keeps a quirk where a brace group followed by a comma set still expands
+// (`{a},b}`). The parser implements it by rewriting the string and restarting
+// the scan, absorbing one `}` per pass. `n` trailing braces therefore cost `n`
+// full passes over a string that itself grows by one `escClose` sentinel each
+// time - quadratic in `n`, with a ~26x constant from the sentinel's length.
+// 128KB of `'{a}' + '}'.repeat(n) + ',z}'` blocked the event loop for 27
+// seconds to produce two results. `EXPANSION_MAX_REWRITES` bounds how many
+// times the scan may restart. Real `{a},b}` input needs a handful.
+const EXPANSION_MAX_REWRITES = 1_000;
function numeric(str) {
return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
}
@@ -52450,37 +52468,52 @@ function unescapeBraces(str) {
.replace(escCommaPattern, ',')
.replace(escPeriodPattern, '.');
}
+// Like `target.push(...items)` but doesn't overflow the stack
+function pushAll(target, items) {
+ for (let i = 0; i < items.length; i++) {
+ target.push(items[i]);
+ }
+}
/**
* Basically just str.split(","), but handling cases
* where we have nested braced sections, which should be
* treated as individual members, like {a,{b,c},d}
*/
function parseCommaParts(str) {
- if (!str) {
- return [''];
- }
const parts = [];
- const m = balanced('{', '}', str);
- if (!m) {
- return str.split(',');
- }
- const { pre, body, post } = m;
- const p = pre.split(',');
- p[p.length - 1] += '{' + body + '}';
- const postParts = parseCommaParts(post);
- if (post.length) {
- ;
- p[p.length - 1] += postParts.shift();
- p.push.apply(p, postParts);
- }
- parts.push.apply(parts, p);
- return parts;
+ // Walk the brace groups iteratively. Recursing on `post` once per group let a
+ // chain of them exhaust the stack - the parsing-side counterpart to
+ // the `expand_` overflow fixed for CVE-2026-14257, and not something `max` or
+ // `maxLength` can bound, since it happens before expansion.
+ //
+ // The part the next chunk continues
+ let carry = '';
+ for (;;) {
+ const m = balanced('{', '}', str);
+ if (!m) {
+ const tail = str.split(',');
+ tail[0] = carry + tail[0];
+ pushAll(parts, tail);
+ return parts;
+ }
+ const { pre, body, post } = m;
+ const p = pre.split(',');
+ p[0] = carry + p[0];
+ p[p.length - 1] += '{' + body + '}';
+ if (!post.length) {
+ pushAll(parts, p);
+ return parts;
+ }
+ carry = p.pop();
+ pushAll(parts, p);
+ str = post;
+ }
}
function expand(str, options = {}) {
if (!str) {
return [];
}
- const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH } = options;
+ const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH, maxDepth = EXPANSION_MAX_DEPTH, maxRewrites = EXPANSION_MAX_REWRITES, } = options;
// I don't know why Bash 4.3 does this, but it does.
// Anything starting with {} will have the first two bytes preserved
// but *only* at the top level, so {},a}b will not expand to anything,
@@ -52490,7 +52523,7 @@ function expand(str, options = {}) {
if (str.slice(0, 2) === '{}') {
str = '\\{\\}' + str.slice(2);
}
- return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
+ return expand_(escapeBraces(str), max, maxLength, maxDepth, 0, maxRewrites, true).map(unescapeBraces);
}
function embrace(str) {
return '{' + str + '}';
@@ -52585,7 +52618,13 @@ function expandSequence(body, isAlphaSequence, max, maxLength) {
}
return N;
}
-function expand_(str, max, maxLength, isTop) {
+function expand_(str, max, maxLength, maxDepth, depth, maxRewrites, isTop) {
+ // Too deeply nested to keep following: treat the rest as literal, the same
+ // way a group that cannot expand is already handled. Truncating rather than
+ // throwing keeps `expand` total, matching `max` and `maxLength`.
+ if (depth > maxDepth) {
+ return [str];
+ }
// Consume the string's top-level brace groups left to right, threading a
// running set of combined prefixes (`acc`). Expanding the tail iteratively -
// rather than recursing on `m.post` once per group - keeps the native stack
@@ -52597,6 +52636,9 @@ function expand_(str, max, maxLength, isTop) {
// comma set - a sequence like `{a..\}` may legitimately yield ''. The drop
// is on the final strings, so it is applied to whichever `combine` produces
// them (the one with no brace set left in the tail).
+ // How many times the `{a},b}` rewrite below has restarted the scan. Each pass
+ // re-reads the whole string, so leaving this unbounded is quadratic.
+ let rewrites = 0;
let dropEmpties = false;
let firstGroup = true;
for (;;) {
@@ -52621,7 +52663,8 @@ function expand_(str, max, maxLength, isTop) {
const isOptions = m.body.indexOf(',') >= 0;
if (!isSequence && !isOptions) {
// {a},b}
- if (m.post.match(/,(?!,).*\}/)) {
+ if (rewrites < maxRewrites && m.post.match(/,(?!,).*\}/)) {
+ rewrites++;
str = m.pre + '{' + m.body + escClose + m.post;
isTop = true;
continue;
@@ -52641,7 +52684,7 @@ function expand_(str, max, maxLength, isTop) {
let n = parseCommaParts(m.body);
if (n.length === 1 && n[0] !== undefined) {
// x{{a,b}}y ==> x{a}y x{b}y
- n = expand_(n[0], max, maxLength, false).map(embrace);
+ n = expand_(n[0], max, maxLength, maxDepth, depth + 1, maxRewrites, false).map(embrace);
//XXX is this necessary? Can't seem to hit it in tests.
/* c8 ignore start */
if (n.length === 1) {
@@ -52667,12 +52710,13 @@ function expand_(str, max, maxLength, isTop) {
values = [];
let valuesLength = 0;
outer: for (let j = 0; j < n.length; j++) {
- const expanded = expand_(n[j], max, maxLength, false);
+ const expanded = expand_(n[j], max, maxLength, maxDepth, depth + 1, maxRewrites, false);
for (let k = 0; k < expanded.length; k++) {
const v = expanded[k];
if (dropsEmpties && !v)
continue;
- if (values.length >= max || valuesLength + v.length > maxLength) {
+ if (values.length >= max ||
+ valuesLength + v.length > maxLength) {
break outer;
}
values.push(v);
diff --git a/dist/setup/978.index.js b/dist/setup/978.index.js
index 23b363d34..fe57a00e2 100644
--- a/dist/setup/978.index.js
+++ b/dist/setup/978.index.js
@@ -13,19 +13,26 @@ export const modules = {
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9896);
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_2__);
-/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2088);
-/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_3__);
-/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6242);
-/* harmony import */ var _platform_types_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(7444);
-/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(4527);
+/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6242);
+/* harmony import */ var _platform_types_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7444);
+/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4527);
-
-class ZuluDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/* .JavaBase */ .O {
+function compareNumberArrays(a, b) {
+ const length = Math.max(a.length, b.length);
+ for (let i = 0; i < length; i++) {
+ const diff = (a[i] ?? 0) - (b[i] ?? 0);
+ if (diff !== 0) {
+ return diff;
+ }
+ }
+ return 0;
+}
+class ZuluDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaBase */ .O {
constructor(installerOptions) {
super('Zulu', installerOptions);
}
@@ -39,19 +46,24 @@ class ZuluDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/*
? [...item.java_version, item.openjdk_build_number]
: item.java_version;
return {
- version: (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .convertVersionToSemver */ .ZY)(javaVersion),
+ version: (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .convertVersionToSemver */ .ZY)(javaVersion),
url: item.download_url,
- zuluVersion: (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .convertVersionToSemver */ .ZY)(item.distro_version),
+ javaVersion: item.java_version,
+ buildNumber: item.openjdk_build_number ?? 0,
+ distroVersion: item.distro_version,
packageUuid: item.package_uuid
};
});
const satisfiedVersions = availableVersions
- .filter(item => (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .isVersionSatisfies */ .y)(version, item.version))
+ .filter(item => (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .isVersionSatisfies */ .y)(version, item.version))
.sort((a, b) => {
- // Azul provides two versions: java_version and distro_version
- // we should sort by both fields by descending
- return (-semver__WEBPACK_IMPORTED_MODULE_3___default().compareBuild(a.version, b.version) ||
- -semver__WEBPACK_IMPORTED_MODULE_3___default().compareBuild(a.zuluVersion, b.zuluVersion));
+ // Compare numerically rather than via semver build metadata: Azul
+ // hotfix releases carry a 4th java_version segment (e.g. 25.0.4.1+1,
+ // rendered as '25.0.4+1.1') that must rank above 25.0.4+7, whereas
+ // semver.compareBuild would order the build identifiers '7' > '1'.
+ return (-compareNumberArrays(a.javaVersion, b.javaVersion) ||
+ b.buildNumber - a.buildNumber ||
+ -compareNumberArrays(a.distroVersion, b.distroVersion));
})
.map((item) => ({
version: item.version,
@@ -85,21 +97,21 @@ class ZuluDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/*
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Downloading Java ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...`);
let javaArchivePath = await this.downloadAndVerify(javaRelease);
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Extracting Java archive...`);
- const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getDownloadArchiveExtension */ .ag)();
+ const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getDownloadArchiveExtension */ .ag)();
if (process.platform === 'win32') {
- javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .renameWinArchive */ .n2)(javaArchivePath);
+ javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .renameWinArchive */ .n2)(javaArchivePath);
}
- const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
+ const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
const archiveName = fs__WEBPACK_IMPORTED_MODULE_2___default().readdirSync(extractedJavaPath)[0];
const archivePath = path__WEBPACK_IMPORTED_MODULE_1___default().join(extractedJavaPath, archiveName);
- const javaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .cacheJdkDir */ .Vj)(archivePath, this.toolcacheFolderName, this.getToolcacheVersionName(javaRelease.version), this.architecture);
+ const javaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .cacheJdkDir */ .Vj)(archivePath, this.toolcacheFolderName, this.getToolcacheVersionName(javaRelease.version), this.architecture);
return { version: javaRelease.version, path: javaPath };
}
async getAvailableVersions() {
const arch = this.getArchitectureOptions();
const [bundleType, features] = this.packageType.split('+');
const platform = this.getPlatformOption();
- const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getDownloadArchiveExtension */ .ag)();
+ const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getDownloadArchiveExtension */ .ag)();
const javafx = features?.includes('fx') ?? false;
const crac = features?.includes('crac') ?? false;
const releaseStatus = this.stable ? 'ga' : 'ea';
@@ -185,7 +197,7 @@ class ZuluDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/*
// The new Metadata API's "linux" value returns both glibc and musl
// packages, so target the libc the runner actually has. A glibc JDK
// cannot run on Alpine.
- return (0,_platform_types_js__WEBPACK_IMPORTED_MODULE_5__/* .isAlpineLinux */ .G6)() ? 'linux_musl' : 'linux_glibc';
+ return (0,_platform_types_js__WEBPACK_IMPORTED_MODULE_4__/* .isAlpineLinux */ .G6)() ? 'linux_musl' : 'linux_glibc';
default:
return process.platform;
}
diff --git a/dist/setup/index.js b/dist/setup/index.js
index 8e019a02a..5c0536646 100644
--- a/dist/setup/index.js
+++ b/dist/setup/index.js
@@ -6009,11 +6009,77 @@ class Request {
}
}
- onUpgrade (statusCode, headers, socket) {
+ /**
+ * @param {number|null} statusCode
+ * @param {Buffer[]|null} headers
+ * @param {import('node:stream').Duplex} socket
+ * @param {string} [statusText]
+ */
+ onUpgrade (statusCode, headers, socket, statusText = '') {
+ this.onFinally()
+
assert(!this.aborted)
assert(!this.completed)
- return this[kHandler].onUpgrade(statusCode, headers, socket)
+ if (statusCode !== null) {
+ this.#publishUpgradeHeaders(statusCode, headers, statusText)
+ }
+
+ const result = this[kHandler].onUpgrade(statusCode, headers, socket)
+
+ if (!this.aborted) {
+ this.completed = true
+ if (statusCode !== null) {
+ this.#publishUpgradeTrailers()
+ }
+ }
+
+ return result
+ }
+
+ /**
+ * @param {number} statusCode
+ * @param {import('node:http2').IncomingHttpHeaders} headers
+ * @param {(headers: import('node:http2').IncomingHttpHeaders) => Buffer[]} parseHeaders
+ * @param {string} [statusText]
+ */
+ onUpgradeResponse (statusCode, headers, parseHeaders, statusText = '') {
+ assert(!this.aborted)
+ assert(this.completed)
+
+ if (channels.headers.hasSubscribers) {
+ this.#publishUpgradeHeaders(statusCode, parseHeaders(headers), statusText)
+ }
+ this.#publishUpgradeTrailers()
+ }
+
+ /**
+ * @param {Error} error
+ */
+ onUpgradeError (error) {
+ assert(!this.aborted)
+ assert(this.completed)
+
+ if (channels.error.hasSubscribers) {
+ channels.error.publish({ request: this, error })
+ }
+ }
+
+ /**
+ * @param {number} statusCode
+ * @param {Buffer[]} headers
+ * @param {string} statusText
+ */
+ #publishUpgradeHeaders (statusCode, headers, statusText) {
+ if (channels.headers.hasSubscribers) {
+ channels.headers.publish({ request: this, response: { statusCode, headers, statusText } })
+ }
+ }
+
+ #publishUpgradeTrailers () {
+ if (channels.trailers.hasSubscribers) {
+ channels.trailers.publish({ request: this, trailers: [] })
+ }
}
onComplete (trailers) {
@@ -7912,7 +7978,7 @@ class Parser {
}
onUpgrade (head) {
- const { upgrade, client, socket, headers, statusCode } = this
+ const { upgrade, client, socket, headers, statusCode, statusText } = this
assert(upgrade)
assert(client[kSocket] === socket)
@@ -7947,9 +8013,10 @@ class Parser {
client.emit('disconnect', client[kUrl], [client], new InformationalError('upgrade'))
try {
- request.onUpgrade(statusCode, headers, socket)
- } catch (err) {
- util.destroy(socket, err)
+ request.onUpgrade(statusCode, headers, socket, statusText)
+ } catch (error) {
+ util.errorRequest(client, request, error)
+ util.destroy(socket, error)
}
client[kResume]()
@@ -8356,7 +8423,7 @@ async function connectH1 (client, socket) {
function clearIdleSocketValidation (socket) {
if (socket[kIdleSocketValidationTimeout]) {
- clearTimeout(socket[kIdleSocketValidationTimeout])
+ clearImmediate(socket[kIdleSocketValidationTimeout])
socket[kIdleSocketValidationTimeout] = null
}
@@ -8365,15 +8432,23 @@ function clearIdleSocketValidation (socket) {
function scheduleIdleSocketValidation (client, socket) {
socket[kIdleSocketValidation] = 1
- socket[kIdleSocketValidationTimeout] = setTimeout(() => {
+ // Yield to the check phase (after poll) so unsolicited bytes / FIN / RST
+ // already pending on this idle keep-alive socket are processed before the
+ // next request is written (GHSA-35p6-xmwp-9g52).
+ //
+ // setTimeout(0) pays Node's ~1ms timer floor on every sequential reuse
+ // (#5493). setImmediate avoids that, but an *unref'd* Immediate lets poll
+ // block for ~500ms when the event loop is otherwise idle (#5600 / #5606).
+ // A ref'd Immediate both keeps the pending request alive and makes poll
+ // return immediately — the hybrid those issues asked for.
+ socket[kIdleSocketValidationTimeout] = setImmediate(() => {
socket[kIdleSocketValidationTimeout] = null
socket[kIdleSocketValidation] = 2
if (client[kSocket] === socket && !socket.destroyed) {
client[kResume]()
}
- }, 0)
- socket[kIdleSocketValidationTimeout].unref?.()
+ })
}
/**
@@ -8522,12 +8597,22 @@ function writeH1 (client, request) {
const socket = client[kSocket]
clearIdleSocketValidation(socket)
- const abort = (err) => {
- if (request.aborted || request.completed) {
+ /**
+ * @param {Error} [error]
+ */
+ const abort = (error) => {
+ if (request.aborted) {
+ return
+ }
+
+ if (request.completed) {
+ if (request.upgrade || request.method === 'CONNECT') {
+ util.destroy(socket, new InformationalError('aborted'))
+ }
return
}
- util.errorRequest(client, request, err || new RequestAbortedError())
+ util.errorRequest(client, request, error || new RequestAbortedError())
util.destroy(body)
util.destroy(socket, new InformationalError('aborted'))
@@ -8984,6 +9069,7 @@ module.exports = connectH1
const assert = __nccwpck_require__(4589)
+const { errorMonitor } = __nccwpck_require__(8474)
const { pipeline } = __nccwpck_require__(7075)
const util = __nccwpck_require__(3440)
const {
@@ -9060,6 +9146,15 @@ function parseH2Headers (headers) {
return result
}
+/**
+ * @param {import('node:http2').IncomingHttpHeaders} headers
+ * @returns {Buffer[]}
+ */
+function parseH2ResponseHeaders (headers) {
+ const { [HTTP2_HEADER_STATUS]: _statusCode, ...realHeaders } = headers
+ return parseH2Headers(realHeaders)
+}
+
async function connectH2 (client, socket) {
client[kSocket] = socket
@@ -9280,22 +9375,32 @@ function writeH2 (client, request) {
headers[HTTP2_HEADER_AUTHORITY] = host || `${hostname}${port ? `:${port}` : ''}`
headers[HTTP2_HEADER_METHOD] = method
- const abort = (err) => {
- if (request.aborted || request.completed) {
+ /**
+ * @param {Error} [error]
+ */
+ const abort = (error) => {
+ if (request.aborted) {
+ return
+ }
+
+ if (request.completed) {
+ if (method === 'CONNECT' && stream != null) {
+ util.destroy(stream, error || new RequestAbortedError())
+ }
return
}
- err = err || new RequestAbortedError()
+ error = error || new RequestAbortedError()
- util.errorRequest(client, request, err)
+ util.errorRequest(client, request, error)
if (stream != null) {
- util.destroy(stream, err)
+ util.destroy(stream, error)
}
// We do not destroy the socket as we can continue using the session
// the stream get's destroyed and the session remains to create new streams
- util.destroy(body, err)
+ util.destroy(body, error)
client[kQueue][client[kRunningIdx]++] = null
client[kResume]()
}
@@ -9314,25 +9419,57 @@ function writeH2 (client, request) {
if (method === 'CONNECT') {
session.ref()
- // We are already connected, streams are pending, first request
- // will create a new stream. We trigger a request to create the stream and wait until
- // `ready` event is triggered
// We disabled endStream to allow the user to write to the stream
stream = session.request(headers, { endStream: false, signal })
+ let upgradeResponseFinished = false
- if (stream.id && !stream.pending) {
- request.onUpgrade(null, null, stream)
- ++session[kOpenStreams]
- client[kQueue][client[kRunningIdx]++] = null
- } else {
- stream.once('ready', () => {
+ /**
+ * @param {import('node:http2').IncomingHttpHeaders} headers
+ */
+ const onResponse = (headers) => {
+ upgradeResponseFinished = true
+ stream.off(errorMonitor, onUpgradeError)
+ request.onUpgradeResponse(Number(headers[HTTP2_HEADER_STATUS]), headers, parseH2ResponseHeaders)
+ }
+
+ /**
+ * @param {Error} error
+ */
+ const onUpgradeError = (error) => {
+ upgradeResponseFinished = true
+ stream.off('response', onResponse)
+ request.onUpgradeError(error)
+ }
+
+ const onReady = () => {
+ try {
request.onUpgrade(null, null, stream)
- ++session[kOpenStreams]
- client[kQueue][client[kRunningIdx]++] = null
- })
+ } catch (error) {
+ stream.off('response', onResponse)
+ abort(error)
+ return
+ }
+
+ if (request.aborted) {
+ return
+ }
+
+ stream.off('error', abort)
+ stream.once(errorMonitor, onUpgradeError)
+ client[kQueue][client[kRunningIdx]++] = null
}
+ stream.once('response', onResponse)
+ stream.once('error', abort)
+ ++session[kOpenStreams]
+ onReady()
+
stream.once('close', () => {
+ if (!upgradeResponseFinished && request.completed) {
+ stream.off('response', onResponse)
+ stream.off(errorMonitor, onUpgradeError)
+ request.onUpgradeError(new InformationalError(`HTTP/2: "stream error" received - code ${stream.rstCode}`))
+ }
session[kOpenStreams] -= 1
if (session[kOpenStreams] === 0) session.unref()
})
@@ -12031,6 +12168,7 @@ class RetryHandler {
this.end = null
this.etag = null
this.resume = null
+ this.headersSent = false
// Handle possible onConnect duplication
this.handler.onConnect(reason => {
@@ -12043,6 +12181,20 @@ class RetryHandler {
})
}
+ checkpointResponseEnd (headers, resume) {
+ if (this.end == null && this.opts.method !== 'HEAD') {
+ const contentLength = headers['content-length']
+ this.end = contentLength != null ? Number(contentLength) - 1 : null
+
+ assert(
+ this.end == null || Number.isFinite(this.end),
+ 'invalid content-length'
+ )
+ }
+
+ this.resume = this.end != null ? resume : null
+ }
+
onRequestSent () {
if (this.handler.onRequestSent) {
this.handler.onRequestSent()
@@ -12131,7 +12283,12 @@ class RetryHandler {
this.retryCount += 1
if (statusCode >= 300) {
- if (this.retryOpts.statusCodes.includes(statusCode) === false) {
+ // Only expose a response if no earlier attempt has reached the caller.
+ // Otherwise abort this attempt so the error settles the existing body
+ // instead of replacing it with a new response.
+ if (!this.headersSent && this.retryOpts.statusCodes.includes(statusCode) === false) {
+ this.headersSent = true
+ this.checkpointResponseEnd(headers, resume)
return this.handler.onHeaders(
statusCode,
rawHeaders,
@@ -12200,8 +12357,15 @@ class RetryHandler {
const { start, size, end = size - 1 } = contentRange
- assert(this.start === start, 'content-range mismatch')
- assert(this.end == null || this.end === end, 'content-range mismatch')
+ if (this.start !== start || (this.end != null && this.end !== end)) {
+ this.abort(
+ new RequestRetryError('Content-Range mismatch', statusCode, {
+ headers,
+ data: { count: this.retryCount }
+ })
+ )
+ return false
+ }
this.resume = resume
return true
@@ -12213,6 +12377,7 @@ class RetryHandler {
const range = parseRangeHeader(headers['content-range'])
if (range == null) {
+ this.headersSent = true
return this.handler.onHeaders(
statusCode,
rawHeaders,
@@ -12251,6 +12416,7 @@ class RetryHandler {
)
this.resume = resume
+ this.headersSent = true
this.etag = headers.etag != null ? headers.etag : null
// Weak etags are not useful for comparison nor cache
@@ -12290,7 +12456,7 @@ class RetryHandler {
}
onError (err) {
- if (this.aborted || isDisturbed(this.opts.body)) {
+ if (this.aborted || isDisturbed(this.opts.body) || (this.headersSent && this.resume == null)) {
return this.handler.onError(err)
}
@@ -16748,6 +16914,49 @@ const COLON = 0x3A
*/
const SPACE = 0x20
+const DATA = Buffer.from('data')
+const EVENT = Buffer.from('event')
+const ID = Buffer.from('id')
+const RETRY = Buffer.from('retry')
+
+function isASCIINumberBytes (buffer, start) {
+ if (start >= buffer.length) {
+ return false
+ }
+
+ for (let i = start; i < buffer.length; i++) {
+ if (buffer[i] < 0x30 || buffer[i] > 0x39) {
+ return false
+ }
+ }
+
+ return true
+}
+
+function isValidLastEventIdBytes (buffer, start) {
+ for (let i = start; i < buffer.length; i++) {
+ if (buffer[i] === 0x00) {
+ return false
+ }
+ }
+
+ return true
+}
+
+function isFieldName (line, length, field) {
+ if (length !== field.length) {
+ return false
+ }
+
+ for (let i = 0; i < length; i++) {
+ if (line[i] !== field[i]) {
+ return false
+ }
+ }
+
+ return true
+}
+
/**
* @typedef {object} EventSourceStreamEvent
* @type {object}
@@ -16788,11 +16997,14 @@ class EventSourceStream extends Transform {
eventEndCheck = false
/**
- * @type {Buffer}
+ * @type {Buffer[]}
*/
- buffer = null
+ chunks = []
+ chunkIndex = 0
pos = 0
+ lineChunkIndex = 0
+ linePos = 0
event = {
data: undefined,
@@ -16831,92 +17043,20 @@ class EventSourceStream extends Transform {
return
}
- // Cache the chunk in the buffer, as the data might not be complete while
- // processing it
- // TODO: Investigate if there is a more performant way to handle
- // incoming chunks
- // see: https://github.com/nodejs/undici/issues/2630
- if (this.buffer) {
- this.buffer = Buffer.concat([this.buffer, chunk])
- } else {
- this.buffer = chunk
- }
+ this.chunks.push(chunk)
// Strip leading byte-order-mark if we opened the stream and started
// the processing of the incoming data
if (this.checkBOM) {
- switch (this.buffer.length) {
- case 1:
- // Check if the first byte is the same as the first byte of the BOM
- if (this.buffer[0] === BOM[0]) {
- // If it is, we need to wait for more data
- callback()
- return
- }
- // Set the checkBOM flag to false as we don't need to check for the
- // BOM anymore
- this.checkBOM = false
-
- // The buffer only contains one byte so we need to wait for more data
- callback()
- return
- case 2:
- // Check if the first two bytes are the same as the first two bytes
- // of the BOM
- if (
- this.buffer[0] === BOM[0] &&
- this.buffer[1] === BOM[1]
- ) {
- // If it is, we need to wait for more data, because the third byte
- // is needed to determine if it is the BOM or not
- callback()
- return
- }
-
- // Set the checkBOM flag to false as we don't need to check for the
- // BOM anymore
- this.checkBOM = false
- break
- case 3:
- // Check if the first three bytes are the same as the first three
- // bytes of the BOM
- if (
- this.buffer[0] === BOM[0] &&
- this.buffer[1] === BOM[1] &&
- this.buffer[2] === BOM[2]
- ) {
- // If it is, we can drop the buffered data, as it is only the BOM
- this.buffer = Buffer.alloc(0)
- // Set the checkBOM flag to false as we don't need to check for the
- // BOM anymore
- this.checkBOM = false
-
- // Await more data
- callback()
- return
- }
- // If it is not the BOM, we can start processing the data
- this.checkBOM = false
- break
- default:
- // The buffer is longer than 3 bytes, so we can drop the BOM if it is
- // present
- if (
- this.buffer[0] === BOM[0] &&
- this.buffer[1] === BOM[1] &&
- this.buffer[2] === BOM[2]
- ) {
- // Remove the BOM from the buffer
- this.buffer = this.buffer.subarray(3)
- }
-
- // Set the checkBOM flag to false as we don't need to check for the
- this.checkBOM = false
- break
+ if (this.handleBOM()) {
+ callback()
+ return
}
}
- while (this.pos < this.buffer.length) {
+ while (this.hasCurrentByte()) {
+ const byte = this.currentByte()
+
// If the previous line ended with an end-of-line, we need to check
// if the next character is also an end-of-line.
if (this.eventEndCheck) {
@@ -16929,10 +17069,9 @@ class EventSourceStream extends Transform {
if (this.crlfCheck) {
// If the current character is a line feed, we can remove it
// from the buffer and reset the crlfCheck flag
- if (this.buffer[this.pos] === LF) {
- this.buffer = this.buffer.subarray(this.pos + 1)
- this.pos = 0
+ if (byte === LF) {
this.crlfCheck = false
+ this.consumeCurrentByte()
// It is possible that the line feed is not the end of the
// event. We need to check if the next character is an
@@ -16948,19 +17087,17 @@ class EventSourceStream extends Transform {
this.crlfCheck = false
}
- if (this.buffer[this.pos] === LF || this.buffer[this.pos] === CR) {
+ if (byte === LF || byte === CR) {
// If the current character is a carriage return, we need to
// set the crlfCheck flag to true, as we need to check if the
// next character is a line feed so we can remove it from the
// buffer
- if (this.buffer[this.pos] === CR) {
+ if (byte === CR) {
this.crlfCheck = true
}
- this.buffer = this.buffer.subarray(this.pos + 1)
- this.pos = 0
- if (
- this.event.data !== undefined || this.event.event || this.event.id || this.event.retry) {
+ this.consumeCurrentByte()
+ if (this.hasPendingEvent()) {
this.processEvent(this.event)
}
this.clearEvent()
@@ -16974,22 +17111,18 @@ class EventSourceStream extends Transform {
// If the current character is an end-of-line, we can process the
// line
- if (this.buffer[this.pos] === LF || this.buffer[this.pos] === CR) {
+ if (byte === LF || byte === CR) {
// If the current character is a carriage return, we need to
// set the crlfCheck flag to true, as we need to check if the
// next character is a line feed
- if (this.buffer[this.pos] === CR) {
+ if (byte === CR) {
this.crlfCheck = true
}
// In any case, we can process the line as we reached an
// end-of-line character
- this.parseLine(this.buffer.subarray(0, this.pos), this.event)
-
- // Remove the processed line from the buffer
- this.buffer = this.buffer.subarray(this.pos + 1)
- // Reset the position as we removed the processed line from the buffer
- this.pos = 0
+ this.parseLine(this.readLine(), this.event)
+ this.consumeCurrentByte()
// A line was processed and this could be the end of the event. We need
// to check if the next line is empty to determine if the event is
// finished.
@@ -16997,7 +17130,7 @@ class EventSourceStream extends Transform {
continue
}
- this.pos++
+ this.advanceCursor()
}
callback()
@@ -17022,64 +17155,53 @@ class EventSourceStream extends Transform {
return
}
- let field = ''
- let value = ''
+ let fieldLength = line.length
+ let valueStart = line.length
// If the line contains a U+003A COLON character (:)
if (colonPosition !== -1) {
- // Collect the characters on the line before the first U+003A COLON
- // character (:), and let field be that string.
- // TODO: Investigate if there is a more performant way to extract the
- // field
- // see: https://github.com/nodejs/undici/issues/2630
- field = line.subarray(0, colonPosition).toString('utf8')
+ fieldLength = colonPosition
// Collect the characters on the line after the first U+003A COLON
// character (:), and let value be that string.
// If value starts with a U+0020 SPACE character, remove it from value.
- let valueStart = colonPosition + 1
+ valueStart = colonPosition + 1
if (line[valueStart] === SPACE) {
++valueStart
}
- // TODO: Investigate if there is a more performant way to extract the
- // value
- // see: https://github.com/nodejs/undici/issues/2630
- value = line.subarray(valueStart).toString('utf8')
+ }
- // Otherwise, the string is not empty but does not contain a U+003A COLON
- // character (:)
- } else {
- // Process the field using the steps described below, using the whole
- // line as the field name, and the empty string as the field value.
- field = line.toString('utf8')
- value = ''
- }
-
- // Modify the event with the field name and value. The value is also
- // decoded as UTF-8
- switch (field) {
- case 'data':
- if (event[field] === undefined) {
- event[field] = value
- } else {
- event[field] += `\n${value}`
- }
- break
- case 'retry':
- if (isASCIINumber(value)) {
- event[field] = value
- }
- break
- case 'id':
- if (isValidLastEventId(value)) {
- event[field] = value
- }
- break
- case 'event':
- if (value.length > 0) {
- event[field] = value
- }
- break
+ if (isFieldName(line, fieldLength, DATA)) {
+ const value = line.toString('utf8', valueStart)
+
+ if (event.data === undefined) {
+ event.data = value
+ } else {
+ event.data += `\n${value}`
+ }
+ return
+ }
+
+ if (isFieldName(line, fieldLength, RETRY)) {
+ if (isASCIINumberBytes(line, valueStart)) {
+ event.retry = line.toString('utf8', valueStart)
+ }
+ return
+ }
+
+ if (isFieldName(line, fieldLength, ID)) {
+ if (isValidLastEventIdBytes(line, valueStart)) {
+ event.id = line.toString('utf8', valueStart)
+ }
+ return
+ }
+
+ if (isFieldName(line, fieldLength, EVENT)) {
+ const value = line.toString('utf8', valueStart)
+
+ if (value.length > 0) {
+ event.event = value
+ }
}
}
@@ -17109,13 +17231,152 @@ class EventSourceStream extends Transform {
}
clearEvent () {
- this.event = {
- data: undefined,
- event: undefined,
- id: undefined,
- retry: undefined
+ this.event.data = undefined
+ this.event.event = undefined
+ this.event.id = undefined
+ this.event.retry = undefined
+ }
+
+ hasPendingEvent () {
+ return this.event.data !== undefined ||
+ this.event.event !== undefined ||
+ this.event.id !== undefined ||
+ this.event.retry !== undefined
+ }
+
+ hasCurrentByte () {
+ return this.chunkIndex < this.chunks.length &&
+ this.pos < this.chunks[this.chunkIndex].length
+ }
+
+ currentByte () {
+ return this.chunks[this.chunkIndex][this.pos]
+ }
+
+ consumeCurrentByte () {
+ this.advanceCursor()
+ this.syncLineStartToCursor()
+ }
+
+ advanceCursor () {
+ this.pos++
+
+ while (this.chunkIndex < this.chunks.length && this.pos >= this.chunks[this.chunkIndex].length) {
+ this.chunkIndex++
+ this.pos = 0
+ }
+ }
+
+ syncLineStartToCursor () {
+ this.lineChunkIndex = this.chunkIndex
+ this.linePos = this.pos
+ this.dropConsumedChunks()
+ }
+
+ dropConsumedChunks () {
+ while (this.lineChunkIndex > 0) {
+ this.chunks.shift()
+ this.lineChunkIndex--
+ this.chunkIndex--
+ }
+
+ if (this.chunkIndex === this.chunks.length) {
+ this.chunks.length = 0
+ this.chunkIndex = 0
+ this.pos = 0
+ this.lineChunkIndex = 0
+ this.linePos = 0
+ }
+ }
+
+ readLine () {
+ if (this.lineChunkIndex === this.chunkIndex) {
+ return this.chunks[this.chunkIndex].subarray(this.linePos, this.pos)
+ }
+
+ const chunks = []
+ let length = 0
+
+ for (let i = this.lineChunkIndex; i <= this.chunkIndex; i++) {
+ const chunk = this.chunks[i]
+ const start = i === this.lineChunkIndex ? this.linePos : 0
+ const end = i === this.chunkIndex ? this.pos : chunk.length
+ const slice = chunk.subarray(start, end)
+ length += slice.length
+ chunks.push(slice)
+ }
+
+ return Buffer.concat(chunks, length)
+ }
+
+ peekBufferedByte (offset) {
+ let chunkIndex = this.lineChunkIndex
+ let pos = this.linePos
+
+ while (chunkIndex < this.chunks.length) {
+ const chunk = this.chunks[chunkIndex]
+ const remaining = chunk.length - pos
+
+ if (offset < remaining) {
+ return chunk[pos + offset]
+ }
+
+ offset -= remaining
+ chunkIndex++
+ pos = 0
}
}
+
+ discardLeadingBytes (count) {
+ while (count > 0 && this.lineChunkIndex < this.chunks.length) {
+ const chunk = this.chunks[this.lineChunkIndex]
+ const remaining = chunk.length - this.linePos
+
+ if (count < remaining) {
+ this.linePos += count
+ count = 0
+ } else {
+ count -= remaining
+ this.lineChunkIndex++
+ this.linePos = 0
+ }
+ }
+
+ this.chunkIndex = this.lineChunkIndex
+ this.pos = this.linePos
+ this.dropConsumedChunks()
+ }
+
+ handleBOM () {
+ const first = this.peekBufferedByte(0)
+ const second = this.peekBufferedByte(1)
+ const third = this.peekBufferedByte(2)
+
+ if (second === undefined) {
+ if (first === BOM[0]) {
+ return true
+ }
+
+ this.checkBOM = false
+ return true
+ }
+
+ if (third === undefined) {
+ if (first === BOM[0] && second === BOM[1]) {
+ return true
+ }
+
+ this.checkBOM = false
+ return false
+ }
+
+ if (first === BOM[0] && second === BOM[1] && third === BOM[2]) {
+ this.discardLeadingBytes(3)
+ }
+
+ this.checkBOM = false
+ return !this.hasCurrentByte()
+ }
}
module.exports = {
@@ -28383,7 +28644,7 @@ function establishWebSocketConnection (url, protocols, client, ws, onEstablish,
// is specified, the server needs to include the same field and one of
// the selected subprotocol values in its response for the connection to
// be established.
- if (!requestProtocols.includes(secProtocol)) {
+ if (requestProtocols === null || !requestProtocols.includes(secProtocol)) {
failWebsocketConnection(ws, 'Protocol was not set in the opening handshake.')
return
}
@@ -29144,7 +29405,12 @@ class PerMessageDeflate {
if (this.#maxPayloadSize > 0 && this.#inflate[kLength] > this.#maxPayloadSize) {
callback(new MessageSizeExceededError())
+ // The inflater may still hold buffered input that can emit a late
+ // zlib error. Remove the data listener, then deterministically stop
+ // the stream so a subsequent 'error' cannot fire without a listener
+ // (which would terminate the process as an unhandled error event).
this.#inflate.removeAllListeners()
+ this.#inflate.destroy()
this.#inflate = null
return
}
@@ -30780,6 +31046,7 @@ module.exports = {
/* harmony export */ OD: () => (/* binding */ INPUT_DEFAULT_GPG_PRIVATE_KEY),
/* harmony export */ OT: () => (/* binding */ INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL),
/* harmony export */ PG: () => (/* binding */ MACOS_JAVA_CONTENT_POSTFIX),
+/* harmony export */ Pt: () => (/* binding */ INPUT_MVN_SERVER_REPOSITORY_ORIGINS),
/* harmony export */ QM: () => (/* binding */ INPUT_JAVA_VERSION),
/* harmony export */ RX: () => (/* binding */ INPUT_DEFAULT_GPG_PASSPHRASE),
/* harmony export */ TS: () => (/* binding */ INPUT_OVERWRITE_SETTINGS),
@@ -30794,6 +31061,7 @@ module.exports = {
/* harmony export */ af: () => (/* binding */ INPUT_JAVA_VERSION_FILE),
/* harmony export */ db: () => (/* binding */ INPUT_GPG_PASSPHRASE_ENV_VAR),
/* harmony export */ fd: () => (/* binding */ INPUT_SERVER_ID),
+/* harmony export */ gR: () => (/* binding */ INPUT_MVN_PLUGIN_REPOSITORIES),
/* harmony export */ g_: () => (/* binding */ INPUT_DISTRIBUTION),
/* harmony export */ gk: () => (/* binding */ INPUT_CACHE),
/* harmony export */ hq: () => (/* binding */ MAVEN_REPOSITORIES_PROFILE_ID),
@@ -30840,7 +31108,9 @@ const INPUT_VERIFY_SIGNATURE_PUBLIC_KEY = 'verify-signature-public-key';
const SIGNATURE_VERIFICATION_DOCUMENTATION_URL = 'https://github.com/actions/setup-java#download-integrity-and-signatures';
const SIGNATURE_VERIFICATION_FAILURE_HELP = `If this is a legitimate vendor signing-key rotation, see ${SIGNATURE_VERIFICATION_DOCUMENTATION_URL} for instructions to configure the updated public key or temporarily disable signature verification.`;
const INPUT_MVN_SERVER_CREDENTIALS = 'mvn-server-credentials';
+const INPUT_MVN_SERVER_REPOSITORY_ORIGINS = 'mvn-server-repository-origins';
const INPUT_MVN_REPOSITORIES = 'mvn-repositories';
+const INPUT_MVN_PLUGIN_REPOSITORIES = 'mvn-plugin-repositories';
const INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL = 'mvn-repositories-include-central';
const INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL = 'mvn-repositories-prioritize-central';
const INPUT_SERVER_ID = 'server-id';
@@ -30975,12 +31245,7 @@ function canResolveTemurinJmods(version) {
if (normalizedVersion === 'latest') {
return true;
}
- let normalizedRange = normalizedVersion
- .replace(/-ea$/, '')
- .replace('-ea.', '+');
- if (/^\d+(\.\d+){3,}$/.test(normalizedRange)) {
- normalizedRange = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__/* .convertVersionToSemver */ .ZY)(normalizedRange);
- }
+ const normalizedRange = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__/* .normalizeJavaVersionToSemver */ .zZ)(normalizedVersion.replace(/-ea$/, '').replace('-ea.', '+'));
if (!semver__WEBPACK_IMPORTED_MODULE_0___default().validRange(normalizedRange)) {
// JavaBase owns general version validation and its targeted error messages.
return true;
@@ -31022,7 +31287,14 @@ function createUnsupportedPackageError(distributionName, packageType, supportedP
const X64_ARM64 = ['x64', 'aarch64'];
-const STANDARD_LINUX = ['x64', 'x86', 'aarch64', 'ppc64le', 's390x'];
+const STANDARD_LINUX = [
+ 'x64',
+ 'x86',
+ 'aarch64',
+ 'ppc64le',
+ 'riscv64',
+ 's390x'
+];
const JAVA_PLATFORM_CAPABILITIES = {
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.Temurin]: {
platforms: {
@@ -31164,6 +31436,7 @@ const CANONICAL_ARCHITECTURES = [
'aarch64',
'ppc64le',
'ppc64',
+ 'riscv64',
's390x'
];
const PLATFORM_ALIASES = {
@@ -31303,7 +31576,8 @@ function validateToolchainIds(versions, versionFile, toolchainIds) {
/* harmony export */ rC: () => (/* binding */ getNextPageUrlFromLinkHeader),
/* harmony export */ ri: () => (/* binding */ getLatestMajorVersion),
/* harmony export */ y: () => (/* binding */ isVersionSatisfies),
-/* harmony export */ yH: () => (/* binding */ getToolcachePath)
+/* harmony export */ yH: () => (/* binding */ getToolcachePath),
+/* harmony export */ zZ: () => (/* binding */ normalizeJavaVersionToSemver)
/* harmony export */ });
/* unused harmony exports getVersionFromToolcachePath, isJobStatusSuccess */
/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_0__ = __nccwpck_require__(857);
@@ -31704,6 +31978,20 @@ function convertVersionToSemver(version) {
}
return mainVersion;
}
+/**
+ * Java versions (JEP 322) can contain more numeric fields than SemVer allows,
+ * e.g. '11.0.9.1' or Temurin respins such as '26.0.2.1+1'. Move the extra
+ * fields into SemVer build metadata ('11.0.9+1', '26.0.2+1.1'). Any other
+ * input (ranges, regular SemVer versions) is returned unchanged.
+ */
+function normalizeJavaVersionToSemver(version) {
+ const match = /^(\d+(?:\.\d+){3,})(?:\+([0-9A-Za-z.-]+))?$/.exec(version);
+ if (!match) {
+ return version;
+ }
+ const converted = convertVersionToSemver(match[1]);
+ return match[2] ? `${converted}.${match[2]}` : converted;
+}
/**
* Builds a validator for the bytes currently served by a URL from the response
* headers of a HEAD request. A vendor's `/latest/` URL never changes, so this
diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md
index 8561ab6f4..dedca4ed4 100644
--- a/docs/advanced-usage.md
+++ b/docs/advanced-usage.md
@@ -649,7 +649,7 @@ absent from a vendor catalog.
| Distribution | Linux | macOS | Windows | Other / version restrictions |
| --- | --- | --- | --- | --- |
-| `temurin` | `x64`, `x86`, `armv7`, `aarch64`, `ppc64le`, `s390x` | `x64`, `aarch64` | `x64`, `x86`, `aarch64` | Linux `armv7` is available through Java 17. |
+| `temurin` | `x64`, `x86`, `armv7`, `aarch64`, `ppc64le`, `riscv64`, `s390x` | `x64`, `aarch64` | `x64`, `x86`, `aarch64` | Linux `armv7` is available through Java 17. |
| `zulu` | `x64`, `x86`, `armv7`, `aarch64` | `x64`, `aarch64` | `x64`, `x86`, `aarch64` | |
| `liberica` | `x64`, `x86`, `armv7`, `aarch64`, `ppc64le` | `x64`, `aarch64` | `x64`, `x86`, `aarch64` | Solaris: `x64`. |
| `liberica-nik` | `x64`, `aarch64` | `x64`, `aarch64` | `x64`, `aarch64` | |
@@ -885,6 +885,11 @@ Use `mvn-server-credentials` to add more than one credential entry to the genera
When this input is set, it replaces the single server configured by `server-id`, `server-username-env-var`, and `server-password-env-var`.
+Use `mvn-server-repository-origins` when a Maven server credential must be allowed for an explicit repository origin. Each line has the format `server-id:repository-origin`; a server can have multiple origins.
+
+> [!NOTE]
+> `mvn-server-repository-origins` only works with Maven 3.10 and later. Earlier Maven versions ignore the generated `repositoryOrigins` element and log an `Unrecognised tag: 'repositoryOrigins'` warning. GitHub-hosted runners currently ship Maven 3.9.x, so use the [Maven Wrapper](https://maven.apache.org/tools/wrapper/) or install Maven 3.10+ yourself to use this feature.
+
```yaml
steps:
- uses: actions/checkout@v7
@@ -896,6 +901,9 @@ steps:
mvn-server-credentials: |
releases:RELEASES_USERNAME:RELEASES_PASSWORD
snapshots:SNAPSHOTS_USERNAME:SNAPSHOTS_PASSWORD
+ mvn-server-repository-origins: |
+ releases:https://central.sonatype.com
+ snapshots:https://central.sonatype.com
- name: Publish with Maven
run: mvn deploy
env:
@@ -913,11 +921,17 @@ This configuration produces the following server entries:
releases
${env.RELEASES_USERNAME}
${env.RELEASES_PASSWORD}
+
+ https://central.sonatype.com
+
snapshots
${env.SNAPSHOTS_USERNAME}
${env.SNAPSHOTS_PASSWORD}
+
+ https://central.sonatype.com
+
```
@@ -989,14 +1003,92 @@ This configuration adds the following active profile to `settings.xml`:
```
-Maven Central is included first by default. Set
-`mvn-repositories-prioritize-central: false` to place custom repositories
-first, or set `mvn-repositories-include-central: false` to disable Central. The
-generated profile overrides the Central repository inherited from Maven's Super
-POM with releases and snapshots disabled. When automatic Central inclusion is
-off, the ID `central` may instead be declared explicitly in `mvn-repositories`
-to replace it with a user-specified repository; otherwise that ID is reserved
-to prevent duplicate entries.
+Maven Central is included first by default. The Central controls apply to both
+dependency and plugin repositories. Set
+`mvn-repositories-prioritize-central: false` to place custom repositories first
+within each configured list, or set `mvn-repositories-include-central: false` to
+disable Central for both types. The generated profile overrides the dependency
+and plugin Central repositories inherited from Maven's Super POM with releases
+and snapshots disabled, even if only one custom repository list is supplied.
+These controls have no effect when neither list contains a nonblank entry.
+
+When automatic Central inclusion is off, the ID `central` may instead be
+declared explicitly in `mvn-repositories` or `mvn-plugin-repositories` to replace
+it with a user-specified repository for that type. Declaring it in one list
+does not enable Central in the other. Otherwise that ID is reserved to prevent
+duplicate entries. Other repositories declared in your project's POM are not
+disabled by these controls.
+
+### Resolving Maven plugins from custom repositories
+
+Maven resolves build plugins through ``, separately from
+dependency ``. Use `mvn-plugin-repositories` to configure plugin
+resolution with the same multiline `repository-id:repository-url:snapshots-enabled`
+format. It can be supplied without `mvn-repositories`; dependency repositories
+are not automatically used as plugin repositories.
+
+For example, configure the same private repository for dependencies and plugins
+and disable inherited Maven Central for both:
+
+```yaml
+steps:
+ - uses: actions/checkout@v7
+ - uses: actions/setup-java@v6
+ with:
+ distribution: 'temurin'
+ java-version: '21'
+ mvn-server-credentials: |
+ private:PRIVATE_REPOSITORY_USERNAME:PRIVATE_REPOSITORY_TOKEN
+ mvn-repositories: |
+ private:https://maven.example.com/releases:false
+ mvn-plugin-repositories: |
+ private:https://maven.example.com/releases:false
+ mvn-repositories-include-central: false
+ - run: mvn --batch-mode verify
+ env:
+ PRIVATE_REPOSITORY_USERNAME: ${{ secrets.PRIVATE_REPOSITORY_USERNAME }}
+ PRIVATE_REPOSITORY_TOKEN: ${{ secrets.PRIVATE_REPOSITORY_TOKEN }}
+```
+
+The matching ID `private` selects the same server credentials for both types.
+IDs must be unique within each list, but can be shared across the two lists.
+Public repositories do not require a matching credential entry.
+
+Alongside dependency repositories, the active `setup-java-repositories` profile
+contains:
+
+```xml
+
+
+ private
+ https://maven.example.com/releases
+
+ false
+
+
+
+ central
+ https://repo.maven.apache.org/maven2
+
+ false
+
+
+ false
+
+
+
+```
+
+Omitting a Central override would leave the Super POM's plugin repository
+enabled. In particular, `mvn-repositories-include-central: false` now disables
+inherited plugin Central even for existing workflows that only configure
+`mvn-repositories`. To download plugins in such workflows, configure a plugin
+repository or explicitly declare `central` in `mvn-plugin-repositories`.
+
+With Central included, it is placed before custom plugin repositories by
+default; `mvn-repositories-prioritize-central: false` places it after them.
+All repository generation respects `settings-path` and `overwrite-settings`;
+an existing settings file is left untouched when `overwrite-settings: false`.
### GPG
diff --git a/package-lock.json b/package-lock.json
index bcc003721..47cb35a8d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,27 +16,27 @@
"@actions/http-client": "^4.0.1",
"@actions/io": "^3.0.2",
"@actions/tool-cache": "^4.0.0",
- "fast-xml-parser": "^5.11.0",
+ "fast-xml-parser": "^5.11.1",
"semver": "^7.8.5"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
- "@jest/globals": "^30.4.1",
- "@types/node": "^26.2.0",
+ "@jest/globals": "^30.5.2",
+ "@types/node": "^26.6.2",
"@types/semver": "^7.8.0",
- "@typescript-eslint/eslint-plugin": "^8.67.0",
+ "@typescript-eslint/eslint-plugin": "^8.70.1",
"@typescript-eslint/parser": "^8.65.0",
"@vercel/ncc": "^0.45.0",
- "eslint": "^10.8.1",
+ "eslint": "^10.11.0",
"eslint-config-prettier": "^10.1.8",
- "eslint-plugin-jest": "^29.16.1",
+ "eslint-plugin-jest": "^29.16.6",
"eslint-plugin-n": "^18.3.0",
- "globals": "^17.11.0",
+ "globals": "^17.12.0",
"husky": "^9.1.7",
- "jest": "^30.4.2",
- "lint-staged": "^17.3.0",
- "prettier": "^3.9.5",
- "ts-jest": "^29.4.11",
+ "jest": "^30.5.2",
+ "lint-staged": "^17.5.1",
+ "prettier": "^3.9.9",
+ "ts-jest": "^29.4.13",
"typescript": "^6.0.3"
},
"engines": {
@@ -836,6 +836,30 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@cacheable/memory": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.2.0.tgz",
+ "integrity": "sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cacheable/utils": "^2.5.0",
+ "@keyv/bigmap": "^1.3.1",
+ "hookified": "^1.15.1",
+ "keyv": "^5.6.0"
+ }
+ },
+ "node_modules/@cacheable/utils": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.5.0.tgz",
+ "integrity": "sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hashery": "^1.5.1",
+ "keyv": "^5.6.0"
+ }
+ },
"node_modules/@emnapi/core": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
@@ -972,9 +996,9 @@
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz",
- "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==",
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.3.tgz",
+ "integrity": "sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -1145,17 +1169,17 @@
}
},
"node_modules/@jest/console": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.4.1.tgz",
- "integrity": "sha512-v3bhyxUh9Hgmo5p6hAOXe14/R3ZxZDOsvHleh4B07z3m/x4/ngPUXEm9XwK4sF4u+f+P2ORb0Ge+MgpaqRMVDA==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.5.2.tgz",
+ "integrity": "sha512-e8sQC4pCMHPBrPX7Hk8TJr+DM5dkUnImSTNag8SEWFAFAF6xIz4AJvCKapnrdHnZxep4bxw4PhG+ZbimYBMyKw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/types": "30.4.1",
+ "@jest/types": "30.5.1",
"@types/node": "*",
"chalk": "^4.1.2",
- "jest-message-util": "30.4.1",
- "jest-util": "30.4.1",
+ "jest-message-util": "30.5.1",
+ "jest-util": "30.5.1",
"slash": "^3.0.0"
},
"engines": {
@@ -1163,18 +1187,18 @@
}
},
"node_modules/@jest/core": {
- "version": "30.4.2",
- "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.4.2.tgz",
- "integrity": "sha512-TZJA6cPJUFxoWhxaLo8t0VX/MZX2wPWr0uIDvLSHIvN4gu9h02vSzqI2kBADG1ExqQlC+cY09xKMSreivvrChQ==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.5.2.tgz",
+ "integrity": "sha512-/jqvFWoJF7LV1a6AUpYMbMm+2yIYsHJfR474H0SCzr9k8tnO/jl9wRg6zSG6lxgf6EozNlCG4amFzWsbZSvvZA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/console": "30.4.1",
- "@jest/pattern": "30.4.0",
- "@jest/reporters": "30.4.1",
- "@jest/test-result": "30.4.1",
- "@jest/transform": "30.4.1",
- "@jest/types": "30.4.1",
+ "@jest/console": "30.5.2",
+ "@jest/pattern": "30.5.0",
+ "@jest/reporters": "30.5.2",
+ "@jest/test-result": "30.5.2",
+ "@jest/transform": "30.5.2",
+ "@jest/types": "30.5.1",
"@types/node": "*",
"ansi-escapes": "^4.3.2",
"chalk": "^4.1.2",
@@ -1182,20 +1206,20 @@
"exit-x": "^0.2.2",
"fast-json-stable-stringify": "^2.1.0",
"graceful-fs": "^4.2.11",
- "jest-changed-files": "30.4.1",
- "jest-config": "30.4.2",
- "jest-haste-map": "30.4.1",
- "jest-message-util": "30.4.1",
- "jest-regex-util": "30.4.0",
- "jest-resolve": "30.4.1",
- "jest-resolve-dependencies": "30.4.2",
- "jest-runner": "30.4.2",
- "jest-runtime": "30.4.2",
- "jest-snapshot": "30.4.1",
- "jest-util": "30.4.1",
- "jest-validate": "30.4.1",
- "jest-watcher": "30.4.1",
- "pretty-format": "30.4.1",
+ "jest-changed-files": "30.5.1",
+ "jest-config": "30.5.2",
+ "jest-haste-map": "30.5.1",
+ "jest-message-util": "30.5.1",
+ "jest-regex-util": "30.5.0",
+ "jest-resolve": "30.5.1",
+ "jest-resolve-dependencies": "30.5.2",
+ "jest-runner": "30.5.2",
+ "jest-runtime": "30.5.2",
+ "jest-snapshot": "30.5.2",
+ "jest-util": "30.5.1",
+ "jest-validate": "30.5.1",
+ "jest-watcher": "30.5.2",
+ "pretty-format": "30.5.1",
"slash": "^3.0.0"
},
"engines": {
@@ -1211,9 +1235,9 @@
}
},
"node_modules/@jest/diff-sequences": {
- "version": "30.4.0",
- "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.4.0.tgz",
- "integrity": "sha512-zOpzlfUs45l6u7jm39qr87JCHUDsaeCtvL+kQe/Vn9jSnRB4/5IPXISm0h9I1vZW/o00Kn4UTJ2MOlhnUGwv3g==",
+ "version": "30.5.0",
+ "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.5.0.tgz",
+ "integrity": "sha512-OsqBjHXCn8cadasoAZBP6nWYvMsRhpMzGXTpxJ5aO04NlbdhIz+FVe3q49l0AwVhsz/cEmIpBes6gAFl1/dWQg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1221,70 +1245,70 @@
}
},
"node_modules/@jest/environment": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.4.1.tgz",
- "integrity": "sha512-AK9yNRqgKxiabqMoe4oW+3/TSSeV8vkdC7BGaxZdU0AFXfOpofTLqdru2GXKZghP3sdgwE9XXpnVwfZ8JnFV4w==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.5.2.tgz",
+ "integrity": "sha512-nwFPOUMbmsjNNRCpnJpB9HbSZu4C07wDDds++5j+j1MezzPLxMPDdbdUVjr2o4RULDOValnDd70taPFI1EtxAg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/fake-timers": "30.4.1",
- "@jest/types": "30.4.1",
+ "@jest/fake-timers": "30.5.2",
+ "@jest/types": "30.5.1",
"@types/node": "*",
- "jest-mock": "30.4.1"
+ "jest-mock": "30.5.2"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
"node_modules/@jest/expect": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.4.1.tgz",
- "integrity": "sha512-ginrj6TMgh2GshLUGCjO94Ptx9HhdZA/I6A9iUfyeLKFtdAjnKzHDgzgP9HYQgbxM1lbXScQ2eUBz2lGeVDPWA==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.5.2.tgz",
+ "integrity": "sha512-2E+1Pg6jJxbRjLNLpciC71iri/3qsKJL222/aXJEFwC0VdUSvfS+JZQQLEVjUYYc8t8pQu2MGE3cF2+bNTYRsg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "expect": "30.4.1",
- "jest-snapshot": "30.4.1"
+ "expect": "30.5.2",
+ "jest-snapshot": "30.5.2"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
"node_modules/@jest/expect-utils": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.4.1.tgz",
- "integrity": "sha512-ZBn5CglH8fBsQsvs4VWNzD4aWfUYks+IdOOQU3MEK71ol/BcVm+P+rtb1KpiFBpSWSCE27uOahyyf1vfqOVbcQ==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.5.2.tgz",
+ "integrity": "sha512-d/HOLSrJUlBIl6n3LzOa7cjW3xdePm5H5gQw2lixZ/0h157l9sw3mLblzFqnPcTbhDzhRQdBOX3A3KcG73nm5Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/get-type": "30.1.0"
+ "@jest/get-type": "30.5.0"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
"node_modules/@jest/fake-timers": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.4.1.tgz",
- "integrity": "sha512-iW5umdmfPeWzehrVhugFQZqCchSCud5S1l2YT0O9ZhjRR0ExclANDZkiSBwzqtnlOn0J1JXvO+HZ6rkuyOVOgQ==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.5.2.tgz",
+ "integrity": "sha512-GKk0h0tKT5SpDPxDhPg3r9mm5s8/YCBzVNMOGdRiQXwUiMsjU10mVPlMaQstH6/cu50vOb8N9oQUMETHuwwxKw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/types": "30.4.1",
+ "@jest/types": "30.5.1",
"@sinonjs/fake-timers": "^15.4.0",
"@types/node": "*",
- "jest-message-util": "30.4.1",
- "jest-mock": "30.4.1",
- "jest-util": "30.4.1"
+ "jest-message-util": "30.5.1",
+ "jest-mock": "30.5.2",
+ "jest-util": "30.5.1"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
"node_modules/@jest/get-type": {
- "version": "30.1.0",
- "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz",
- "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==",
+ "version": "30.5.0",
+ "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.5.0.tgz",
+ "integrity": "sha512-9/2VUPitAjmBzbvDvqrxmvB7BzWsBW0WmkkojX1ODuxX1NLGxx9gfaZpHB0z8DtJ9uhGNmZG/VXBhf8uO0OV8Q==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1292,62 +1316,78 @@
}
},
"node_modules/@jest/globals": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.4.1.tgz",
- "integrity": "sha512-ZbuY4cmXC8DkxYjfvT2DbcHWL2T6vmsMhXCDcmTB2T0y0gaezBI77ufq5ZAIdcRkYZ7NEQEDg1xFeKbxUJ5v5Q==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.5.2.tgz",
+ "integrity": "sha512-62zfS+dL+M5aTNHXCNLyqD+j4oqxTIzDYrZbpqMP8Yn+gvlAGyzC6BSPNb1ZmFOakV1RtFYX/O3FCQXSWmQdgg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/environment": "30.4.1",
- "@jest/expect": "30.4.1",
- "@jest/types": "30.4.1",
- "jest-mock": "30.4.1"
+ "@jest/environment": "30.5.2",
+ "@jest/expect": "30.5.2",
+ "@jest/types": "30.5.1",
+ "jest-mock": "30.5.2"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
"node_modules/@jest/pattern": {
- "version": "30.4.0",
- "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.4.0.tgz",
- "integrity": "sha512-RAWn3+f9u8BsHijKJ71uHcFp6vmyEt6VvoWXkl6hKF3qVIuWNmudVjg12DlBPGup/frIl5UcUlH5HfEuvHpEXg==",
+ "version": "30.5.0",
+ "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.5.0.tgz",
+ "integrity": "sha512-HdNQYSdRTEBNrginaqzQtTjG0HRMfrra/z6Ok7uL3S87vSlarIVohEsJsSj5edu3MiHoHjAkvPROz5ZjoKai+w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*",
- "jest-regex-util": "30.4.0"
+ "jest-regex-util": "30.5.0"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
+ "node_modules/@jest/react-is-18": {
+ "name": "react-is",
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jest/react-is-19": {
+ "name": "react-is",
+ "version": "19.3.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.3.0.tgz",
+ "integrity": "sha512-UpMYezM4v5/18F28aC66AEsjXIgE02kyEMH6yLdgLXu/UTfa1Ntwck/nNLrbqJsEXW7gPb0coNO9FQse9WTovA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@jest/reporters": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.4.1.tgz",
- "integrity": "sha512-/SnkPCzEQpUaBH81kjdEdDdo2WZl5hxw+BmLDGWjRkm8o7XlhjwsU36cqwe5PGBE5WYpBvDzRSdXx9rbGuJtNA==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.5.2.tgz",
+ "integrity": "sha512-ev6E9iG73twQcfAfoTnviuYkr3yOrYbzAtMFCimv2fxHXPIp9PBt2u1wNMt0aYWgl8FPwIcS8oqRJg6alnht4Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@bcoe/v8-coverage": "^0.2.3",
- "@jest/console": "30.4.1",
- "@jest/test-result": "30.4.1",
- "@jest/transform": "30.4.1",
- "@jest/types": "30.4.1",
- "@jridgewell/trace-mapping": "^0.3.25",
+ "@jest/console": "30.5.2",
+ "@jest/test-result": "30.5.2",
+ "@jest/transform": "30.5.2",
+ "@jest/types": "30.5.1",
+ "@jridgewell/trace-mapping": "^0.3.31",
"@types/node": "*",
"chalk": "^4.1.2",
"collect-v8-coverage": "^1.0.2",
"exit-x": "^0.2.2",
- "glob": "^10.5.0",
+ "glob": "^13.0.6",
"graceful-fs": "^4.2.11",
"istanbul-lib-coverage": "^3.0.0",
"istanbul-lib-instrument": "^6.0.0",
"istanbul-lib-report": "^3.0.0",
"istanbul-lib-source-maps": "^5.0.0",
"istanbul-reports": "^3.1.3",
- "jest-message-util": "30.4.1",
- "jest-util": "30.4.1",
- "jest-worker": "30.4.1",
+ "jest-message-util": "30.5.1",
+ "jest-util": "30.5.1",
+ "jest-worker": "30.5.1",
"slash": "^3.0.0",
"string-length": "^4.0.2",
"v8-to-istanbul": "^9.0.1"
@@ -1365,9 +1405,9 @@
}
},
"node_modules/@jest/schemas": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.4.1.tgz",
- "integrity": "sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==",
+ "version": "30.5.0",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.5.0.tgz",
+ "integrity": "sha512-/hunigyNpc4RCjC0VaW3f5RCUZVM2+WQ65qP7z083Gmvac7or2LI50XVNOtE4YPgBpV0yxYiAgorAPGniCoJmg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1378,13 +1418,13 @@
}
},
"node_modules/@jest/snapshot-utils": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.4.1.tgz",
- "integrity": "sha512-ObY4ljvQ95mt6iwKtVLetR/4yXiAgl3H4nJxhztr0MTjrN97TwDYrnCp/kF60Ec9HdhkWTHSu+Hg05aXfngpOA==",
+ "version": "30.5.1",
+ "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.5.1.tgz",
+ "integrity": "sha512-V3wnxNtiVmw5PPVg433Cn3VdXnsOeu/ofLw3KC04Bn2y1wIlU5kozXQn48rhrgj/02LrCVtntTEF1yBha0XSUw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/types": "30.4.1",
+ "@jest/types": "30.5.1",
"chalk": "^4.1.2",
"graceful-fs": "^4.2.11",
"natural-compare": "^1.4.0"
@@ -1394,14 +1434,15 @@
}
},
"node_modules/@jest/source-map": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz",
- "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.5.2.tgz",
+ "integrity": "sha512-c5CehvkbfHX6yyNg7bMn2ylqlp9AHXuZ/3hPH/Lh5bxD/vefd/lV9HBjMqXef9yQNqkdwyZvkLSVSwB38hy8Qw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jridgewell/trace-mapping": "^0.3.25",
+ "@jridgewell/trace-mapping": "^0.3.31",
"callsites": "^3.1.0",
+ "convert-source-map": "^2.0.0",
"graceful-fs": "^4.2.11"
},
"engines": {
@@ -1409,14 +1450,14 @@
}
},
"node_modules/@jest/test-result": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.4.1.tgz",
- "integrity": "sha512-/ZG7pgEiOmmWkN9TplKbOu4id2N5lh7FHwRwlkgBVAzGdRH+OkkQ8wX/kIxg4zmd3ZQvAL1RwL2yWsvNYYECTw==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.5.2.tgz",
+ "integrity": "sha512-eO6YU5rsLfs60ne694e0IAmRgeBnoA8mu0nlxXDbl/1j5km0o2vO9/VbbUIKIH+WRKKEI+ELgwraRGn2Lhep8g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/console": "30.4.1",
- "@jest/types": "30.4.1",
+ "@jest/console": "30.5.2",
+ "@jest/types": "30.5.1",
"@types/istanbul-lib-coverage": "^2.0.6",
"collect-v8-coverage": "^1.0.2"
},
@@ -1425,15 +1466,15 @@
}
},
"node_modules/@jest/test-sequencer": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.4.1.tgz",
- "integrity": "sha512-PeYE+4td5rKjoRPxztObrXU+H8hsjZfxKMXOcmrr34JerSyB/ROOxbbicz8B7A5j9R9VayDnVPvBmedqCsFCdw==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.5.2.tgz",
+ "integrity": "sha512-bmij8jZyYAC47ExT2GeP7PcrlwSNS+Bp3KeRuBH88gpcxqDv6fljN8PemS4J/lLZ79xb6mpaennQTTq0zUAVVg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/test-result": "30.4.1",
+ "@jest/test-result": "30.5.2",
"graceful-fs": "^4.2.11",
- "jest-haste-map": "30.4.1",
+ "jest-haste-map": "30.5.1",
"slash": "^3.0.0"
},
"engines": {
@@ -1441,23 +1482,23 @@
}
},
"node_modules/@jest/transform": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.4.1.tgz",
- "integrity": "sha512-Wz0LyktlTvRefoymh+n64hQ84KNXsRGcwdoZ8CSa0Ea+fgYcHZlnk+hDP7v2MS7il2bQ5uTEIxf4/NNfhMN4KQ==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.5.2.tgz",
+ "integrity": "sha512-LBGwmaE886C41jDZ65eqR1YbXM7642MK3ZhTowZd5+xDlrDLuf4ePuDdDmVSvcr8NTVJ3MqxLkMbUCzuigUaoQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/core": "^7.27.4",
- "@jest/types": "30.4.1",
- "@jridgewell/trace-mapping": "^0.3.25",
- "babel-plugin-istanbul": "^7.0.1",
+ "@jest/types": "30.5.1",
+ "@jridgewell/trace-mapping": "^0.3.31",
+ "babel-plugin-istanbul": "^8.0.0",
"chalk": "^4.1.2",
"convert-source-map": "^2.0.0",
"fast-json-stable-stringify": "^2.1.0",
"graceful-fs": "^4.2.11",
- "jest-haste-map": "30.4.1",
- "jest-regex-util": "30.4.0",
- "jest-util": "30.4.1",
+ "jest-haste-map": "30.5.1",
+ "jest-regex-util": "30.5.0",
+ "jest-util": "30.5.1",
"pirates": "^4.0.7",
"slash": "^3.0.0",
"write-file-atomic": "^5.0.1"
@@ -1467,14 +1508,14 @@
}
},
"node_modules/@jest/types": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.4.1.tgz",
- "integrity": "sha512-f1x/vJXIfjOlEmejYpbkbgw1gOqpPECwMvMEtBqe47j7H2Hg8h8w3o3ikhSXq3MI15kg+oQ0exWO0uCtTNJLoQ==",
+ "version": "30.5.1",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.5.1.tgz",
+ "integrity": "sha512-LvVYn83nnXPl+Rg98nvcFgjx6nRMTArhSn6RAX/w3ELn54S8A42TYZvsCMdGUqTM8S0wyXbtlQdU6Hi6dykj9g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/pattern": "30.4.0",
- "@jest/schemas": "30.4.1",
+ "@jest/pattern": "30.5.0",
+ "@jest/schemas": "30.5.0",
"@types/istanbul-lib-coverage": "^2.0.6",
"@types/istanbul-reports": "^3.0.4",
"@types/node": "*",
@@ -1535,23 +1576,50 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@keyv/bigmap": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz",
+ "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hashery": "^1.4.0",
+ "hookified": "^1.15.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "keyv": "^5.6.0"
+ }
+ },
+ "node_modules/@keyv/serialize": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz",
+ "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@napi-rs/wasm-runtime": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz",
- "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.4.tgz",
+ "integrity": "sha512-AJxoUD2/15ESHbvpcyjU274nsAPLuOtPHCk0vKJM5pj//Fg/B1FXNWjPnXTT9PymCYYiHo4zPj0ZomXBKhoy7g==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@tybys/wasm-util": "^0.10.3"
},
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=23.5.0"
+ },
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
},
"peerDependencies": {
- "@emnapi/core": "^1.7.1",
- "@emnapi/runtime": "^1.7.1"
+ "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4",
+ "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4"
}
},
"node_modules/@nodable/entities": {
@@ -1566,6 +1634,311 @@
],
"license": "MIT"
},
+ "node_modules/@parcel/watcher": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.6.0.tgz",
+ "integrity": "sha512-7FNeNl8NCE7aINx7WXiKQrPYZWC/hvrTsmk6zmxbI7LTXE7hVek/n8AfVgpe2y82zl3w0HvCHN0bVKMBoJcC0w==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "detect-libc": "^2.0.3",
+ "is-glob": "^4.0.3",
+ "node-addon-api": "^7.0.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "@parcel/watcher-android-arm64": "2.6.0",
+ "@parcel/watcher-darwin-arm64": "2.6.0",
+ "@parcel/watcher-darwin-x64": "2.6.0",
+ "@parcel/watcher-freebsd-x64": "2.6.0",
+ "@parcel/watcher-linux-arm-glibc": "2.6.0",
+ "@parcel/watcher-linux-arm-musl": "2.6.0",
+ "@parcel/watcher-linux-arm64-glibc": "2.6.0",
+ "@parcel/watcher-linux-arm64-musl": "2.6.0",
+ "@parcel/watcher-linux-x64-glibc": "2.6.0",
+ "@parcel/watcher-linux-x64-musl": "2.6.0",
+ "@parcel/watcher-win32-arm64": "2.6.0",
+ "@parcel/watcher-win32-x64": "2.6.0"
+ }
+ },
+ "node_modules/@parcel/watcher-android-arm64": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.6.0.tgz",
+ "integrity": "sha512-trgpLSCKRC/huFjXX/Smh+0sWe4+YtKfktIToiMl59ghz7z+qkH6kMvNnUbLyRs9N11t8l4svSCs1+5B3rOAhA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-darwin-arm64": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.6.0.tgz",
+ "integrity": "sha512-Y3QV0gl7Q1zbfueunkWIERICbEojQFCgpyG7YqOGNFLsckXyI1xu9mAIUpKY9QBYzBtSkN8dBPwd3yiAO9ovMw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-darwin-x64": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.6.0.tgz",
+ "integrity": "sha512-Ohv6OpzhUfKYD7Beb8kDvG0jbIxORCYY1JRdZnaBtnjjkJxgD7ZVL0nw2sCYd0yTMKTvz3nnTnOF3cDifK+kvw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-freebsd-x64": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.6.0.tgz",
+ "integrity": "sha512-5HmXvDgs8VK+74jF9y9/2FE3/OnlcKmc56tjmSrEuZjpSZOGL+fvAu+HKJBdPs9uwoP2hE6TlSUpXZ/C5jUFmQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm-glibc": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.6.0.tgz",
+ "integrity": "sha512-Ps/hui3A+vMbjdqlqAowK2ZL8+BO8dBjxeWXj6npTBs3jx4wWmbPpaLuqwrQrSqIVMCnpWo238bJ1U37GhQOYg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm-musl": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.6.0.tgz",
+ "integrity": "sha512-9c6AUHgHoG+IY88MRIHupztQiQnrbqHYQjkM2btA+Bf/wQnQMuiD0Wfk1EVv3TlNT3x41uU71rn6E4xh/+zvkw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm64-glibc": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.6.0.tgz",
+ "integrity": "sha512-yHRqS2owEXe6Hic9z6Mh1ECsCd+ODVOGvZDyciqRd21+v+o+DnXMOrw50DSpIG2sb8GPEaPPmfeCAWKPJdq46g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm64-musl": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.6.0.tgz",
+ "integrity": "sha512-WhB2e/V7rqdHHWZusBSPuy5Ei8S6lSz6FE5TKKQz5h3a0O+C+mhY7vxU9b/stqvMb8beLnPY82ZrFTLKs+SrKA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-x64-glibc": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.6.0.tgz",
+ "integrity": "sha512-ulGE6x6Oz6iAwg75T8YQSoguBWasniIbX+QWpaYPcCnDOpdWX3k+4xbEYPZVLxOuoJI+svJJPD3sEj8G7lrQ3A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-x64-musl": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.6.0.tgz",
+ "integrity": "sha512-tkBYKt7YQrjIJWYDnto2YgO8MRkjlMTSNoRHzsXinBqbLdeOM3L32wPZJvIZxqaLMfSlS/4sUjH/6STVP/XDLw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-arm64": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.6.0.tgz",
+ "integrity": "sha512-gIZAP23jaHjGWasY/TY6yL7NHFClf0Ga7FN+iINvk+KN94rhm94lYZhFsbYFNcA04/onvGD9kKmiJLJB2HbNwQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-x64": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.6.0.tgz",
+ "integrity": "sha512-cA+/pXV2YkfxlIcXOQ5fSWqAzzPyD78/x5qbK/I0vUkrlYHA8TIz+MXjAbGouguKVSI4bOmkTSJ1/poVSsgt+A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
"node_modules/@pkgr/core": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz",
@@ -1622,9 +1995,9 @@
}
},
"node_modules/@tybys/wasm-util": {
- "version": "0.10.3",
- "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz",
- "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==",
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.4.tgz",
+ "integrity": "sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -1726,13 +2099,13 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "26.2.0",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz",
- "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==",
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.2.tgz",
+ "integrity": "sha512-X1P21scMv4zGKLYqjdGjaKa7COa0RKVYYZZN/NfvLQ1JegxFhdhpZG/Lyn8AXx6CDUavKAd11v6BvfpkDByK8g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "undici-types": "~8.3.0"
+ "undici-types": "~8.9.0"
}
},
"node_modules/@types/semver": {
@@ -1767,17 +2140,17 @@
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.67.0.tgz",
- "integrity": "sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.70.1.tgz",
+ "integrity": "sha512-nDNrUQ/4ruSNYbu749TRY7cfrzPtoLHEXSNBI8aaNY32LlZCajixqRf3FqcKC4p5Cam4VOHYx/t+i5+nKXvrqA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.12.2",
- "@typescript-eslint/scope-manager": "8.67.0",
- "@typescript-eslint/type-utils": "8.67.0",
- "@typescript-eslint/utils": "8.67.0",
- "@typescript-eslint/visitor-keys": "8.67.0",
+ "@typescript-eslint/scope-manager": "8.70.1",
+ "@typescript-eslint/type-utils": "8.70.1",
+ "@typescript-eslint/utils": "8.70.1",
+ "@typescript-eslint/visitor-keys": "8.70.1",
"ignore": "^7.0.5",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.5.0"
@@ -1790,21 +2163,21 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "@typescript-eslint/parser": "^8.67.0",
+ "@typescript-eslint/parser": "^8.70.1",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.67.0.tgz",
- "integrity": "sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.70.1.tgz",
+ "integrity": "sha512-7zKTnyvaVWqzLZHPFQtX1hVHqgkMC+WebPWakNCSyrQVbIP1AM0L0TlBZtACldIRb6PptI8Odk+jyZ5kP3B1VA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.67.0",
- "@typescript-eslint/typescript-estree": "8.67.0",
- "@typescript-eslint/utils": "8.67.0",
+ "@typescript-eslint/types": "8.70.1",
+ "@typescript-eslint/typescript-estree": "8.70.1",
+ "@typescript-eslint/utils": "8.70.1",
"debug": "^4.4.3",
"ts-api-utils": "^2.5.0"
},
@@ -1821,16 +2194,16 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.67.0.tgz",
- "integrity": "sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.70.1.tgz",
+ "integrity": "sha512-TU8PwyGN0PQJUcE96mw8eCQ44SmxGdQlJmlWakHaHQ15eIuuvye5yNtmh/i6oS88jzXVQB71xdNkbkB/fMwL0g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/project-service": "8.67.0",
- "@typescript-eslint/tsconfig-utils": "8.67.0",
- "@typescript-eslint/types": "8.67.0",
- "@typescript-eslint/visitor-keys": "8.67.0",
+ "@typescript-eslint/project-service": "8.70.1",
+ "@typescript-eslint/tsconfig-utils": "8.70.1",
+ "@typescript-eslint/types": "8.70.1",
+ "@typescript-eslint/visitor-keys": "8.70.1",
"debug": "^4.4.3",
"minimatch": "^10.2.2",
"semver": "^7.7.3",
@@ -1849,14 +2222,14 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.67.0.tgz",
- "integrity": "sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.70.1.tgz",
+ "integrity": "sha512-62xOgboPfwc3/IgPSX/W6oQR3ZbF04194FPGUGH8HL8iLFHbt/456/8Ph1wLNUgVF+s94FlHoipBsz+v7+LMnA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.67.0",
- "@typescript-eslint/types": "^8.67.0",
+ "@typescript-eslint/tsconfig-utils": "^8.70.1",
+ "@typescript-eslint/types": "^8.70.1",
"debug": "^4.4.3"
},
"engines": {
@@ -1871,9 +2244,9 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.67.0.tgz",
- "integrity": "sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.70.1.tgz",
+ "integrity": "sha512-jumze1fPI+sDOaM2TWGQdn39PDxTr7TZGeuyLkAbNyx2vtMT3uRnVKChN0hfht5V2TugphJzF6bYXvBcE09qqg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1888,16 +2261,16 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.67.0.tgz",
- "integrity": "sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.70.1.tgz",
+ "integrity": "sha512-Esgul8MsnKnRLdYU2Eb2cRV9bS5HJYtKj1ByJnOzzG2M58DGdSUQ1jUuILxipqcpB2h9WLrbD5GijIWUjX/Tqw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
- "@typescript-eslint/scope-manager": "8.67.0",
- "@typescript-eslint/types": "8.67.0",
- "@typescript-eslint/typescript-estree": "8.67.0"
+ "@typescript-eslint/scope-manager": "8.70.1",
+ "@typescript-eslint/types": "8.70.1",
+ "@typescript-eslint/typescript-estree": "8.70.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1912,16 +2285,16 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.67.0.tgz",
- "integrity": "sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.70.1.tgz",
+ "integrity": "sha512-TU8PwyGN0PQJUcE96mw8eCQ44SmxGdQlJmlWakHaHQ15eIuuvye5yNtmh/i6oS88jzXVQB71xdNkbkB/fMwL0g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/project-service": "8.67.0",
- "@typescript-eslint/tsconfig-utils": "8.67.0",
- "@typescript-eslint/types": "8.67.0",
- "@typescript-eslint/visitor-keys": "8.67.0",
+ "@typescript-eslint/project-service": "8.70.1",
+ "@typescript-eslint/tsconfig-utils": "8.70.1",
+ "@typescript-eslint/types": "8.70.1",
+ "@typescript-eslint/visitor-keys": "8.70.1",
"debug": "^4.4.3",
"minimatch": "^10.2.2",
"semver": "^7.7.3",
@@ -1940,14 +2313,14 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.67.0.tgz",
- "integrity": "sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.70.1.tgz",
+ "integrity": "sha512-62xOgboPfwc3/IgPSX/W6oQR3ZbF04194FPGUGH8HL8iLFHbt/456/8Ph1wLNUgVF+s94FlHoipBsz+v7+LMnA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.67.0",
- "@typescript-eslint/types": "^8.67.0",
+ "@typescript-eslint/tsconfig-utils": "^8.70.1",
+ "@typescript-eslint/types": "^8.70.1",
"debug": "^4.4.3"
},
"engines": {
@@ -1962,9 +2335,9 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.67.0.tgz",
- "integrity": "sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.70.1.tgz",
+ "integrity": "sha512-jumze1fPI+sDOaM2TWGQdn39PDxTr7TZGeuyLkAbNyx2vtMT3uRnVKChN0hfht5V2TugphJzF6bYXvBcE09qqg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1979,16 +2352,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.67.0.tgz",
- "integrity": "sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.70.1.tgz",
+ "integrity": "sha512-nO974WLllwhSFWQXnMLj6nDGa8f0khKEz1JzpPJ1u7Vm/4X1X6ZHajpoknU4bb41vJyMB0HHVyS2GqdhWfIXZw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.67.0",
- "@typescript-eslint/types": "8.67.0",
- "@typescript-eslint/typescript-estree": "8.67.0",
- "@typescript-eslint/visitor-keys": "8.67.0",
+ "@typescript-eslint/scope-manager": "8.70.1",
+ "@typescript-eslint/types": "8.70.1",
+ "@typescript-eslint/typescript-estree": "8.70.1",
+ "@typescript-eslint/visitor-keys": "8.70.1",
"debug": "^4.4.3"
},
"engines": {
@@ -2004,16 +2377,16 @@
}
},
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.67.0.tgz",
- "integrity": "sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.70.1.tgz",
+ "integrity": "sha512-TU8PwyGN0PQJUcE96mw8eCQ44SmxGdQlJmlWakHaHQ15eIuuvye5yNtmh/i6oS88jzXVQB71xdNkbkB/fMwL0g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/project-service": "8.67.0",
- "@typescript-eslint/tsconfig-utils": "8.67.0",
- "@typescript-eslint/types": "8.67.0",
- "@typescript-eslint/visitor-keys": "8.67.0",
+ "@typescript-eslint/project-service": "8.70.1",
+ "@typescript-eslint/tsconfig-utils": "8.70.1",
+ "@typescript-eslint/types": "8.70.1",
+ "@typescript-eslint/visitor-keys": "8.70.1",
"debug": "^4.4.3",
"minimatch": "^10.2.2",
"semver": "^7.7.3",
@@ -2032,14 +2405,14 @@
}
},
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.67.0.tgz",
- "integrity": "sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.70.1.tgz",
+ "integrity": "sha512-62xOgboPfwc3/IgPSX/W6oQR3ZbF04194FPGUGH8HL8iLFHbt/456/8Ph1wLNUgVF+s94FlHoipBsz+v7+LMnA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.67.0",
- "@typescript-eslint/types": "^8.67.0",
+ "@typescript-eslint/tsconfig-utils": "^8.70.1",
+ "@typescript-eslint/types": "^8.70.1",
"debug": "^4.4.3"
},
"engines": {
@@ -2054,9 +2427,9 @@
}
},
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.67.0.tgz",
- "integrity": "sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.70.1.tgz",
+ "integrity": "sha512-jumze1fPI+sDOaM2TWGQdn39PDxTr7TZGeuyLkAbNyx2vtMT3uRnVKChN0hfht5V2TugphJzF6bYXvBcE09qqg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2071,14 +2444,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.67.0.tgz",
- "integrity": "sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.70.1.tgz",
+ "integrity": "sha512-Pa0EeSeAusQc1WbjQMac+YfenewYTBu0KjgYvkUKwhXaHUKbFog23Dm/rp0DX/6tyYOQ3Xl1a+3EcFNZynGHCw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.67.0",
- "@typescript-eslint/visitor-keys": "8.67.0"
+ "@typescript-eslint/types": "8.70.1",
+ "@typescript-eslint/visitor-keys": "8.70.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2089,9 +2462,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.67.0.tgz",
- "integrity": "sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.70.1.tgz",
+ "integrity": "sha512-Dm1ypdhhrGCTyyehxElhgJ6kgk8MVCv5qXdoOVqPr1uqk42jX8KjrZqhROvdShczA8qrDoYiOWn1ykWlx2k81Q==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2103,13 +2476,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.67.0.tgz",
- "integrity": "sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.70.1.tgz",
+ "integrity": "sha512-Vwj9lUIW5Xq3wQ9w6gv3R86g1hMK8f2zNOdGTAgeXUMMXFK78G9ruCjjqutHMNJc0+CH7LYRnHeUB9IT8wFmcw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.67.0",
+ "@typescript-eslint/types": "8.70.1",
"eslint-visitor-keys": "^5.0.0"
},
"engines": {
@@ -2648,16 +3021,16 @@
}
},
"node_modules/babel-jest": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.4.1.tgz",
- "integrity": "sha512-fATAbM8piYxkiXQp3RBXmZHxZVNJZAVXXfyeyCN2Tida3+qJ8ea9UxhiJ2y4fLO90ZImKt6k9FlcH2+rLkJGhw==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.5.2.tgz",
+ "integrity": "sha512-ES8WeJ2fNWPEDunyAtUfJ12nHyaWUloCHdkfK2oW5uSoQSUmjNKdWiGaXJITJwvFEWoD/evHEg/QoCXAvLaQqQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/transform": "30.4.1",
+ "@jest/transform": "30.5.2",
"@types/babel__core": "^7.20.5",
- "babel-plugin-istanbul": "^7.0.1",
- "babel-preset-jest": "30.4.0",
+ "babel-plugin-istanbul": "^8.0.0",
+ "babel-preset-jest": "30.5.0",
"chalk": "^4.1.2",
"graceful-fs": "^4.2.11",
"slash": "^3.0.0"
@@ -2670,9 +3043,9 @@
}
},
"node_modules/babel-plugin-istanbul": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz",
- "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==",
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-8.0.0.tgz",
+ "integrity": "sha512-18wCskrN3DgbuBmp1gr7LBGT8xdz5xhQQqFvFhVxbkl8VBCrMKQ2YtqBWtUal1Zrc1HTuX0011+Brjw78TCFkg==",
"dev": true,
"license": "BSD-3-Clause",
"workspaces": [
@@ -2683,16 +3056,16 @@
"@istanbuljs/load-nyc-config": "^1.0.0",
"@istanbuljs/schema": "^0.1.3",
"istanbul-lib-instrument": "^6.0.2",
- "test-exclude": "^6.0.0"
+ "test-exclude": "^7.0.1"
},
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/babel-plugin-jest-hoist": {
- "version": "30.4.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.4.0.tgz",
- "integrity": "sha512-9EdtWM/sSfXLOGLwSn+GS6pIXyBnL07/8gyJlwFXjWy4DxMOyItqyUT29d4lQiS380EZwYlX7/At4PgBS+m2aA==",
+ "version": "30.5.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.5.0.tgz",
+ "integrity": "sha512-gtGo1B+u14jrZQv6TdSWIWkTqclboo7Qn+dFAGUOIuXLFuJKAdg3U5MIWzZnW4vfUb4dX9skmAMiby86e/SF4A==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2730,20 +3103,20 @@
}
},
"node_modules/babel-preset-jest": {
- "version": "30.4.0",
- "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.4.0.tgz",
- "integrity": "sha512-lBY4jxsNmCnSiu7kquw8ZC9F4+XLMOKypT3RnNHPvU2Kpd4W0xaPuLr5ZkRyOsvLYAY4yaW1ZwTW4xB7NIiZzg==",
+ "version": "30.5.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.5.0.tgz",
+ "integrity": "sha512-ZGPn5ClP4lBDpuOK8W1yQIOy359HmbnZv3suucAlIe+SEE9yDsxV4S2PjSbH2Vc97U+WmzYD7vw3kr8NsQ/i6w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "babel-plugin-jest-hoist": "30.4.0",
+ "babel-plugin-jest-hoist": "30.5.0",
"babel-preset-current-node-syntax": "^1.2.0"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
},
"peerDependencies": {
- "@babel/core": "^7.11.0 || ^8.0.0-beta.1"
+ "@babel/core": "^7.11.0 || ^8.0.0-beta.1 || ^8.0.0"
}
},
"node_modules/balanced-match": {
@@ -2769,9 +3142,9 @@
}
},
"node_modules/brace-expansion": {
- "version": "5.0.9",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
- "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
+ "version": "5.0.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
+ "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
@@ -2837,12 +3210,19 @@
"node-int64": "^0.4.0"
}
},
- "node_modules/buffer-from": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "node_modules/cacheable": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz",
+ "integrity": "sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "dependencies": {
+ "@cacheable/memory": "^2.2.0",
+ "@cacheable/utils": "^2.5.0",
+ "hookified": "^1.15.0",
+ "keyv": "^5.6.0",
+ "qified": "^0.10.1"
+ }
},
"node_modules/callsites": {
"version": "3.1.0",
@@ -2929,9 +3309,9 @@
}
},
"node_modules/cjs-module-lexer": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz",
- "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.1.tgz",
+ "integrity": "sha512-Ca8swihM+/4yKecYHY52kgJd300hi2lADU/a1RxNTRe+RJ9jvqQlESpbz9DnG9mowez8qwXHB8qYdIUw9e+F5Q==",
"dev": true,
"license": "MIT"
},
@@ -3059,6 +3439,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/detect-newline": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
@@ -3120,6 +3510,13 @@
"is-arrayish": "^0.2.1"
}
},
+ "node_modules/es-module-lexer": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz",
+ "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -3144,9 +3541,9 @@
}
},
"node_modules/eslint": {
- "version": "10.8.1",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.1.tgz",
- "integrity": "sha512-wqA7W2jbsC/BnV9Iv1UZpKVFkO1AdNoSmYW8NWG4HNOBbkAMvIqDZ27pI2f07dqn583NcIC44ckjAcOXDL1QbQ==",
+ "version": "10.11.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.11.0.tgz",
+ "integrity": "sha512-P7a6UEEqb9G95MYAtqkmsTbVXIYyzIfl6NGOIJk162PaahFxFyeGcrlXYFSiagECg4sEm8IseJdZBKR3rx6MsQ==",
"dev": true,
"license": "MIT",
"workspaces": [
@@ -3158,7 +3555,7 @@
"@eslint/config-array": "^0.23.5",
"@eslint/config-helpers": "^0.7.0",
"@eslint/core": "^1.2.1",
- "@eslint/plugin-kit": "^0.7.2",
+ "@eslint/plugin-kit": "^0.7.3",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
@@ -3173,7 +3570,7 @@
"esquery": "^1.7.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^8.0.0",
+ "file-entry-cache": "11.1.5 || >11.1.6 <12",
"find-up": "^5.0.0",
"glob-parent": "^6.0.2",
"ignore": "^5.2.0",
@@ -3257,9 +3654,9 @@
}
},
"node_modules/eslint-plugin-jest": {
- "version": "29.16.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.16.1.tgz",
- "integrity": "sha512-tfxOIsjzaBud+f74aLbBMRcnrztt5eCIgnAdeoGdnzMAQ4IdAa/s/p8Ls55mk9MC79N3j2jbv4Qetz6Hclbcfw==",
+ "version": "29.16.6",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.16.6.tgz",
+ "integrity": "sha512-q8TVr0rlNvUD0XnafGWkwtPeX+tTl2llP86EDl3sJtwWrQA/JT9SIu2hLLZbhhX6fT5SDE4O0gIKyZUujKnkYA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3287,16 +3684,16 @@
}
},
"node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.67.0.tgz",
- "integrity": "sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.70.1.tgz",
+ "integrity": "sha512-Esgul8MsnKnRLdYU2Eb2cRV9bS5HJYtKj1ByJnOzzG2M58DGdSUQ1jUuILxipqcpB2h9WLrbD5GijIWUjX/Tqw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
- "@typescript-eslint/scope-manager": "8.67.0",
- "@typescript-eslint/types": "8.67.0",
- "@typescript-eslint/typescript-estree": "8.67.0"
+ "@typescript-eslint/scope-manager": "8.70.1",
+ "@typescript-eslint/types": "8.70.1",
+ "@typescript-eslint/typescript-estree": "8.70.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -3311,16 +3708,16 @@
}
},
"node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.67.0.tgz",
- "integrity": "sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.70.1.tgz",
+ "integrity": "sha512-TU8PwyGN0PQJUcE96mw8eCQ44SmxGdQlJmlWakHaHQ15eIuuvye5yNtmh/i6oS88jzXVQB71xdNkbkB/fMwL0g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/project-service": "8.67.0",
- "@typescript-eslint/tsconfig-utils": "8.67.0",
- "@typescript-eslint/types": "8.67.0",
- "@typescript-eslint/visitor-keys": "8.67.0",
+ "@typescript-eslint/project-service": "8.70.1",
+ "@typescript-eslint/tsconfig-utils": "8.70.1",
+ "@typescript-eslint/types": "8.70.1",
+ "@typescript-eslint/visitor-keys": "8.70.1",
"debug": "^4.4.3",
"minimatch": "^10.2.2",
"semver": "^7.7.3",
@@ -3339,14 +3736,14 @@
}
},
"node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.67.0.tgz",
- "integrity": "sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.70.1.tgz",
+ "integrity": "sha512-62xOgboPfwc3/IgPSX/W6oQR3ZbF04194FPGUGH8HL8iLFHbt/456/8Ph1wLNUgVF+s94FlHoipBsz+v7+LMnA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.67.0",
- "@typescript-eslint/types": "^8.67.0",
+ "@typescript-eslint/tsconfig-utils": "^8.70.1",
+ "@typescript-eslint/types": "^8.70.1",
"debug": "^4.4.3"
},
"engines": {
@@ -3361,9 +3758,9 @@
}
},
"node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.67.0.tgz",
- "integrity": "sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==",
+ "version": "8.70.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.70.1.tgz",
+ "integrity": "sha512-jumze1fPI+sDOaM2TWGQdn39PDxTr7TZGeuyLkAbNyx2vtMT3uRnVKChN0hfht5V2TugphJzF6bYXvBcE09qqg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3633,18 +4030,18 @@
}
},
"node_modules/expect": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/expect/-/expect-30.4.1.tgz",
- "integrity": "sha512-PMARsyh/JtqC20HoGqlFcIlQAyqUtW4PlI1rup1uhYJtKuwAjbvWi3GQMAn+STdHum/dk8xrKfUM1+5SAwpolA==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-30.5.2.tgz",
+ "integrity": "sha512-0LNuMvs8/5mRYhnCR4k+lGV7fqPMs6Bnksda4S3zsCUmdxBpAn4zU4NNzXdq1pMKe/H4W5t/zVIDSJ/H3e0vDA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/expect-utils": "30.4.1",
- "@jest/get-type": "30.1.0",
- "jest-matcher-utils": "30.4.1",
- "jest-message-util": "30.4.1",
- "jest-mock": "30.4.1",
- "jest-util": "30.4.1"
+ "@jest/expect-utils": "30.5.2",
+ "@jest/get-type": "30.5.0",
+ "jest-matcher-utils": "30.5.2",
+ "jest-message-util": "30.5.1",
+ "jest-mock": "30.5.2",
+ "jest-util": "30.5.1"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
@@ -3688,9 +4085,9 @@
}
},
"node_modules/fast-xml-parser": {
- "version": "5.11.0",
- "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.11.0.tgz",
- "integrity": "sha512-9IGxMqvqLOnqP+Egi1nqDHKv5k8aZ7r9n558enxcucmyVGEBNPAU+MOg/8jPIS7rO7sSq4gFm1/nHtiaubMruw==",
+ "version": "5.11.1",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.11.1.tgz",
+ "integrity": "sha512-TBw6K/fxoQGGjCmZDw9w/ZwP3uDcnTM4YH/g+PFRWr8sbe5idXtxNN6vITh4+1ruCZaho6uBFurElsA7F0zzgw==",
"funding": [
{
"type": "github",
@@ -3739,16 +4136,13 @@
}
},
"node_modules/file-entry-cache": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
- "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "version": "11.1.5",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz",
+ "integrity": "sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "flat-cache": "^4.0.0"
- },
- "engines": {
- "node": ">=16.0.0"
+ "flat-cache": "^6.1.23"
}
},
"node_modules/find-up": {
@@ -3769,23 +4163,21 @@
}
},
"node_modules/flat-cache": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
- "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "version": "6.1.23",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz",
+ "integrity": "sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.4"
- },
- "engines": {
- "node": ">=16"
+ "cacheable": "^2.5.0",
+ "flatted": "^3.4.2",
+ "hookified": "^1.15.0"
}
},
"node_modules/flatted": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.3.tgz",
- "integrity": "sha512-/zipXxyO6rGvuNGDiULY9MvEGSkb2gaG4GGH4ygMi0ZZzyMHdUZBmntJmx5x1G2VuPytCwGN4xsJP6cw+sK+vQ==",
+ "version": "3.4.4",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz",
+ "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==",
"dev": true,
"license": "ISC"
},
@@ -3806,21 +4198,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@@ -3916,9 +4293,9 @@
}
},
"node_modules/globals": {
- "version": "17.11.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-17.11.0.tgz",
- "integrity": "sha512-Z2I8hM+PbJDXQDq3Icgpzv+mPdwr68iZUU9d5WW4FuXfDUQfkZaZuvjMv42/5crNyw154+9+VWXbYrUgDXbxNw==",
+ "version": "17.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-17.12.0.tgz",
+ "integrity": "sha512-cezEd/DTyyht9cvSSURyygXPfy04GtWO/5e6ZPvH7fCtjKz9PYOmuawphw1Ctd1f6C+5JypXfGD7ahNMXvevBA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3943,13 +4320,13 @@
"license": "ISC"
},
"node_modules/handlebars": {
- "version": "4.7.9",
- "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz",
- "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==",
+ "version": "4.7.10",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.10.tgz",
+ "integrity": "sha512-P5VJMVM7qgBn6vjXMw8WG9uVI+ncf2pi72j4de4yz5ZULLj2RGqLYaKOYGsgyrViQ0tePOVlN1tDCCXXtFqXKg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "minimist": "^1.2.5",
+ "minimist": "^1.2.8",
"neo-async": "^2.6.2",
"source-map": "^0.6.1",
"wordwrap": "^1.0.0"
@@ -3974,6 +4351,26 @@
"node": ">=8"
}
},
+ "node_modules/hashery": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz",
+ "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hookified": "^1.15.0"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/hookified": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz",
+ "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/html-escaper": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
@@ -4243,16 +4640,16 @@
}
},
"node_modules/jest": {
- "version": "30.4.2",
- "resolved": "https://registry.npmjs.org/jest/-/jest-30.4.2.tgz",
- "integrity": "sha512-Yi1jqNC/Oq0N4hBgNH/YvBpP1P57QqundgytzYqy3yqAa7NZPNjSoi4SGbRAXDMdBzNE6xBCi5U7RgfrvMEUVQ==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-30.5.2.tgz",
+ "integrity": "sha512-3gnpdBIza8ijCl3iMV9ChE3hSt1+46865qqod863gQtJr1DixOkAU5DoGbi3u+XlRcw++BhZQMu/y4xBdHBvSQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/core": "30.4.2",
- "@jest/types": "30.4.1",
+ "@jest/core": "30.5.2",
+ "@jest/types": "30.5.1",
"import-local": "^3.2.0",
- "jest-cli": "30.4.2"
+ "jest-cli": "30.5.2"
},
"bin": {
"jest": "bin/jest.js"
@@ -4270,14 +4667,14 @@
}
},
"node_modules/jest-changed-files": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.4.1.tgz",
- "integrity": "sha512-IuctmYrxi21iOSOaIXpJWalHyPAsVv0GeBHKDn8C1CA4W5htHn7INL+wdnL4Bo0+olEndvAFkmb++tIQJG+vvg==",
+ "version": "30.5.1",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.5.1.tgz",
+ "integrity": "sha512-0+bvMM/ENhDI29Z8q1r4HxiDIi4G5tnBmSw4esfPQoj9q8Nik7KIyuxHkTVnnniJQf05SxpGaKDQ+4h28ynGPg==",
"dev": true,
"license": "MIT",
"dependencies": {
"execa": "^5.1.1",
- "jest-util": "30.4.1",
+ "jest-util": "30.5.1",
"p-limit": "^3.1.0"
},
"engines": {
@@ -4285,29 +4682,29 @@
}
},
"node_modules/jest-circus": {
- "version": "30.4.2",
- "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.4.2.tgz",
- "integrity": "sha512-rvHH7VlY6LgbJXJTQ87GW62g1FntOtbhh0zT+v04kC+pgL6aBKyYINXxWukCpj3dcIBMw5/XUbtDS9dU9JTXeQ==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.5.2.tgz",
+ "integrity": "sha512-vffFgjs5JSJ9q4ds1vNW3klKYPJfYfIY61LT/zaZgvTeASJOWZUt8LBfHgIcV4rwxlPBLl/ePBGccHEclS4PlQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/environment": "30.4.1",
- "@jest/expect": "30.4.1",
- "@jest/test-result": "30.4.1",
- "@jest/types": "30.4.1",
+ "@jest/environment": "30.5.2",
+ "@jest/expect": "30.5.2",
+ "@jest/test-result": "30.5.2",
+ "@jest/types": "30.5.1",
"@types/node": "*",
"chalk": "^4.1.2",
"co": "^4.6.0",
"dedent": "^1.6.0",
"is-generator-fn": "^2.1.0",
- "jest-each": "30.4.1",
- "jest-matcher-utils": "30.4.1",
- "jest-message-util": "30.4.1",
- "jest-runtime": "30.4.2",
- "jest-snapshot": "30.4.1",
- "jest-util": "30.4.1",
+ "jest-each": "30.5.2",
+ "jest-matcher-utils": "30.5.2",
+ "jest-message-util": "30.5.1",
+ "jest-runtime": "30.5.2",
+ "jest-snapshot": "30.5.2",
+ "jest-util": "30.5.1",
"p-limit": "^3.1.0",
- "pretty-format": "30.4.1",
+ "pretty-format": "30.5.1",
"pure-rand": "^7.0.0",
"slash": "^3.0.0",
"stack-utils": "^2.0.6"
@@ -4317,21 +4714,21 @@
}
},
"node_modules/jest-cli": {
- "version": "30.4.2",
- "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.4.2.tgz",
- "integrity": "sha512-jfA2ocvVHMXS2QijrJ0d31ektP+d/W0T5RpcTX2Pq+3sVqHlsXVCM2+FmwpL+bdY8OfHpIg9xMxLF17Zg0U49Q==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.5.2.tgz",
+ "integrity": "sha512-YYYxUUVjFgPvgEleKNKMaYGIFgR3l3832Cl0kRL/oCiDZ03v7wImUtquHl2OOBCCNgprjZgBN5bczS/JklPBDg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/core": "30.4.2",
- "@jest/test-result": "30.4.1",
- "@jest/types": "30.4.1",
+ "@jest/core": "30.5.2",
+ "@jest/test-result": "30.5.2",
+ "@jest/types": "30.5.1",
"chalk": "^4.1.2",
"exit-x": "^0.2.2",
"import-local": "^3.2.0",
- "jest-config": "30.4.2",
- "jest-util": "30.4.1",
- "jest-validate": "30.4.1",
+ "jest-config": "30.5.2",
+ "jest-util": "30.5.1",
+ "jest-validate": "30.5.1",
"yargs": "^17.7.2"
},
"bin": {
@@ -4350,33 +4747,33 @@
}
},
"node_modules/jest-config": {
- "version": "30.4.2",
- "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.4.2.tgz",
- "integrity": "sha512-rNHAShJQqQwFNoL0hbf3BphSBOWnpOUAKvidLS/AjNVLPfoj5mSf4jQMfW3cYOs6hXeZC7nF7mDHaBnbxELOzg==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.5.2.tgz",
+ "integrity": "sha512-U6221OZekabePvGcGPf4raIBKMvYQWFHvhobDJRojOYaFMj2HaGytAdknjDhYc6JTz2fdHW9+6k0wWUDaNeOFQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/core": "^7.27.4",
- "@jest/get-type": "30.1.0",
- "@jest/pattern": "30.4.0",
- "@jest/test-sequencer": "30.4.1",
- "@jest/types": "30.4.1",
- "babel-jest": "30.4.1",
+ "@jest/get-type": "30.5.0",
+ "@jest/pattern": "30.5.0",
+ "@jest/test-sequencer": "30.5.2",
+ "@jest/types": "30.5.1",
+ "babel-jest": "30.5.2",
"chalk": "^4.1.2",
"ci-info": "^4.2.0",
"deepmerge": "^4.3.1",
- "glob": "^10.5.0",
+ "glob": "^13.0.6",
"graceful-fs": "^4.2.11",
- "jest-circus": "30.4.2",
- "jest-docblock": "30.4.0",
- "jest-environment-node": "30.4.1",
- "jest-regex-util": "30.4.0",
- "jest-resolve": "30.4.1",
- "jest-runner": "30.4.2",
- "jest-util": "30.4.1",
- "jest-validate": "30.4.1",
+ "jest-circus": "30.5.2",
+ "jest-docblock": "30.5.0",
+ "jest-environment-node": "30.5.2",
+ "jest-regex-util": "30.5.0",
+ "jest-resolve": "30.5.1",
+ "jest-runner": "30.5.2",
+ "jest-util": "30.5.1",
+ "jest-validate": "30.5.1",
"parse-json": "^5.2.0",
- "pretty-format": "30.4.1",
+ "pretty-format": "30.5.1",
"slash": "^3.0.0",
"strip-json-comments": "^3.1.1"
},
@@ -4401,25 +4798,25 @@
}
},
"node_modules/jest-diff": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.4.1.tgz",
- "integrity": "sha512-CRpFK0RtLriVDGcPPAnR6HMVI8bSR2jnUIgralhauzYQZIb4RH9AtEInTuQr65LmmGggGcRT6HIASxwqsVsmlA==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.5.2.tgz",
+ "integrity": "sha512-rBtHnI6BWTiWj3lM7fOLVfChx7R9B0u9VV3PRHawKs79x6ZjW1QoSrKenaigNGWlvhtoi2BqvDbABDie+Os3xQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/diff-sequences": "30.4.0",
- "@jest/get-type": "30.1.0",
+ "@jest/diff-sequences": "30.5.0",
+ "@jest/get-type": "30.5.0",
"chalk": "^4.1.2",
- "pretty-format": "30.4.1"
+ "pretty-format": "30.5.1"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
"node_modules/jest-docblock": {
- "version": "30.4.0",
- "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.4.0.tgz",
- "integrity": "sha512-ZPMabUZCx5MpbZ2eBYSvZ0J8fvo3dR9oM+eeUpb3aKNQFuS2tu3Duw1TNlMoP8k3WQgKGJuhcMFvwcVuq6T7oA==",
+ "version": "30.5.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.5.0.tgz",
+ "integrity": "sha512-NwDqcxtoZi33RhuW+zJS/RVA3rmheQ8BnwpYZuc/Eruaz6seQb7+aoCeDZu/3X7W2XmD8DbSo9Pn72DbKsBFYw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4430,111 +4827,110 @@
}
},
"node_modules/jest-each": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.4.1.tgz",
- "integrity": "sha512-/8MJbH6fuj48TstjrMf+u/pd06Qezz5xOXvZA6442heNOWr8bdeoGZX2d9fCn028CoMgYmroH9//zky5GfyYmA==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.5.2.tgz",
+ "integrity": "sha512-GRrW+7fmmgmkvyfEBqc1QFdWnF1Ex5yG6Y6AWL4TTxnkWlKIT98dsKh3P3UuWm6v4XsQwVE6DEzXIPMzWJ3ZbA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/get-type": "30.1.0",
- "@jest/types": "30.4.1",
+ "@jest/get-type": "30.5.0",
+ "@jest/types": "30.5.1",
"chalk": "^4.1.2",
- "jest-util": "30.4.1",
- "pretty-format": "30.4.1"
+ "jest-regex-util": "30.5.0",
+ "jest-util": "30.5.1",
+ "pretty-format": "30.5.1"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
"node_modules/jest-environment-node": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.4.1.tgz",
- "integrity": "sha512-4FZYVOk85hz2AyT6BbarKy9u37g6DbrDyCdFhsnDdXqyrueYQvB+0zO4f/kqLCRD0BsPRXPMNJeQwihKZV8naw==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.5.2.tgz",
+ "integrity": "sha512-Ciz4KgTGIbojxSKpuFImgWJj5EyqfE8xMq9NxWmOXnQywHHS03H9Mv+vaCB29J5pr3JBrY27WbRV18rBdjh8Dg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/environment": "30.4.1",
- "@jest/fake-timers": "30.4.1",
- "@jest/types": "30.4.1",
+ "@jest/environment": "30.5.2",
+ "@jest/fake-timers": "30.5.2",
+ "@jest/types": "30.5.1",
"@types/node": "*",
- "jest-mock": "30.4.1",
- "jest-util": "30.4.1",
- "jest-validate": "30.4.1"
+ "jest-mock": "30.5.2",
+ "jest-util": "30.5.1",
+ "jest-validate": "30.5.1"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
"node_modules/jest-haste-map": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.4.1.tgz",
- "integrity": "sha512-rFrcONd8jeFsyw+Z9CrScJgglRf2+NFmNam8dKu7n+SoHqNYT47mn0DdEcVUZJpvh7Iz6/si7f7yUH7GJHVgnw==",
+ "version": "30.5.1",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.5.1.tgz",
+ "integrity": "sha512-VIFgt67jW480YDxKfEv9IYQKrFpYt7bOCMn3VsnjK7AK9qo7p6acpnA1DHwsVOULE3dTaYew/6JaTD/d0VDHoQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/types": "30.4.1",
+ "@jest/types": "30.5.1",
+ "@parcel/watcher": "^2.6.0",
"@types/node": "*",
"anymatch": "^3.1.3",
"fb-watchman": "^2.0.2",
+ "fdir": "^6.5.0",
"graceful-fs": "^4.2.11",
- "jest-regex-util": "30.4.0",
- "jest-util": "30.4.1",
- "jest-worker": "30.4.1",
- "picomatch": "^4.0.3",
- "walker": "^1.0.8"
+ "jest-regex-util": "30.5.0",
+ "jest-util": "30.5.1",
+ "jest-worker": "30.5.1",
+ "picomatch": "^4.0.3"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "optionalDependencies": {
- "fsevents": "^2.3.3"
}
},
"node_modules/jest-leak-detector": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.4.1.tgz",
- "integrity": "sha512-IpmyiioeHxiWDhesHnUFmOxcTzwCwKpgACgWajtAP+nYQXiY7DakTxB6Bx9JFiRMljr0AX1PvnQdaU1KFoz6NQ==",
+ "version": "30.5.1",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.5.1.tgz",
+ "integrity": "sha512-gt4GT2aWgEoCNTcBe4rqS74xTIUJxi+UD9SNSu9aOk5LmTEd6fS5KSTmAKAfitCCktQHNN+upUuL6EkBfFbMDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/get-type": "30.1.0",
- "pretty-format": "30.4.1"
+ "@jest/get-type": "30.5.0",
+ "pretty-format": "30.5.1"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
"node_modules/jest-matcher-utils": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.4.1.tgz",
- "integrity": "sha512-zvYfX5CaeEkFrrLS9suWe9rvJrm9J1Iv3ua8kIBv9GEPzcnsfBf0bob37la7s67fs0nlBC3EuvkOLnXQKxtx4A==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.5.2.tgz",
+ "integrity": "sha512-lFkB365PTIHOhPzwrb9T6gvlDnPpOZ7/c3ewOKKB7bzztqjVrtlyRL2MkyfJXpyY2u2SKw001JKrTx14fBUFcQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/get-type": "30.1.0",
+ "@jest/get-type": "30.5.0",
"chalk": "^4.1.2",
- "jest-diff": "30.4.1",
- "pretty-format": "30.4.1"
+ "jest-diff": "30.5.2",
+ "pretty-format": "30.5.1"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
"node_modules/jest-message-util": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.4.1.tgz",
- "integrity": "sha512-kwCKIvq0MCW1HzLoGola9Te6JUdzgV0loyKJ3Qghrkz9i5/RRIHsL95BMQc2HBBhlBKC4j22K9p11TGHH8RBpQ==",
+ "version": "30.5.1",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.5.1.tgz",
+ "integrity": "sha512-UdQlLdd9wL/Ys7xRErckqwD6wPlSZYueosSWuHc1r2ztGLwlgPvtSJq2+BPEgaEY13WLvfFbmhTj8pba0Sd1jg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.27.1",
- "@jest/types": "30.4.1",
+ "@jest/types": "30.5.1",
"@types/stack-utils": "^2.0.3",
"chalk": "^4.1.2",
"graceful-fs": "^4.2.11",
- "jest-util": "30.4.1",
+ "jest-util": "30.5.1",
"picomatch": "^4.0.3",
- "pretty-format": "30.4.1",
+ "pretty-format": "30.5.1",
"slash": "^3.0.0",
"stack-utils": "^2.0.6"
},
@@ -4543,42 +4939,25 @@
}
},
"node_modules/jest-mock": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.4.1.tgz",
- "integrity": "sha512-/i8SVb8/NSB7RfNi8gfqu8gxLV23KaL5EpAttyb9iz8qWRIqXRLflycz/32wXsYkOnaUlx8NAKnJYtpsmXUmfw==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.5.2.tgz",
+ "integrity": "sha512-KTHb37Fhj8xY8qPFvTFaFJHcdsumQp+ExsUlgoX232Agmc706gagBs53+CYvulV7MVQo9AgXOUxsqzzVBoJlrA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/types": "30.4.1",
+ "@jest/expect-utils": "30.5.2",
+ "@jest/types": "30.5.1",
"@types/node": "*",
- "jest-util": "30.4.1"
+ "jest-util": "30.5.1"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/jest-pnp-resolver": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
- "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "peerDependencies": {
- "jest-resolve": "*"
- },
- "peerDependenciesMeta": {
- "jest-resolve": {
- "optional": true
- }
- }
- },
"node_modules/jest-regex-util": {
- "version": "30.4.0",
- "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.4.0.tgz",
- "integrity": "sha512-mWlvLviKIgIQ8VCuM1xRdD0TWp3zlzionlmDBjuXVBs+VkmXq6FgW9T4Emr7oGz/Rk6feDCGyiugolcQEyp3mg==",
+ "version": "30.5.0",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.5.0.tgz",
+ "integrity": "sha512-Mg0WK7A6xRHLSA1udJ8y9f3lM0uUhFTBnLKzwPmqB9AylvpleJ6BLemR8K9dK27DY+cesDryoA7yLZCAHsPG1A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -4586,100 +4965,100 @@
}
},
"node_modules/jest-resolve": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.4.1.tgz",
- "integrity": "sha512-Zry8Yq/yJcNAZ7dJ5F2heic8AheXvbFZ7XI5V+h28nrYZ7Qoyy4dItq8OodjnYD270mvX+ZudmrNV9cysqhW5Q==",
+ "version": "30.5.1",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.5.1.tgz",
+ "integrity": "sha512-wprhLejRtwN6h8ZgaqC0eYjGJ1uMdGPT/+b3eFncbG4NWuuP9QL+vWwRinu9waw7hkOLcpMJGVJAMgBwsPssMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"chalk": "^4.1.2",
"graceful-fs": "^4.2.11",
- "jest-haste-map": "30.4.1",
- "jest-pnp-resolver": "^1.2.3",
- "jest-util": "30.4.1",
- "jest-validate": "30.4.1",
+ "jest-haste-map": "30.5.1",
+ "jest-util": "30.5.1",
+ "jest-validate": "30.5.1",
"slash": "^3.0.0",
- "unrs-resolver": "^1.7.11"
+ "unrs-resolver": "^1.12.1"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
"node_modules/jest-resolve-dependencies": {
- "version": "30.4.2",
- "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.4.2.tgz",
- "integrity": "sha512-gDiVh1I+GxYzz9oXlyw+1wv6VOYX1WYxMOfjsA3iGKePV2oxmbHhwxfkALxNxYy1ciw6APWwkW2zZONwP97aEQ==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.5.2.tgz",
+ "integrity": "sha512-GMI0DP5enX9Z2qW2zFy1bOkrCfWAOPRJQ7qHt0pdfrxBPsgWxglMPrRSK2TX/wRWYxcPRSLFg3Z88qPOzHx7FQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "jest-regex-util": "30.4.0",
- "jest-snapshot": "30.4.1"
+ "jest-regex-util": "30.5.0",
+ "jest-snapshot": "30.5.2"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
"node_modules/jest-runner": {
- "version": "30.4.2",
- "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.4.2.tgz",
- "integrity": "sha512-2dw0PslVYXxffXGpLo+Ejad+KcI1Qkjn7f4X4619gf21oCUmL+SPfjqIa/losUem3yEOvfNZe/F1HWUcNpODcg==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.5.2.tgz",
+ "integrity": "sha512-/B6px7hiiNhVSRwuv9AGn0nawYvwsHeQZ3ItTd5Gp2diFd0EOKaWVeWqcbw3L88vx1GfpCKjQkxWItZCTl11Rw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/console": "30.4.1",
- "@jest/environment": "30.4.1",
- "@jest/test-result": "30.4.1",
- "@jest/transform": "30.4.1",
- "@jest/types": "30.4.1",
+ "@jest/console": "30.5.2",
+ "@jest/environment": "30.5.2",
+ "@jest/source-map": "30.5.2",
+ "@jest/test-result": "30.5.2",
+ "@jest/transform": "30.5.2",
+ "@jest/types": "30.5.1",
"@types/node": "*",
"chalk": "^4.1.2",
"emittery": "^0.13.1",
"exit-x": "^0.2.2",
"graceful-fs": "^4.2.11",
- "jest-docblock": "30.4.0",
- "jest-environment-node": "30.4.1",
- "jest-haste-map": "30.4.1",
- "jest-leak-detector": "30.4.1",
- "jest-message-util": "30.4.1",
- "jest-resolve": "30.4.1",
- "jest-runtime": "30.4.2",
- "jest-util": "30.4.1",
- "jest-watcher": "30.4.1",
- "jest-worker": "30.4.1",
- "p-limit": "^3.1.0",
- "source-map-support": "0.5.13"
+ "jest-docblock": "30.5.0",
+ "jest-environment-node": "30.5.2",
+ "jest-haste-map": "30.5.1",
+ "jest-leak-detector": "30.5.1",
+ "jest-message-util": "30.5.1",
+ "jest-resolve": "30.5.1",
+ "jest-runtime": "30.5.2",
+ "jest-util": "30.5.1",
+ "jest-watcher": "30.5.2",
+ "jest-worker": "30.5.1",
+ "p-limit": "^3.1.0"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
"node_modules/jest-runtime": {
- "version": "30.4.2",
- "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.4.2.tgz",
- "integrity": "sha512-3/5e8iPz2k/VLqlr8DgTftYyLUv8Su3FkCAO2/Od81UsUTpSxOrS6O5x5KkoQwyUjmpYyDJKeyAvg2T2nvpNkQ==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.5.2.tgz",
+ "integrity": "sha512-0paUAHBlheai10A3XSy9Xh+YBG0IROy+/qzcDPzQ/nbbXrznQzeWy5qniICWK6d3W3scaRQCVAbXdcK0ibBq4w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/environment": "30.4.1",
- "@jest/fake-timers": "30.4.1",
- "@jest/globals": "30.4.1",
- "@jest/source-map": "30.0.1",
- "@jest/test-result": "30.4.1",
- "@jest/transform": "30.4.1",
- "@jest/types": "30.4.1",
+ "@jest/environment": "30.5.2",
+ "@jest/fake-timers": "30.5.2",
+ "@jest/globals": "30.5.2",
+ "@jest/source-map": "30.5.2",
+ "@jest/test-result": "30.5.2",
+ "@jest/transform": "30.5.2",
+ "@jest/types": "30.5.1",
"@types/node": "*",
"chalk": "^4.1.2",
- "cjs-module-lexer": "^2.1.0",
+ "cjs-module-lexer": "^2.2.0",
"collect-v8-coverage": "^1.0.2",
- "glob": "^10.5.0",
+ "es-module-lexer": "^2.1.0",
+ "glob": "^13.0.6",
"graceful-fs": "^4.2.11",
- "jest-haste-map": "30.4.1",
- "jest-message-util": "30.4.1",
- "jest-mock": "30.4.1",
- "jest-regex-util": "30.4.0",
- "jest-resolve": "30.4.1",
- "jest-snapshot": "30.4.1",
- "jest-util": "30.4.1",
+ "jest-haste-map": "30.5.1",
+ "jest-message-util": "30.5.1",
+ "jest-mock": "30.5.2",
+ "jest-regex-util": "30.5.0",
+ "jest-resolve": "30.5.1",
+ "jest-snapshot": "30.5.2",
+ "jest-util": "30.5.1",
"slash": "^3.0.0",
"strip-bom": "^4.0.0"
},
@@ -4688,9 +5067,9 @@
}
},
"node_modules/jest-snapshot": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.4.1.tgz",
- "integrity": "sha512-tEOkkfOMppUyeiHwjZswOQ3lcnoTnws/q5FnGIaeIh/jmoU0ZlgMYRR8sTlTj+nNGCoJ0RDq6SfxGxCsyMTPmw==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.5.2.tgz",
+ "integrity": "sha512-jKIdes25AnAH73dOCi2qE6J6vHJ6L2vyBS11M89kT50DVJcLTf2AOjvcc+2vVaN8lUbY5v2R83aqXo3Ro9fqYA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4699,20 +5078,20 @@
"@babel/plugin-syntax-jsx": "^7.27.1",
"@babel/plugin-syntax-typescript": "^7.27.1",
"@babel/types": "^7.27.3",
- "@jest/expect-utils": "30.4.1",
- "@jest/get-type": "30.1.0",
- "@jest/snapshot-utils": "30.4.1",
- "@jest/transform": "30.4.1",
- "@jest/types": "30.4.1",
+ "@jest/expect-utils": "30.5.2",
+ "@jest/get-type": "30.5.0",
+ "@jest/snapshot-utils": "30.5.1",
+ "@jest/transform": "30.5.2",
+ "@jest/types": "30.5.1",
"babel-preset-current-node-syntax": "^1.2.0",
"chalk": "^4.1.2",
- "expect": "30.4.1",
+ "expect": "30.5.2",
"graceful-fs": "^4.2.11",
- "jest-diff": "30.4.1",
- "jest-matcher-utils": "30.4.1",
- "jest-message-util": "30.4.1",
- "jest-util": "30.4.1",
- "pretty-format": "30.4.1",
+ "jest-diff": "30.5.2",
+ "jest-matcher-utils": "30.5.2",
+ "jest-message-util": "30.5.1",
+ "jest-util": "30.5.1",
+ "pretty-format": "30.5.1",
"semver": "^7.7.2",
"synckit": "^0.11.8"
},
@@ -4721,13 +5100,13 @@
}
},
"node_modules/jest-util": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.4.1.tgz",
- "integrity": "sha512-vjQb1sACEiv13DKJMDToJpzVW0joCsIQrmbg0fi7CyOOt+g9jTuQl2A216pWRBYhOVt53XbL/2LbMKg1BECWOw==",
+ "version": "30.5.1",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.5.1.tgz",
+ "integrity": "sha512-yKuxmNy2rSbTXw+3SIPanJo+nV4/BS1p26v44IYBFMsswSQySfMMcPHErnOncda7i9HEz0q605rIhSTBVgrZTg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/types": "30.4.1",
+ "@jest/types": "30.5.1",
"@types/node": "*",
"chalk": "^4.1.2",
"ci-info": "^4.2.0",
@@ -4739,18 +5118,18 @@
}
},
"node_modules/jest-validate": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.4.1.tgz",
- "integrity": "sha512-PDWi4SOwLnwqNDfHZjOcsEFyZ4fc/2W2gVL3DEoyqnB6jCQMLRtfBong8s6omIw3lI0HWOus12xfnFmQtjW3fw==",
+ "version": "30.5.1",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.5.1.tgz",
+ "integrity": "sha512-i/buJ56wTpxihE93hQYNMfdOThS87+HGvLZzZJmU4xggPcdTYQq051iwALLCHp3q+SkCGH+EFejQZz5EbBSkkg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/get-type": "30.1.0",
- "@jest/types": "30.4.1",
+ "@jest/get-type": "30.5.0",
+ "@jest/types": "30.5.1",
"camelcase": "^6.3.0",
"chalk": "^4.1.2",
"leven": "^3.1.0",
- "pretty-format": "30.4.1"
+ "pretty-format": "30.5.1"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
@@ -4770,19 +5149,19 @@
}
},
"node_modules/jest-watcher": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.4.1.tgz",
- "integrity": "sha512-/l9UonmvCwjHH7d2h3iAwIloLc1H0S8mJZ/LNK3i86hqwPAz8otUJjP9MfYtz9Tt77Su5FD2xGjZn8d31IZHlw==",
+ "version": "30.5.2",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.5.2.tgz",
+ "integrity": "sha512-rqRgg4R11GA9m1UsEZwQeixHsgZReCn6TOHAHtIH33yXrIvoX0OGPA20Yzzjkz7X40fZvcRSxEpQppYPcWzmcQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/test-result": "30.4.1",
- "@jest/types": "30.4.1",
+ "@jest/test-result": "30.5.2",
+ "@jest/types": "30.5.1",
"@types/node": "*",
"ansi-escapes": "^4.3.2",
"chalk": "^4.1.2",
"emittery": "^0.13.1",
- "jest-util": "30.4.1",
+ "jest-util": "30.5.1",
"string-length": "^4.0.2"
},
"engines": {
@@ -4790,15 +5169,15 @@
}
},
"node_modules/jest-worker": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.4.1.tgz",
- "integrity": "sha512-SHynN/q/QD++iNyvMdy+WMmbCGk8jIsNcRxycXbWubSOhvo6T+j2afcfUSl+3hYsiBebOTo0cT7c2H7CXugu1g==",
+ "version": "30.5.1",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.5.1.tgz",
+ "integrity": "sha512-Cbxh5v7AoLuFRmFJSM4/aHdQ68rjXvUWr716EE0Dh3I7T+T/3FgFKhOERGXHcU2Meftq9+9zxPM3TSNyI9D+HA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*",
"@ungap/structured-clone": "^1.3.0",
- "jest-util": "30.4.1",
+ "jest-util": "30.5.1",
"merge-stream": "^2.0.0",
"supports-color": "^8.1.1"
},
@@ -4856,13 +5235,6 @@
"node": ">=6"
}
},
- "node_modules/json-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
- "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
@@ -4898,13 +5270,13 @@
}
},
"node_modules/keyv": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
- "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz",
+ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "json-buffer": "3.0.1"
+ "@keyv/serialize": "^1.1.1"
}
},
"node_modules/leven": {
@@ -4939,15 +5311,15 @@
"license": "MIT"
},
"node_modules/lint-staged": {
- "version": "17.3.0",
- "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-17.3.0.tgz",
- "integrity": "sha512-woZS3vNe3UKqBaLPvbLOtKRY4tLANpWQhom12MGWqC8Mh1lCOO+WgSwmX2amjJAqTY9BkXYW87fCUH5H9Ph6xw==",
+ "version": "17.5.1",
+ "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-17.5.1.tgz",
+ "integrity": "sha512-7EDuco1xnBMeVpvAbeMq1U5KXwJGLmY8q6l+Ye78r36C4mPc+Vg1Z2SK8gHyRTyvPro90A0q5/FAZ+Au23d6QQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "picomatch": "^4.0.5",
+ "picomatch": "^4.0.7",
"string-argv": "^0.3.2",
- "tinyexec": "^1.2.4"
+ "tinyexec": "^1.3.1"
},
"bin": {
"lint-staged": "bin/lint-staged.js"
@@ -5018,16 +5390,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/makeerror": {
- "version": "1.0.12",
- "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
- "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "tmpl": "1.0.5"
- }
- },
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -5116,6 +5478,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/node-addon-api": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
+ "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@@ -5328,9 +5697,9 @@
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
- "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
+ "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -5430,9 +5799,9 @@
}
},
"node_modules/prettier": {
- "version": "3.9.6",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz",
- "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==",
+ "version": "3.9.9",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.9.tgz",
+ "integrity": "sha512-Z/CJHIkdujO/OtN7nXUii0Rf3VT5SRuhjBA82Xvu2XhBUgX3nhP67T0LHceBdQLex7OOFGTox+Q5Yg8Jk2Qivg==",
"dev": true,
"license": "MIT",
"bin": {
@@ -5446,16 +5815,16 @@
}
},
"node_modules/pretty-format": {
- "version": "30.4.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.4.1.tgz",
- "integrity": "sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==",
+ "version": "30.5.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.5.1.tgz",
+ "integrity": "sha512-byhRAPguVKMQIj4kjJwJ5lAskVhfuiSdiYl/aLTWpgkGEmic2jYhJh1yE9ih8Ox44Xg9ccCT11/S6QrzSJuNrg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/schemas": "30.4.1",
- "ansi-styles": "^5.2.0",
- "react-is-18": "npm:react-is@^18.3.1",
- "react-is-19": "npm:react-is@^19.2.5"
+ "@jest/react-is-18": "npm:react-is@^18.3.1",
+ "@jest/react-is-19": "npm:react-is@^19.2.5",
+ "@jest/schemas": "30.5.0",
+ "ansi-styles": "^5.2.0"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
@@ -5501,19 +5870,23 @@
],
"license": "MIT"
},
- "node_modules/react-is-18": {
- "name": "react-is",
- "version": "18.3.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
- "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "node_modules/qified": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/qified/-/qified-0.10.1.tgz",
+ "integrity": "sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "dependencies": {
+ "hookified": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=20"
+ }
},
- "node_modules/react-is-19": {
- "name": "react-is",
- "version": "19.2.8",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.8.tgz",
- "integrity": "sha512-s5un28nYxKJw5gvUHyW5PCC28CvBqLu9r3cWgzHT4Vo/5fqqkFcdRYsGcKf50WMPpjjFZS5d76fn3YCo2njKwQ==",
+ "node_modules/qified/node_modules/hookified": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz",
+ "integrity": "sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==",
"dev": true,
"license": "MIT"
},
@@ -5628,17 +6001,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/source-map-support": {
- "version": "0.5.13",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
- "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.0"
- }
- },
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@@ -5828,9 +6190,9 @@
}
},
"node_modules/tinyexec": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz",
- "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.1.tgz",
+ "integrity": "sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -5854,13 +6216,6 @@
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
- "node_modules/tmpl": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
- "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
- "dev": true,
- "license": "BSD-3-Clause"
- },
"node_modules/ts-api-utils": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
@@ -5875,9 +6230,9 @@
}
},
"node_modules/ts-jest": {
- "version": "29.4.12",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.12.tgz",
- "integrity": "sha512-Ov6ClY53Fflh6BGAnY2DlTq1hYDrTycz2PVTXBWFW2CU+9zrEqAp9fWdGXl42EXO5RLSFAcAZ2JFKbP+zBTFfw==",
+ "version": "29.4.13",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.13.tgz",
+ "integrity": "sha512-rUQG+Ar95cNQf//KvsSjvabLpCTbwk+vKGWkAgiKFugqVwmOpGR7n7xa3S68/AB21Wn0KNhIAVxmxrUsz0L1AQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5898,7 +6253,7 @@
"node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0"
},
"peerDependencies": {
- "@babel/core": ">=7.0.0-beta.0 <8",
+ "@babel/core": ">=7.0.0-beta.0 <9",
"@jest/transform": "^29.0.0 || ^30.0.0",
"@jest/types": "^29.0.0 || ^30.0.0",
"babel-jest": "^29.0.0 || ^30.0.0",
@@ -5993,8 +6348,8 @@
},
"node_modules/typescript": {
"version": "6.0.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
- "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
+ "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/typescript/-/typescript-6.0.3.tgz",
+ "integrity": "sha1-kCUdwAeRbpcnhsuU100VsYVXfSE=",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -6020,18 +6375,18 @@
}
},
"node_modules/undici": {
- "version": "6.28.0",
- "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz",
- "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==",
+ "version": "6.29.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.29.0.tgz",
+ "integrity": "sha512-R+RODBqp6i2pPflGdq+xIOUkl+RNfGgHwoinecKu/JCuf2uO06cOKoDbI2P7Dn6KcswdKwrczbU6IYJ6K8X+wg==",
"license": "MIT",
"engines": {
"node": ">=18.17"
}
},
"node_modules/undici-types": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
- "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
+ "version": "8.9.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz",
+ "integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==",
"dev": true,
"license": "MIT"
},
@@ -6129,16 +6484,6 @@
"node": ">=10.12.0"
}
},
- "node_modules/walker": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
- "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "makeerror": "1.0.12"
- }
- },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
diff --git a/package.json b/package.json
index b6d0bc576..500787181 100644
--- a/package.json
+++ b/package.json
@@ -49,27 +49,27 @@
"@actions/http-client": "^4.0.1",
"@actions/io": "^3.0.2",
"@actions/tool-cache": "^4.0.0",
- "fast-xml-parser": "^5.11.0",
+ "fast-xml-parser": "^5.11.1",
"semver": "^7.8.5"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
- "@jest/globals": "^30.4.1",
- "@types/node": "^26.2.0",
+ "@jest/globals": "^30.5.2",
+ "@types/node": "^26.6.2",
"@types/semver": "^7.8.0",
- "@typescript-eslint/eslint-plugin": "^8.67.0",
+ "@typescript-eslint/eslint-plugin": "^8.70.1",
"@typescript-eslint/parser": "^8.65.0",
"@vercel/ncc": "^0.45.0",
- "eslint": "^10.8.1",
+ "eslint": "^10.11.0",
"eslint-config-prettier": "^10.1.8",
- "eslint-plugin-jest": "^29.16.1",
+ "eslint-plugin-jest": "^29.16.6",
"eslint-plugin-n": "^18.3.0",
- "globals": "^17.11.0",
+ "globals": "^17.12.0",
"husky": "^9.1.7",
- "jest": "^30.4.2",
- "lint-staged": "^17.3.0",
- "prettier": "^3.9.5",
- "ts-jest": "^29.4.11",
+ "jest": "^30.5.2",
+ "lint-staged": "^17.5.1",
+ "prettier": "^3.9.9",
+ "ts-jest": "^29.4.13",
"typescript": "^6.0.3"
},
"bugs": {
diff --git a/src/auth.ts b/src/auth.ts
index 3e20cb25b..91480f765 100644
--- a/src/auth.ts
+++ b/src/auth.ts
@@ -13,6 +13,7 @@ export interface MavenServerCredentials {
id: string;
usernameEnvVar: string;
passwordEnvVar: string;
+ repositoryOrigins?: string[];
}
export interface MavenRepository {
@@ -24,10 +25,13 @@ export interface MavenRepository {
export interface MavenRepositorySettings {
repositories: MavenRepository[];
+ pluginRepositories?: MavenRepository[];
includeCentral: boolean;
prioritizeCentral: boolean;
}
+const MAVEN_REPOSITORY_ORIGIN = /^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^/?#@]+\/?$/;
+
export async function configureAuthentication() {
const servers = getMavenServerSettings();
const repositorySettings = getMavenRepositorySettings();
@@ -95,25 +99,28 @@ export function getMavenServerSettings(): MavenServerCredentials[] {
constants.INPUT_MVN_SERVER_CREDENTIALS
);
- if (entries.some(entry => entry.trim())) {
- return parseMavenServerCredentials(entries);
- }
-
- return [
- {
- id: core.getInput(constants.INPUT_SERVER_ID),
- usernameEnvVar: getInputWithDeprecatedAlias(
- constants.INPUT_SERVER_USERNAME_ENV_VAR,
- constants.INPUT_SERVER_USERNAME_DEPRECATED,
- constants.INPUT_DEFAULT_SERVER_USERNAME
- ),
- passwordEnvVar: getInputWithDeprecatedAlias(
- constants.INPUT_SERVER_PASSWORD_ENV_VAR,
- constants.INPUT_SERVER_PASSWORD_DEPRECATED,
- constants.INPUT_DEFAULT_SERVER_PASSWORD
- )
- }
- ];
+ const servers = entries.some(entry => entry.trim())
+ ? parseMavenServerCredentials(entries)
+ : [
+ {
+ id: core.getInput(constants.INPUT_SERVER_ID),
+ usernameEnvVar: getInputWithDeprecatedAlias(
+ constants.INPUT_SERVER_USERNAME_ENV_VAR,
+ constants.INPUT_SERVER_USERNAME_DEPRECATED,
+ constants.INPUT_DEFAULT_SERVER_USERNAME
+ ),
+ passwordEnvVar: getInputWithDeprecatedAlias(
+ constants.INPUT_SERVER_PASSWORD_ENV_VAR,
+ constants.INPUT_SERVER_PASSWORD_DEPRECATED,
+ constants.INPUT_DEFAULT_SERVER_PASSWORD
+ )
+ }
+ ];
+
+ return addMavenServerRepositoryOrigins(
+ servers,
+ core.getMultilineInput(constants.INPUT_MVN_SERVER_REPOSITORY_ORIGINS)
+ );
}
// only exported for testing purposes
@@ -156,11 +163,96 @@ export function parseMavenServerCredentials(
return servers;
}
+// only exported for testing purposes
+export function addMavenServerRepositoryOrigins(
+ servers: MavenServerCredentials[],
+ entries: string[]
+): MavenServerCredentials[] {
+ const serverIds = new Set(servers.map(server => server.id));
+ const originsByServer = new Map();
+
+ entries.forEach((entry, index) => {
+ if (!entry.trim()) {
+ return;
+ }
+
+ const separator = entry.indexOf(':');
+ if (separator <= 0 || separator === entry.length - 1) {
+ throw new Error(
+ `Invalid mvn-server-repository-origins entry at line ${index + 1}. Expected format: server-id:repository-origin`
+ );
+ }
+
+ const id = entry.slice(0, separator).trim();
+ const value = entry.slice(separator + 1).trim();
+ if (!id || !value) {
+ throw new Error(
+ `Invalid mvn-server-repository-origins entry at line ${index + 1}. Server ID and repository origin are required`
+ );
+ }
+ if (!serverIds.has(id)) {
+ throw new Error(
+ `Unknown server-id '${id}' in mvn-server-repository-origins at line ${index + 1}`
+ );
+ }
+
+ let url: URL;
+ try {
+ if (!MAVEN_REPOSITORY_ORIGIN.test(value)) {
+ throw new Error();
+ }
+ url = new URL(value);
+ } catch {
+ throw new Error(
+ `Invalid repository origin '${value}' in mvn-server-repository-origins at line ${index + 1}`
+ );
+ }
+ if (
+ !url.host ||
+ url.username ||
+ url.password ||
+ (url.pathname !== '' && url.pathname !== '/') ||
+ url.search ||
+ url.hash
+ ) {
+ throw new Error(
+ `Invalid repository origin '${value}' in mvn-server-repository-origins at line ${index + 1}`
+ );
+ }
+
+ const explicitPort = /:(\d+)\/?$/.exec(value)?.[1];
+ const port = explicitPort ? Number.parseInt(explicitPort, 10) : undefined;
+ const includePort =
+ port !== undefined &&
+ !(
+ (url.protocol === 'http:' && port === 80) ||
+ (url.protocol === 'https:' && port === 443)
+ );
+ const origin = `${url.protocol}//${url.hostname}${includePort ? `:${port}` : ''}`;
+ const origins = originsByServer.get(id) || [];
+ if (!origins.includes(origin)) {
+ origins.push(origin);
+ originsByServer.set(id, origins);
+ }
+ });
+
+ return servers.map(server => {
+ const repositoryOrigins = originsByServer.get(server.id);
+ return repositoryOrigins ? {...server, repositoryOrigins} : server;
+ });
+}
+
// only exported for testing purposes
export function getMavenRepositorySettings():
MavenRepositorySettings | undefined {
const entries = core.getMultilineInput(constants.INPUT_MVN_REPOSITORIES);
- if (!entries.some(entry => entry.trim())) {
+ const pluginEntries = core.getMultilineInput(
+ constants.INPUT_MVN_PLUGIN_REPOSITORIES
+ );
+ if (
+ !entries.some(entry => entry.trim()) &&
+ !pluginEntries.some(entry => entry.trim())
+ ) {
return undefined;
}
@@ -170,6 +262,11 @@ export function getMavenRepositorySettings():
);
return {
repositories: parseMavenRepositories(entries, includeCentral),
+ pluginRepositories: parseMavenRepositories(
+ pluginEntries,
+ includeCentral,
+ constants.INPUT_MVN_PLUGIN_REPOSITORIES
+ ),
includeCentral,
prioritizeCentral: getBooleanInput(
constants.INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL,
@@ -181,7 +278,8 @@ export function getMavenRepositorySettings():
// only exported for testing purposes
export function parseMavenRepositories(
entries: string[],
- includeCentral: boolean
+ includeCentral: boolean,
+ inputName = constants.INPUT_MVN_REPOSITORIES
): MavenRepository[] {
const repositories: MavenRepository[] = [];
const repositoryIds = new Set();
@@ -195,7 +293,7 @@ export function parseMavenRepositories(
const lastSeparator = entry.lastIndexOf(':');
if (firstSeparator <= 0 || lastSeparator <= firstSeparator) {
throw new Error(
- `Invalid mvn-repositories entry at line ${index + 1}. Expected format: repository-id:repository-url:snapshots-enabled`
+ `Invalid ${inputName} entry at line ${index + 1}. Expected format: repository-id:repository-url:snapshots-enabled`
);
}
@@ -207,18 +305,16 @@ export function parseMavenRepositories(
.toLowerCase();
if (!id || !url || !snapshotsValue) {
throw new Error(
- `Invalid mvn-repositories entry at line ${index + 1}. repository-id, repository URL, and snapshots-enabled are required`
+ `Invalid ${inputName} entry at line ${index + 1}. repository-id, repository URL, and snapshots-enabled are required`
);
}
if (snapshotsValue !== 'true' && snapshotsValue !== 'false') {
throw new Error(
- `Invalid snapshots-enabled value '${snapshotsValue}' in mvn-repositories entry at line ${index + 1}. Expected true or false`
+ `Invalid snapshots-enabled value '${snapshotsValue}' in ${inputName} entry at line ${index + 1}. Expected true or false`
);
}
if (repositoryIds.has(id)) {
- throw new Error(
- `Duplicate repository-id '${id}' in mvn-repositories input`
- );
+ throw new Error(`Duplicate repository-id '${id}' in ${inputName} input`);
}
if (includeCentral && id === constants.MAVEN_CENTRAL_REPOSITORY_ID) {
throw new Error(
@@ -237,6 +333,56 @@ export function parseMavenRepositories(
return repositories;
}
+function generateRepositorySection(
+ customRepositories: MavenRepository[],
+ settings: MavenRepositorySettings,
+ element: 'repository' | 'pluginRepository'
+): string[] {
+ if (!customRepositories.length && settings.includeCentral) {
+ return [];
+ }
+
+ const centralRepository: MavenRepository = {
+ id: constants.MAVEN_CENTRAL_REPOSITORY_ID,
+ url: constants.MAVEN_CENTRAL_REPOSITORY_URL,
+ snapshotsEnabled: false
+ };
+ const customCentralConfigured = customRepositories.some(
+ repository => repository.id === constants.MAVEN_CENTRAL_REPOSITORY_ID
+ );
+ const repositories = settings.includeCentral
+ ? settings.prioritizeCentral
+ ? [centralRepository, ...customRepositories]
+ : [...customRepositories, centralRepository]
+ : customCentralConfigured
+ ? customRepositories
+ : [...customRepositories, {...centralRepository, releasesEnabled: false}];
+ const container =
+ element === 'repository' ? 'repositories' : 'pluginRepositories';
+ const lines = [` <${container}>`];
+
+ for (const repository of repositories) {
+ lines.push(
+ ` <${element}>`,
+ ` ${escapeXmlText(repository.id)}`,
+ ` ${escapeXmlText(repository.url)}`,
+ ...(repository.releasesEnabled === undefined
+ ? []
+ : [
+ ' ',
+ ` ${repository.releasesEnabled}`,
+ ' '
+ ]),
+ ' ',
+ ` ${repository.snapshotsEnabled}`,
+ ' ',
+ ` ${element}>`
+ );
+ }
+ lines.push(` ${container}>`);
+ return lines;
+}
+
export async function createAuthenticationSettings(
servers: MavenServerCredentials[],
settingsDirectory: string,
@@ -286,58 +432,39 @@ export function generate(
' ',
` ${escapeXmlText(server.id)}`,
` ${escapeXmlText(`\${env.${server.usernameEnvVar}}`)}`,
- ` ${escapeXmlText(`\${env.${server.passwordEnvVar}}`)}`,
- ' '
+ ` ${escapeXmlText(`\${env.${server.passwordEnvVar}}`)}`
);
+ if (server.repositoryOrigins) {
+ lines.push(' ');
+ for (const origin of server.repositoryOrigins) {
+ lines.push(
+ ` ${escapeXmlText(origin)}`
+ );
+ }
+ lines.push(' ');
+ }
+ lines.push(' ');
}
lines.push(' ');
if (repositorySettings || includeGpgPassphraseProfile) {
lines.push(' ');
if (repositorySettings) {
- const centralRepository: MavenRepository = {
- id: constants.MAVEN_CENTRAL_REPOSITORY_ID,
- url: constants.MAVEN_CENTRAL_REPOSITORY_URL,
- snapshotsEnabled: false
- };
- const customCentralConfigured = repositorySettings.repositories.some(
- repository => repository.id === constants.MAVEN_CENTRAL_REPOSITORY_ID
- );
- const repositories = repositorySettings.includeCentral
- ? repositorySettings.prioritizeCentral
- ? [centralRepository, ...repositorySettings.repositories]
- : [...repositorySettings.repositories, centralRepository]
- : customCentralConfigured
- ? repositorySettings.repositories
- : [
- ...repositorySettings.repositories,
- {...centralRepository, releasesEnabled: false}
- ];
-
lines.push(
' ',
` ${constants.MAVEN_REPOSITORIES_PROFILE_ID}`,
- ' '
+ ...generateRepositorySection(
+ repositorySettings.repositories,
+ repositorySettings,
+ 'repository'
+ ),
+ ...generateRepositorySection(
+ repositorySettings.pluginRepositories ?? [],
+ repositorySettings,
+ 'pluginRepository'
+ ),
+ ' '
);
- for (const repository of repositories) {
- lines.push(
- ' ',
- ` ${escapeXmlText(repository.id)}`,
- ` ${escapeXmlText(repository.url)}`,
- ...(repository.releasesEnabled === undefined
- ? []
- : [
- ' ',
- ` ${repository.releasesEnabled}`,
- ' '
- ]),
- ' ',
- ` ${repository.snapshotsEnabled}`,
- ' ',
- ' '
- );
- }
- lines.push(' ', ' ');
}
if (includeGpgPassphraseProfile) {
lines.push(
diff --git a/src/constants.ts b/src/constants.ts
index 9404e188d..bdba92242 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -16,7 +16,10 @@ export const SIGNATURE_VERIFICATION_DOCUMENTATION_URL =
'https://github.com/actions/setup-java#download-integrity-and-signatures';
export const SIGNATURE_VERIFICATION_FAILURE_HELP = `If this is a legitimate vendor signing-key rotation, see ${SIGNATURE_VERIFICATION_DOCUMENTATION_URL} for instructions to configure the updated public key or temporarily disable signature verification.`;
export const INPUT_MVN_SERVER_CREDENTIALS = 'mvn-server-credentials';
+export const INPUT_MVN_SERVER_REPOSITORY_ORIGINS =
+ 'mvn-server-repository-origins';
export const INPUT_MVN_REPOSITORIES = 'mvn-repositories';
+export const INPUT_MVN_PLUGIN_REPOSITORIES = 'mvn-plugin-repositories';
export const INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL =
'mvn-repositories-include-central';
export const INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL =
diff --git a/src/distributions/base-installer.ts b/src/distributions/base-installer.ts
index f2d0c1414..32c7455c1 100644
--- a/src/distributions/base-installer.ts
+++ b/src/distributions/base-installer.ts
@@ -5,9 +5,9 @@ import semver from 'semver';
import path from 'path';
import * as httpm from '@actions/http-client';
import {
- convertVersionToSemver,
getToolcachePath,
- isVersionSatisfies
+ isVersionSatisfies,
+ normalizeJavaVersionToSemver
} from '../util.js';
import type {
ChecksumAlgorithm,
@@ -675,12 +675,9 @@ export abstract class JavaBase {
// Java uses a versioning scheme (JEP 322) that can contain more numeric
// fields than SemVer allows, e.g. '18.0.1.1' or '11.0.9.1'. Convert such
- // exact versions to SemVer build notation ('18.0.1+1') so they are
- // accepted. Ranges and versions that already carry build metadata are
- // left untouched.
- if (/^\d+(\.\d+){3,}$/.test(version)) {
- version = convertVersionToSemver(version);
- }
+ // exact versions to SemVer build notation ('18.0.1+1', or '26.0.2+1.1'
+ // for '26.0.2.1+1') so they are accepted. Ranges are left untouched.
+ version = normalizeJavaVersionToSemver(version);
if (!semver.validRange(version)) {
throw new Error(
diff --git a/src/distributions/liberica/installer.ts b/src/distributions/liberica/installer.ts
index 27a09f3e7..b4320d66a 100644
--- a/src/distributions/liberica/installer.ts
+++ b/src/distributions/liberica/installer.ts
@@ -166,8 +166,8 @@ export class LibericaDistributions extends JavaBase {
}
private convertVersionToSemver(version: LibericaVersion): string {
- const {buildVersion, featureVersion, interimVersion, updateVersion} =
- version;
+ const {featureVersion, interimVersion, updateVersion} = version;
+ const buildVersion = version.version.split('+')[1] || version.buildVersion;
const mainVersion = [featureVersion, interimVersion, updateVersion].join(
'.'
);
diff --git a/src/distributions/package-types.ts b/src/distributions/package-types.ts
index 9b0d23bd6..81ab37849 100644
--- a/src/distributions/package-types.ts
+++ b/src/distributions/package-types.ts
@@ -1,5 +1,5 @@
import semver from 'semver';
-import {convertVersionToSemver} from '../util.js';
+import {normalizeJavaVersionToSemver} from '../util.js';
export enum JavaDistribution {
Temurin = 'temurin',
@@ -98,12 +98,9 @@ function canResolveTemurinJmods(version: string): boolean {
return true;
}
- let normalizedRange = normalizedVersion
- .replace(/-ea$/, '')
- .replace('-ea.', '+');
- if (/^\d+(\.\d+){3,}$/.test(normalizedRange)) {
- normalizedRange = convertVersionToSemver(normalizedRange);
- }
+ const normalizedRange = normalizeJavaVersionToSemver(
+ normalizedVersion.replace(/-ea$/, '').replace('-ea.', '+')
+ );
if (!semver.validRange(normalizedRange)) {
// JavaBase owns general version validation and its targeted error messages.
return true;
diff --git a/src/distributions/platform-types.ts b/src/distributions/platform-types.ts
index a48b4595e..5e65c7262 100644
--- a/src/distributions/platform-types.ts
+++ b/src/distributions/platform-types.ts
@@ -5,7 +5,14 @@ import {JavaDistribution} from './package-types.js';
export type JavaPlatform = 'linux' | 'macos' | 'windows' | 'solaris';
export type JavaArchitecture =
- 'x86' | 'x64' | 'armv7' | 'aarch64' | 'ppc64le' | 'ppc64' | 's390x';
+ | 'x86'
+ | 'x64'
+ | 'armv7'
+ | 'aarch64'
+ | 'ppc64le'
+ | 'ppc64'
+ | 'riscv64'
+ | 's390x';
interface VersionedArchitecture {
architecture: JavaArchitecture;
@@ -27,7 +34,14 @@ export type JavaPlatformCapability =
RestrictedPlatformCapability | UnrestrictedPlatformCapability;
const X64_ARM64 = ['x64', 'aarch64'] as const;
-const STANDARD_LINUX = ['x64', 'x86', 'aarch64', 'ppc64le', 's390x'] as const;
+const STANDARD_LINUX = [
+ 'x64',
+ 'x86',
+ 'aarch64',
+ 'ppc64le',
+ 'riscv64',
+ 's390x'
+] as const;
export const JAVA_PLATFORM_CAPABILITIES: Record<
JavaDistribution,
@@ -174,6 +188,7 @@ const CANONICAL_ARCHITECTURES: readonly JavaArchitecture[] = [
'aarch64',
'ppc64le',
'ppc64',
+ 'riscv64',
's390x'
];
diff --git a/src/distributions/temurin/installer.ts b/src/distributions/temurin/installer.ts
index e01535e91..2b81d7725 100644
--- a/src/distributions/temurin/installer.ts
+++ b/src/distributions/temurin/installer.ts
@@ -70,7 +70,7 @@ export class TemurinDistribution extends JavaBase {
const formattedVersion = this.stable
? item.version_data.semver
: item.version_data.semver.replace('-beta+', '+');
- return {
+ const release: JavaDownloadRelease = {
version: formattedVersion,
url: item.binaries[0].package.link,
signatureUrl: item.binaries[0].package.signature_link,
@@ -79,11 +79,29 @@ export class TemurinDistribution extends JavaBase {
value: item.binaries[0].package.checksum,
source: item.binaries[0].package.checksum_link
}
- } as JavaDownloadRelease;
+ };
+ return {
+ release,
+ openjdkVersion: getOpenJdkSemverVersion(item.version_data)
+ };
});
+ // The Adoptium API `semver` folds the JEP 322 patch field into the build
+ // number ('26.0.2.1+1' -> '26.0.2+101') and appends extra metadata for LTS
+ // releases ('25.0.4+7' -> '25.0.4+7.0.LTS'). Exact versions requested by
+ // users follow the OpenJDK notation instead, so also match them against a
+ // key derived from the OpenJDK version fields ('26.0.2+1.1', '25.0.4+7').
+ const isExactBuildRequest = (semver.parse(version)?.build.length ?? 0) > 0;
+
const satisfiedVersions = availableVersionsWithBinaries
- .filter(item => isVersionSatisfies(version, item.version))
+ .filter(
+ ({release, openjdkVersion}) =>
+ isVersionSatisfies(version, release.version) ||
+ (isExactBuildRequest &&
+ openjdkVersion !== null &&
+ semver.compareBuild(version, openjdkVersion) === 0)
+ )
+ .map(({release}) => release)
.sort((a, b) => {
return -semver.compareBuild(a.version, b.version);
});
@@ -92,7 +110,7 @@ export class TemurinDistribution extends JavaBase {
satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
if (!resolvedFullVersion) {
const availableVersionStrings = availableVersionsWithBinaries.map(
- item => item.version
+ ({release}) => release.version
);
throw this.createVersionNotFoundError(version, availableVersionStrings);
}
@@ -309,3 +327,20 @@ export class TemurinDistribution extends JavaBase {
return architecture === 'armv7' ? 'arm' : architecture;
}
}
+
+/**
+ * Builds a SemVer version from the OpenJDK version fields reported by the
+ * Adoptium API, e.g. '26.0.2.1+1' -> '26.0.2+1.1' and '25.0.4+7-LTS' ->
+ * '25.0.4+7'. Returns null if the fields cannot form a valid SemVer version.
+ */
+function getOpenJdkSemverVersion(
+ versionData: ITemurinAvailableVersions['version_data']
+): string | null {
+ const {major, minor, security, patch, build} = versionData;
+ if (build === undefined || build === null) {
+ return null;
+ }
+ const buildMetadata = patch ? `${patch}.${build}` : `${build}`;
+ const version = `${major}.${minor}.${security}+${buildMetadata}`;
+ return semver.valid(version) ? version : null;
+}
diff --git a/src/distributions/temurin/models.ts b/src/distributions/temurin/models.ts
index c5bff9020..443d3bb25 100644
--- a/src/distributions/temurin/models.ts
+++ b/src/distributions/temurin/models.ts
@@ -34,6 +34,7 @@ export interface ITemurinAvailableVersions {
minor: number;
openjdk_version: string;
security: string;
+ patch?: number;
semver: string;
};
}
diff --git a/src/distributions/zulu/installer.ts b/src/distributions/zulu/installer.ts
index 2c05567c8..0107dd249 100644
--- a/src/distributions/zulu/installer.ts
+++ b/src/distributions/zulu/installer.ts
@@ -2,7 +2,6 @@ import * as core from '@actions/core';
import path from 'path';
import fs from 'fs';
-import semver from 'semver';
import {JavaBase} from '../base-installer.js';
import {IZuluPackageDetails, IZuluVersions} from './models.js';
@@ -30,6 +29,17 @@ interface ZuluResolvedRelease {
packageUuid: string;
}
+function compareNumberArrays(a: number[], b: number[]): number {
+ const length = Math.max(a.length, b.length);
+ for (let i = 0; i < length; i++) {
+ const diff = (a[i] ?? 0) - (b[i] ?? 0);
+ if (diff !== 0) {
+ return diff;
+ }
+ }
+ return 0;
+}
+
export class ZuluDistribution extends JavaBase {
constructor(installerOptions: JavaInstallerOptions) {
super('Zulu', installerOptions);
@@ -50,7 +60,9 @@ export class ZuluDistribution extends JavaBase {
return {
version: convertVersionToSemver(javaVersion),
url: item.download_url,
- zuluVersion: convertVersionToSemver(item.distro_version),
+ javaVersion: item.java_version,
+ buildNumber: item.openjdk_build_number ?? 0,
+ distroVersion: item.distro_version,
packageUuid: item.package_uuid
};
});
@@ -58,11 +70,14 @@ export class ZuluDistribution extends JavaBase {
const satisfiedVersions = availableVersions
.filter(item => isVersionSatisfies(version, item.version))
.sort((a, b) => {
- // Azul provides two versions: java_version and distro_version
- // we should sort by both fields by descending
+ // Compare numerically rather than via semver build metadata: Azul
+ // hotfix releases carry a 4th java_version segment (e.g. 25.0.4.1+1,
+ // rendered as '25.0.4+1.1') that must rank above 25.0.4+7, whereas
+ // semver.compareBuild would order the build identifiers '7' > '1'.
return (
- -semver.compareBuild(a.version, b.version) ||
- -semver.compareBuild(a.zuluVersion, b.zuluVersion)
+ -compareNumberArrays(a.javaVersion, b.javaVersion) ||
+ b.buildNumber - a.buildNumber ||
+ -compareNumberArrays(a.distroVersion, b.distroVersion)
);
})
.map((item): ZuluResolvedRelease => ({
diff --git a/src/gpg.ts b/src/gpg.ts
index b522d126c..4ea4044d7 100644
--- a/src/gpg.ts
+++ b/src/gpg.ts
@@ -89,17 +89,20 @@ export async function removeGpgHome(gpgHome: string): Promise {
return;
}
+ await stopGpgAgent(resolvedGpgHome);
+ await io.rmRF(resolvedGpgHome);
+}
+
+async function stopGpgAgent(gpgHome: string): Promise {
try {
await exec.exec(
'gpgconf',
- ['--homedir', toGpgPath(resolvedGpgHome), '--kill', 'gpg-agent'],
+ ['--homedir', toGpgPath(gpgHome), '--kill', 'gpg-agent'],
{silent: true, ignoreReturnCode: true}
);
} catch {
// gpgconf may be unavailable, but directory removal must still be attempted.
}
-
- await io.rmRF(resolvedGpgHome);
}
export async function verifyPackageSignature(
@@ -160,6 +163,7 @@ export async function verifyPackageSignature(
options
);
} finally {
+ await stopGpgAgent(gpgHome);
await io.rmRF(signaturePath);
await io.rmRF(gpgHome);
}
diff --git a/src/util.ts b/src/util.ts
index e2583849d..b71a73629 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -510,6 +510,21 @@ export function convertVersionToSemver(version: number[] | string) {
return mainVersion;
}
+/**
+ * Java versions (JEP 322) can contain more numeric fields than SemVer allows,
+ * e.g. '11.0.9.1' or Temurin respins such as '26.0.2.1+1'. Move the extra
+ * fields into SemVer build metadata ('11.0.9+1', '26.0.2+1.1'). Any other
+ * input (ranges, regular SemVer versions) is returned unchanged.
+ */
+export function normalizeJavaVersionToSemver(version: string): string {
+ const match = /^(\d+(?:\.\d+){3,})(?:\+([0-9A-Za-z.-]+))?$/.exec(version);
+ if (!match) {
+ return version;
+ }
+ const converted = convertVersionToSemver(match[1]);
+ return match[2] ? `${converted}.${match[2]}` : converted;
+}
+
/**
* Builds a validator for the bytes currently served by a URL from the response
* headers of a HEAD request. A vendor's `/latest/` URL never changes, so this