Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLeitwolf112026-09-26 16:57:36 +0300
committerLeitwolf112026-09-26 16:57:36 +0300
commit07b91c2966ffe5daa9501f41436b3a45b3a2d774 (patch)
tree4a8771a38cbd7bc61735c3ae59b8b440f03d0d42
parent1855533fa44547e568471303530c67e5d2fa69c5 (diff)
downloadprogmaweb-07b91c2966ffe5daa9501f41436b3a45b3a2d774.tar.gz
Add Progmaweb frontend tests and full-stack security and coverage workflows
-rw-r--r--.codacy.yml11
-rw-r--r--.github/codeql/codeql-config.yml10
-rw-r--r--.github/dependabot.yml20
-rw-r--r--.github/pull_request_template.md25
-rw-r--r--.github/workflows/backend.yml9
-rw-r--r--.github/workflows/codeql.yml50
-rw-r--r--.github/workflows/frontend.yml8
-rw-r--r--.gitignore1
-rw-r--r--README.md7
-rw-r--r--apps/api-tests/Progmaweb.Api.Tests.csproj1
-rw-r--r--apps/api-tests/packages.lock.json11
-rw-r--r--apps/api/packages.lock.json2
-rw-r--r--apps/web/package.json3
-rw-r--r--apps/web/tests/localization.test.mjs62
-rw-r--r--package.json2
-rw-r--r--pnpm-lock.yaml255
16 files changed, 475 insertions, 2 deletions
diff --git a/.codacy.yml b/.codacy.yml
new file mode 100644
index 0000000..52ecd91
--- /dev/null
+++ b/.codacy.yml
@@ -0,0 +1,11 @@
+---
+# SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com>
+# SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1
+
+exclude_paths:
+ - '**/node_modules/**'
+ - '**/.next/**'
+ - '**/bin/**'
+ - '**/obj/**'
+ - 'coverage/**'
+
diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml
new file mode 100644
index 0000000..e4b5b8d
--- /dev/null
+++ b/.github/codeql/codeql-config.yml
@@ -0,0 +1,10 @@
+# SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com>
+# SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1
+
+name: Progmaweb owned sources
+paths-ignore:
+ - apps/web/.next
+ - apps/web/node_modules
+ - '**/bin'
+ - '**/obj'
+
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..647cf0e
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,20 @@
+# SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com>
+# SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1
+
+version: 2
+updates:
+ - package-ecosystem: github-actions
+ directory: /
+ schedule:
+ interval: weekly
+ - package-ecosystem: npm
+ directory: /
+ schedule:
+ interval: weekly
+ - package-ecosystem: nuget
+ directories:
+ - /apps/api
+ - /apps/api-tests
+ schedule:
+ interval: weekly
+
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000..f4d6812
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,25 @@
+<!--
+SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com>
+SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1
+-->
+
+## User-facing change
+
+Describe the Progmasoft, account, or ViGet behavior changed. State whether a deployed route or persistent account data
+is affected.
+
+## Verification
+
+- [ ] Next.js check, frontend tests, lint, and build were run where relevant.
+- [ ] ASP.NET Core build and API tests were run where relevant.
+- [ ] en-US/de-DE, light/dark, accessibility, and small-screen behavior were considered for UI changes.
+- [ ] Auth, session, publisher identity, registry paths, and deployment compatibility were reviewed if affected.
+- [ ] No credentials, generated output, or unrelated files are included.
+
+Commands and results (including anything not run):
+
+```text
+
+```
+
+Screenshots or recordings for visual changes:
diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml
index e534f44..0aa2c83 100644
--- a/.github/workflows/backend.yml
+++ b/.github/workflows/backend.yml
@@ -23,6 +23,7 @@ on:
permissions:
contents: read
+ id-token: write
concurrency:
group: backend-${{ github.ref }}
@@ -41,4 +42,10 @@ jobs:
cache-dependency-path: "**/*.csproj"
- run: dotnet restore Progmaweb.slnx --locked-mode
- run: dotnet build Progmaweb.slnx --configuration Release --no-restore
- - run: dotnet test --project apps/api-tests/Progmaweb.Api.Tests.csproj --configuration Release --no-build
+ - run: dotnet test --project apps/api-tests/Progmaweb.Api.Tests.csproj --configuration Release --no-build --coverlet --coverlet-output-format cobertura
+ - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
+ with:
+ use_oidc: true
+ files: TestResults/coverage.cobertura.xml
+ flags: progmaweb-backend
+ fail_ci_if_error: true
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 0000000..1f6db33
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,50 @@
+# SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com>
+# SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1
+
+name: CodeQL
+on:
+ push:
+ branches: [main]
+ pull_request:
+ schedule:
+ - cron: '37 4 * * 1'
+permissions:
+ actions: read
+ contents: read
+ security-events: write
+jobs:
+ analyze:
+ name: ${{ matrix.language }}
+ runs-on: ubuntu-latest
+ timeout-minutes: 45
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - language: actions
+ build_mode: none
+ - language: javascript-typescript
+ build_mode: none
+ - language: csharp
+ build_mode: manual
+ steps:
+ - uses: actions/checkout@v7
+ - uses: actions/setup-dotnet@v5
+ if: matrix.language == 'csharp'
+ with:
+ dotnet-version: 10.0.x
+ - uses: github/codeql-action/init@7999b86c43a865dc79d8923397f35af22de63401 # v4
+ with:
+ languages: ${{ matrix.language }}
+ build-mode: ${{ matrix.build_mode }}
+ config-file: ./.github/codeql/codeql-config.yml
+ queries: security-extended
+ - name: Build ASP.NET Core for extraction
+ if: matrix.language == 'csharp'
+ run: |
+ dotnet restore Progmaweb.slnx --locked-mode
+ dotnet build Progmaweb.slnx --configuration Release --no-restore
+ - uses: github/codeql-action/analyze@7999b86c43a865dc79d8923397f35af22de63401 # v4
+ with:
+ category: /language:${{ matrix.language }}
+
diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml
index cdbdb0a..87e17da 100644
--- a/.github/workflows/frontend.yml
+++ b/.github/workflows/frontend.yml
@@ -23,6 +23,7 @@ on:
permissions:
contents: read
+ id-token: write
concurrency:
group: frontend-${{ github.ref }}
@@ -44,5 +45,12 @@ jobs:
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm check
+ - run: pnpm test:coverage
- run: pnpm lint
- run: pnpm build
+ - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
+ with:
+ use_oidc: true
+ files: apps/web/coverage/lcov.info
+ flags: progmaweb-frontend
+ fail_ci_if_error: true
diff --git a/.gitignore b/.gitignore
index 9feeddb..641c3ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ node_modules/
.next/
out/
coverage/
+TestResults/
dist/
bin/
obj/
diff --git a/README.md b/README.md
index d8075ab..339dc8a 100644
--- a/README.md
+++ b/README.md
@@ -71,11 +71,18 @@ downloaded Google client JSON.
```text
pnpm check
+pnpm test
+pnpm test:coverage
pnpm build
dotnet build apps/api/Progmaweb.Api.csproj --configuration Release
dotnet test --project apps/api-tests/Progmaweb.Api.Tests.csproj --configuration Release
+dotnet test --project apps/api-tests/Progmaweb.Api.Tests.csproj --configuration Release --coverlet --coverlet-output-format cobertura
```
+Frontend tests exercise the published locale contract and account/ViGet metadata without starting a production service.
+The frontend LCOV and API Cobertura reports are uploaded to Codecov as separate components in CI. CodeQL and Codacy
+provide static analysis; Dependabot proposes dependency updates without merging them automatically.
+
## License
Progmaweb project-owned source code is licensed under `AGPL-3.0-or-later`, matching the Visual X# website, with the
diff --git a/apps/api-tests/Progmaweb.Api.Tests.csproj b/apps/api-tests/Progmaweb.Api.Tests.csproj
index 63b5f6c..efb6a2f 100644
--- a/apps/api-tests/Progmaweb.Api.Tests.csproj
+++ b/apps/api-tests/Progmaweb.Api.Tests.csproj
@@ -11,6 +11,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.11" />
+ <PackageReference Include="coverlet.MTP" Version="8.0.0" />
<!-- xUnit's MTP-v2 package is the native .NET 10 test host. Keeping the
VSTest adapter here would make the solution mix incompatible runners. -->
<PackageReference Include="xunit.v3.mtp-v2" Version="4.0.0" />
diff --git a/apps/api-tests/packages.lock.json b/apps/api-tests/packages.lock.json
index 38c06e7..ca4dbb9 100644
--- a/apps/api-tests/packages.lock.json
+++ b/apps/api-tests/packages.lock.json
@@ -2,6 +2,17 @@
"version": 1,
"dependencies": {
"net10.0": {
+ "coverlet.MTP": {
+ "type": "Direct",
+ "requested": "[8.0.0, )",
+ "resolved": "8.0.0",
+ "contentHash": "r3+GPhzJd8G/qlw8UFOYGECZSFvpg0j+yRTGbSr8ikk1ed4Hui+Y56ghPcBT43S3DWYKEzZLGmZ/KFS28k1zHg==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.1",
+ "Microsoft.Extensions.DependencyInjection": "8.0.1",
+ "Microsoft.Testing.Platform": "2.0.2"
+ }
+ },
"Microsoft.AspNetCore.Mvc.Testing": {
"type": "Direct",
"requested": "[10.0.11, )",
diff --git a/apps/api/packages.lock.json b/apps/api/packages.lock.json
index d134eda..b7d7ff4 100644
--- a/apps/api/packages.lock.json
+++ b/apps/api/packages.lock.json
@@ -10,4 +10,4 @@
}
}
}
-}
+} \ No newline at end of file
diff --git a/apps/web/package.json b/apps/web/package.json
index ba3bcf5..fef38d7 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -12,6 +12,8 @@
"build": "next build",
"start": "next start",
"check": "next typegen && tsc --noEmit",
+ "test": "node --experimental-strip-types --test tests/*.test.mjs",
+ "test:coverage": "c8 --reporter=lcov --reporter=text npm test",
"lint": "eslint . --max-warnings=0",
"format": "prettier --write ."
},
@@ -21,6 +23,7 @@
"react-dom": "19.2.8"
},
"devDependencies": {
+ "c8": "12.0.0",
"@types/node": "24.10.1",
"@types/react": "19.2.14",
"@types/react-dom": "19.2.3",
diff --git a/apps/web/tests/localization.test.mjs b/apps/web/tests/localization.test.mjs
new file mode 100644
index 0000000..3d499ed
--- /dev/null
+++ b/apps/web/tests/localization.test.mjs
@@ -0,0 +1,62 @@
+// SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com>
+// SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1
+
+import assert from "node:assert/strict";
+import { test } from "node:test";
+import {
+ getMessages,
+ isLocale,
+ messages,
+ supportedLocales,
+} from "../lib/localization.ts";
+
+test("only the two published locales are accepted", () => {
+ assert.deepEqual(supportedLocales, ["en-US", "de-DE"]);
+ assert.equal(isLocale("en-US"), true);
+ assert.equal(isLocale("de-DE"), true);
+ for (const value of ["en", "de", "en-us", "tr-TR", "", undefined]) {
+ assert.equal(isLocale(value), false, `unexpected locale: ${value}`);
+ }
+});
+
+test("both locales give the account and ViGet routes distinct page metadata", () => {
+ const english = messages["en-US"].metadata;
+ const german = messages["de-DE"].metadata;
+ for (const key of [
+ "homeTitle",
+ "accountTitle",
+ "loginTitle",
+ "registerTitle",
+ "vigetTitle",
+ "dslPluginsTitle",
+ ]) {
+ assert.equal(typeof english[key], "string");
+ assert.equal(typeof german[key], "string");
+ assert.notEqual(english[key].trim(), "");
+ assert.notEqual(german[key].trim(), "");
+ }
+ assert.notEqual(english.loginTitle, german.loginTitle);
+ assert.notEqual(english.registerTitle, german.registerTitle);
+ assert.match(english.vigetTitle, /ViGet/);
+ assert.match(german.vigetTitle, /ViGet/);
+});
+
+test("each supported locale resolves to its own complete message tree", () => {
+ for (const locale of supportedLocales) {
+ assert.strictEqual(getMessages(locale), messages[locale]);
+ }
+
+ function shape(value) {
+ if (Array.isArray(value)) return value.map(shape);
+ if (value !== null && typeof value === "object") {
+ return Object.fromEntries(
+ Object.entries(value).map(([key, child]) => [key, shape(child)]),
+ );
+ }
+ assert.equal(typeof value, "string");
+ assert.notEqual(value.trim(), "");
+ return "text";
+ }
+
+ assert.deepEqual(shape(messages["de-DE"]), shape(messages["en-US"]));
+});
diff --git a/package.json b/package.json
index 4c409f8..003afee 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,8 @@
"dev": "pnpm --filter @progmasoft/web dev",
"build": "pnpm --filter @progmasoft/web build",
"check": "pnpm --filter @progmasoft/web check",
+ "test": "pnpm --filter @progmasoft/web test",
+ "test:coverage": "pnpm --filter @progmasoft/web test:coverage",
"lint": "pnpm --filter @progmasoft/web lint",
"format": "pnpm --filter @progmasoft/web format"
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 06db313..9e6edee 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -29,6 +29,9 @@ importers:
'@types/react-dom':
specifier: 19.2.3
version: 19.2.3(@types/react@19.2.14)
+ c8:
+ specifier: 12.0.0
+ version: 12.0.0
eslint:
specifier: 9.39.2
version: 9.39.2(supports-color@7.2.0)
@@ -111,6 +114,10 @@ packages:
resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==}
engines: {node: '>=6.9.0'}
+ '@bcoe/v8-coverage@1.0.2':
+ resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==}
+ engines: {node: '>=18'}
+
'@emnapi/core@1.10.0':
resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==}
@@ -349,6 +356,10 @@ packages:
cpu: [x64]
os: [win32]
+ '@istanbuljs/schema@0.1.6':
+ resolution: {integrity: sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==}
+ engines: {node: '>=8'}
+
'@jridgewell/gen-mapping@0.3.13':
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
@@ -458,6 +469,9 @@ packages:
'@types/estree@1.0.9':
resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
+ '@types/istanbul-lib-coverage@2.0.6':
+ resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
+
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
@@ -667,10 +681,18 @@ packages:
ajv@6.15.0:
resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==}
+ ansi-regex@6.3.0:
+ resolution: {integrity: sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==}
+ engines: {node: '>=12'}
+
ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
+ ansi-styles@6.2.3:
+ resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
+ engines: {node: '>=12'}
+
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
@@ -757,6 +779,16 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
+ c8@12.0.0:
+ resolution: {integrity: sha512-4zpJvrd1nKWutnnKC2pXkFmb6iM1l+ffN//o1CzlTNwW7GSOs9a1xrLqkC48nU8oEkjmPZLPiwMsIaOvoF4Pqg==}
+ engines: {node: ^20.19.0 || ^22.12.0 || >=23}
+ hasBin: true
+ peerDependencies:
+ monocart-coverage-reports: ^2
+ peerDependenciesMeta:
+ monocart-coverage-reports:
+ optional: true
+
call-bind-apply-helpers@1.0.2:
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
engines: {node: '>= 0.4'}
@@ -783,6 +815,10 @@ packages:
client-only@0.0.1:
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
+ cliui@9.0.1:
+ resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==}
+ engines: {node: '>=20'}
+
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
@@ -861,6 +897,9 @@ packages:
electron-to-chromium@1.5.415:
resolution: {integrity: sha512-958V+Kbhtgz+SxXeEVKBjrlKRBIDAYvUJfwhjxMZ5S6ut9jAl7l9ZKBkBrvjyjZE36PabLUo2L8kEeV5O4vgJg==}
+ emoji-regex@10.6.0:
+ resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
+
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
@@ -1077,6 +1116,10 @@ packages:
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
engines: {node: '>= 0.4'}
+ foreground-child@3.3.1:
+ resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
+ engines: {node: '>=14'}
+
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
@@ -1095,6 +1138,14 @@ packages:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'}
+ get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+
+ get-east-asian-width@1.7.0:
+ resolution: {integrity: sha512-XjH1AECxf0giL2V1aU8vKyRR2ppRUb5c0EvT7zuJTokQ74bNo52zOtghqdWIqrhUD79fo3x0WfKZdOqxF6LG1Q==}
+ engines: {node: '>=18'}
+
get-intrinsic@1.3.0:
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
engines: {node: '>= 0.4'}
@@ -1118,6 +1169,10 @@ packages:
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
engines: {node: '>=10.13.0'}
+ glob@13.0.6:
+ resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
+ engines: {node: 18 || 20 || >=22}
+
globals@14.0.0:
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
engines: {node: '>=18'}
@@ -1167,6 +1222,9 @@ packages:
hermes-parser@0.25.1:
resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==}
+ html-escaper@2.0.2:
+ resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
+
ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
@@ -1300,6 +1358,18 @@ packages:
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ istanbul-lib-coverage@3.2.2:
+ resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
+ engines: {node: '>=8'}
+
+ istanbul-lib-report@3.0.1:
+ resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
+ engines: {node: '>=10'}
+
+ istanbul-reports@3.2.0:
+ resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==}
+ engines: {node: '>=8'}
+
iterator.prototype@1.1.5:
resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
engines: {node: '>= 0.4'}
@@ -1363,9 +1433,17 @@ packages:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
+ lru-cache@11.5.3:
+ resolution: {integrity: sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==}
+ engines: {node: 20 || >=22}
+
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+ make-dir@4.0.0:
+ resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
+ engines: {node: '>=10'}
+
math-intrinsics@1.1.0:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
@@ -1388,6 +1466,10 @@ packages:
minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+ minipass@7.1.3:
+ resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@@ -1496,6 +1578,10 @@ packages:
path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+ path-scurry@2.0.2:
+ resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
+ engines: {node: 18 || 20 || >=22}
+
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -1642,6 +1728,10 @@ packages:
resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==}
engines: {node: '>= 0.4'}
+ signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
+
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
@@ -1653,6 +1743,14 @@ packages:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'}
+ string-width@7.2.0:
+ resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
+ engines: {node: '>=18'}
+
+ string-width@8.3.0:
+ resolution: {integrity: sha512-ZbmZM0JCihQN91dWnxoipT2KOEyHqEyfRXUyjuRhW8b/xnqPDoq4gWEVApTVa9db2wN8mmoikgFBbjh71+cGeQ==}
+ engines: {node: '>=20'}
+
string.prototype.includes@2.0.1:
resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==}
engines: {node: '>= 0.4'}
@@ -1676,6 +1774,10 @@ packages:
resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
engines: {node: '>= 0.4'}
+ strip-ansi@7.2.0:
+ resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==}
+ engines: {node: '>=12'}
+
strip-bom@3.0.0:
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
engines: {node: '>=4'}
@@ -1705,6 +1807,10 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
+ test-exclude@8.0.0:
+ resolution: {integrity: sha512-ZOffsNrXYggvU1mDGHk54I96r26P8SyMjO5slMKSc7+IWmtB/MQKnEC2fP51imB3/pT6YK5cT5E8f+Dd9KdyOQ==}
+ engines: {node: 20 || >=22}
+
tinyglobby@0.2.17:
resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
engines: {node: '>=12.0.0'}
@@ -1776,6 +1882,10 @@ packages:
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+ v8-to-istanbul@9.3.0:
+ resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==}
+ engines: {node: '>=10.12.0'}
+
which-boxed-primitive@1.1.1:
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
engines: {node: '>= 0.4'}
@@ -1801,9 +1911,29 @@ packages:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
+ wrap-ansi@9.0.2:
+ resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==}
+ engines: {node: '>=18'}
+
+ y18n@5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+
yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+ yargs-parser@21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
+
+ yargs-parser@22.0.0:
+ resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==}
+ engines: {node: ^20.19.0 || ^22.12.0 || >=23}
+
+ yargs@18.2.0:
+ resolution: {integrity: sha512-9OpKOLeaoNFecEp7P6iYbzze/5CqWoH7N3SMs/6y1XF4nMvFMspEGZzJ6uFi9MmQwXhyzqYoSEKO3tvA3Z/o2w==}
+ engines: {node: ^20.19.0 || ^22.12.0 || >=23}
+
yocto-queue@0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
@@ -1919,6 +2049,8 @@ snapshots:
'@babel/helper-string-parser': 7.29.7
'@babel/helper-validator-identifier': 7.29.7
+ '@bcoe/v8-coverage@1.0.2': {}
+
'@emnapi/core@1.10.0':
dependencies:
'@emnapi/wasi-threads': 1.2.1
@@ -2114,6 +2246,8 @@ snapshots:
'@img/sharp-win32-x64@0.35.4':
optional: true
+ '@istanbuljs/schema@0.1.6': {}
+
'@jridgewell/gen-mapping@0.3.13':
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
@@ -2200,6 +2334,8 @@ snapshots:
'@types/estree@1.0.9': {}
+ '@types/istanbul-lib-coverage@2.0.6': {}
+
'@types/json-schema@7.0.15': {}
'@types/json5@0.0.29': {}
@@ -2390,10 +2526,14 @@ snapshots:
json-schema-traverse: 0.4.1
uri-js: 4.4.1
+ ansi-regex@6.3.0: {}
+
ansi-styles@4.3.0:
dependencies:
color-convert: 2.0.1
+ ansi-styles@6.2.3: {}
+
argparse@2.0.1: {}
aria-query@5.3.2: {}
@@ -2504,6 +2644,20 @@ snapshots:
node-releases: 2.0.54
update-browserslist-db: 1.3.1(browserslist@4.28.8)
+ c8@12.0.0:
+ dependencies:
+ '@bcoe/v8-coverage': 1.0.2
+ '@istanbuljs/schema': 0.1.6
+ find-up: 5.0.0
+ foreground-child: 3.3.1
+ istanbul-lib-coverage: 3.2.2
+ istanbul-lib-report: 3.0.1
+ istanbul-reports: 3.2.0
+ test-exclude: 8.0.0
+ v8-to-istanbul: 9.3.0
+ yargs: 18.2.0
+ yargs-parser: 21.1.1
+
call-bind-apply-helpers@1.0.2:
dependencies:
es-errors: 1.3.0
@@ -2532,6 +2686,12 @@ snapshots:
client-only@0.0.1: {}
+ cliui@9.0.1:
+ dependencies:
+ string-width: 7.2.0
+ strip-ansi: 7.2.0
+ wrap-ansi: 9.0.2
+
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
@@ -2611,6 +2771,8 @@ snapshots:
electron-to-chromium@1.5.415: {}
+ emoji-regex@10.6.0: {}
+
emoji-regex@9.2.2: {}
es-abstract-get@1.0.0:
@@ -2977,6 +3139,11 @@ snapshots:
dependencies:
is-callable: 1.2.7
+ foreground-child@3.3.1:
+ dependencies:
+ cross-spawn: 7.0.6
+ signal-exit: 4.1.0
+
function-bind@1.1.2: {}
function.prototype.name@1.2.0:
@@ -2997,6 +3164,10 @@ snapshots:
gensync@1.0.0-beta.2: {}
+ get-caller-file@2.0.5: {}
+
+ get-east-asian-width@1.7.0: {}
+
get-intrinsic@1.3.0:
dependencies:
call-bind-apply-helpers: 1.0.2
@@ -3033,6 +3204,12 @@ snapshots:
dependencies:
is-glob: 4.0.3
+ glob@13.0.6:
+ dependencies:
+ minimatch: 10.2.6
+ minipass: 7.1.3
+ path-scurry: 2.0.2
+
globals@14.0.0: {}
globals@16.4.0: {}
@@ -3072,6 +3249,8 @@ snapshots:
dependencies:
hermes-estree: 0.25.1
+ html-escaper@2.0.2: {}
+
ignore@5.3.2: {}
ignore@7.0.6: {}
@@ -3209,6 +3388,19 @@ snapshots:
isexe@2.0.0: {}
+ istanbul-lib-coverage@3.2.2: {}
+
+ istanbul-lib-report@3.0.1:
+ dependencies:
+ istanbul-lib-coverage: 3.2.2
+ make-dir: 4.0.0
+ supports-color: 7.2.0
+
+ istanbul-reports@3.2.0:
+ dependencies:
+ html-escaper: 2.0.2
+ istanbul-lib-report: 3.0.1
+
iterator.prototype@1.1.5:
dependencies:
define-data-property: 1.1.4
@@ -3270,10 +3462,16 @@ snapshots:
dependencies:
js-tokens: 4.0.0
+ lru-cache@11.5.3: {}
+
lru-cache@5.1.1:
dependencies:
yallist: 3.1.1
+ make-dir@4.0.0:
+ dependencies:
+ semver: 7.8.5
+
math-intrinsics@1.1.0: {}
merge2@1.4.1: {}</