diff --git a/.changes/README.md b/.changes/README.md
new file mode 100644
index 000000000..2e529ab0f
--- /dev/null
+++ b/.changes/README.md
@@ -0,0 +1,86 @@
+# Release notes (`.changes/`)
+
+Every PR with a user-visible change drops one file here describing that change
+in plain language. At release time
+`tools/release/build-release-notes.mjs` turns the accumulated files into the
+GitHub release body, the `CHANGELOG.md` section, and a blog-post scaffold for
+the website — then deletes them.
+
+The point is to write the note **while the context is still fresh**, instead of
+reconstructing three months of work from commit titles at release time.
+
+## File
+
+Name it `-.md`, e.g. `.changes/playback-up-next-rail.md`.
+
+```markdown
+---
+type: feature
+area: playback
+issues: [1187]
+screenshot: up-next-rail
+---
+
+Series now show an "Up Next" rail beside the player on wide windows: the rest
+of the current season, watch progress, and click-to-play inline.
+```
+
+| Field | Required | Value |
+| ------------ | -------- | ----------------------------------------------------------- |
+| `type` | yes | `breaking`, `feature`, `fix`, `perf`, or `internal` |
+| `area` | yes | lowercase slug, same as the conventional-commit scope |
+| `issues` | no | issue numbers this closes — `[1187]` or `1187` |
+| `screenshot` | no | slug from the release screenshot manifest |
+
+There is **no version field**. The release version is chosen deliberately at
+release time, not derived from these files.
+
+You never write a PR number: the generator resolves it from the commit that
+added the file.
+
+## Writing the body
+
+One to three sentences, present tense, **written for a user, not a reviewer**.
+The body is capped at 400 characters — depth belongs in the blog post.
+
+- ❌ "Refactor `WebVideoControlsAdapter` to hoist volume state into the session"
+- ✅ "The player now remembers volume between episodes"
+
+- ❌ "Fix off-by-one in `resolveEnrichmentSeasonNumber`"
+- ✅ "Series whose title carries a season marker no longer show the wrong season"
+
+`type: internal` is for changes with no user-visible effect that are still worth
+recording (dependency bumps with behaviour risk, packaging moves). They stay out
+of the release body and blog post, and land collapsed in `CHANGELOG.md`.
+
+## When a note is not needed
+
+Skip the note — and apply the `no-release-note` label — for test-only changes,
+docs, CI/workflow plumbing, and pure refactors with no behaviour change.
+
+## Commands
+
+```bash
+pnpm run release:notes:validate
+pnpm run release:notes:github
+pnpm run release:notes:changelog
+pnpm run release:notes:blog
+node tools/release/build-release-notes.mjs --consume
+```
+
+The release version comes from the root `package.json` — bump it first, then
+generate. `--version 0.24.0` overrides it for a dry run before the bump.
+
+Only `--consume` deletes anything; every other mode is a safe dry run.
+
+The release sequence is: bump the version → `release:notes:changelog` →
+`release:notes:blog` → `--consume` → commit → tag → push. The tag build then
+extracts the new `CHANGELOG.md` section into the GitHub release body
+(`tools/release/extract-changelog-section.mjs`) and **fails the release** if
+the section is missing — a tag cut without the changelog step cannot silently
+ship PR-title-only notes.
+
+The website publishes **one post per minor version** (`v0-18` … `v0-22`), and
+release screenshots live under the matching `blog/v0-24/` directory. A patch
+release therefore edits the existing post rather than generating a new one, so
+`--format blog` refuses to overwrite unless you pass `--force`.
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 000000000..887886187
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,23 @@
+
+
+## What changed
+
+## Why
+
+## Release note
+
+Changes a user could notice need one file in `.changes/` describing the change
+in plain language — see
+[`.changes/README.md`](https://github.com/4gray/iptvnator/blob/master/.changes/README.md).
+It becomes the release notes and the website post, so it is worth a minute.
+
+- [ ] Added a note under `.changes/`
+- [ ] Not needed (test-only, docs, CI, or a refactor with no behavior change)
+
+## Checks
+
+- [ ] Tests added or updated for the changed behavior
+- [ ] `pnpm run lint` and the affected `pnpm nx test ` pass
diff --git a/.github/workflows/build-and-make.yaml b/.github/workflows/build-and-make.yaml
index bb162af7f..abbac03eb 100644
--- a/.github/workflows/build-and-make.yaml
+++ b/.github/workflows/build-and-make.yaml
@@ -1450,7 +1450,15 @@ jobs:
if [ "${IS_TAG_BUILD}" = "true" ]; then
NAME="Release v${VERSION}"
TAG="${GITHUB_REF_NAME}"
- BODY=""
+ # Authored release notes: the release flow writes this
+ # CHANGELOG section from .changes/*.md before tagging
+ # (see .changes/README.md), so at tag time the changelog
+ # is the authored source of truth. The extractor exits
+ # non-zero when the section is missing, failing the
+ # release rather than silently shipping PR-title-only
+ # notes. generate_release_notes stays on below, so the
+ # GitHub commit list still renders under this body.
+ BODY="$(node tools/release/extract-changelog-section.mjs "${VERSION}")"
elif [ "${EVENT_NAME}" = "pull_request" ]; then
NAME="v${VERSION} — PR #${PR_NUMBER} @ ${SHORT_SHA} [test]"
TAG="test-pr-${PR_NUMBER}"
diff --git a/AGENTS.md b/AGENTS.md
index 180f023c2..1c608607c 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -33,6 +33,16 @@ This file provides guidance to coding agents working in this repository.
- Repo docs are canonical even when they were originally drafted by an LLM.
- Final task summaries should state whether docs were updated and which doc changed.
+## Release Notes For User-Visible Changes
+
+- Any change a user could notice — new behavior, changed behavior, bug fix, performance win, breaking change — must add one note file under `.changes/` in the same PR. Format, field table, and writing rules: `.changes/README.md`.
+- Name it `-.md`; `area` matches the conventional-commit scope. There is no version field — the release version is chosen at release time.
+- Write the body for a user, not a reviewer: "the player now remembers volume between episodes", not "hoist volume state into the session". Max 400 characters; depth belongs in the release blog post.
+- Skip the note for test-only changes, docs, CI/workflow plumbing, and pure refactors with no behavior change. When skipping on a PR that touches `apps/**` or `libs/**`, apply the `no-release-note` label.
+- Validate before finishing: `pnpm run release:notes:validate`.
+- Release-post screenshots come only from the release capture script running against the mock servers. Never add a screenshot taken from a real playlist or account to `apps/website/public/blog/**` — real streams, logos, and metadata are copyrighted, and credentials must never reach a published image.
+- Final task summaries should state whether a release note was added or why it was skipped.
+
## Regression Prevention And Test Updates
- Before the final summary for any feature, behavior change, bug fix, data-flow change, Electron IPC/database change, or user-visible UI workflow change, complete a test impact pass. Identify the affected projects and decide whether unit, integration, E2E, build, lint, or manual/CDP verification is required.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 42aacde10..854fbf7e0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,16 @@
+# Changelog
+
+Releases **0.13.0 – 0.23.0** were published as
+[GitHub releases](https://github.com/4gray/iptvnator/releases) and
+[website posts](https://4gray.github.io/iptvnator/blog/) rather than collected
+here. This file resumes from the next release onwards; the entries below are
+kept as they were written.
+
+New sections are generated from `.changes/*.md` and inserted directly below
+this marker — see `.changes/README.md`.
+
+
+
# [0.12.0](https://github.com/4gray/iptvnator/compare/v0.11.1...v0.12.0) (2023-03-11)
diff --git a/CLAUDE.md b/CLAUDE.md
index a4b2938d8..df74fe116 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -26,6 +26,16 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
- Repo docs are canonical even when they were originally drafted by an LLM.
- Final task summaries should state whether docs were updated and which doc changed.
+## Release Notes For User-Visible Changes
+
+- Any change a user could notice — new behavior, changed behavior, bug fix, performance win, breaking change — must add one note file under `.changes/` in the same PR. Format, field table, and writing rules: `.changes/README.md`.
+- Name it `-.md`; `area` matches the conventional-commit scope. There is no version field — the release version is chosen at release time.
+- Write the body for a user, not a reviewer: "the player now remembers volume between episodes", not "hoist volume state into the session". Max 400 characters; depth belongs in the release blog post.
+- Skip the note for test-only changes, docs, CI/workflow plumbing, and pure refactors with no behavior change. When skipping on a PR that touches `apps/**` or `libs/**`, apply the `no-release-note` label.
+- Validate before finishing: `pnpm run release:notes:validate`.
+- Release-post screenshots come only from the release capture script running against the mock servers. Never add a screenshot taken from a real playlist or account to `apps/website/public/blog/**` — real streams, logos, and metadata are copyrighted, and credentials must never reach a published image.
+- Final task summaries should state whether a release note was added or why it was skipped.
+
## Regression Prevention And Test Updates
- Before the final summary for any feature, behavior change, bug fix, data-flow change, Electron IPC/database change, or user-visible UI workflow change, Claude Code must complete a test impact pass. Identify the affected projects and decide whether unit, integration, E2E, build, lint, or manual/CDP verification is required.
diff --git a/package.json b/package.json
index 5601cb22f..872879829 100644
--- a/package.json
+++ b/package.json
@@ -61,6 +61,10 @@
"release:artwork:manifest": "tsx tools/release/generate-marketing-artwork.ts --manifest",
"release:artwork:generate": "tsx tools/release/generate-marketing-artwork.ts --generate",
"release:artwork:validate": "tsx tools/release/generate-marketing-artwork.ts --validate",
+ "release:notes:validate": "node tools/release/build-release-notes.mjs --validate",
+ "release:notes:github": "node tools/release/build-release-notes.mjs --format github",
+ "release:notes:changelog": "node tools/release/build-release-notes.mjs --format changelog",
+ "release:notes:blog": "node tools/release/build-release-notes.mjs --format blog",
"lint": "nx run-many --target=lint --all",
"build": "nx build electron-backend"
},
@@ -157,9 +161,6 @@
"@nx/workspace": "22.7.1",
"@playwright/test": "^1.36.0",
"@schematics/angular": "21.2.9",
- "@semantic-release/changelog": "6.0.3",
- "@semantic-release/git": "10.0.1",
- "@semantic-release/npm": "12.0.1",
"@swc-node/register": "1.11.1",
"@swc/core": "1.15.8",
"@swc/helpers": "0.5.18",
@@ -177,7 +178,6 @@
"@typescript-eslint/utils": "^8.46.2",
"angular-eslint": "21.3.1",
"astro": "5.18.1",
- "conventional-changelog-cli": "5.0.0",
"cors": "2.8.6",
"drizzle-kit": "0.31.5",
"electron": "^41.7.2",
@@ -204,7 +204,6 @@
"nx": "22.7.1",
"nx-electron": "22.0.0",
"prettier": "^3.8.1",
- "semantic-release": "24.2.9",
"sharp": "0.34.5",
"tailwindcss": "^3.4.19",
"ts-jest": "^29.4.5",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 94ef0f18f..b5659b2ab 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -279,15 +279,6 @@ importers:
'@schematics/angular':
specifier: 21.2.9
version: 21.2.9(chokidar@5.0.0)
- '@semantic-release/changelog':
- specifier: 6.0.3
- version: 6.0.3(semantic-release@24.2.9(typescript@5.9.3))
- '@semantic-release/git':
- specifier: 10.0.1
- version: 10.0.1(semantic-release@24.2.9(typescript@5.9.3))
- '@semantic-release/npm':
- specifier: 12.0.1
- version: 12.0.1(semantic-release@24.2.9(typescript@5.9.3))
'@swc-node/register':
specifier: 1.11.1
version: 1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.18))(@swc/types@0.1.25)(typescript@5.9.3)
@@ -339,9 +330,6 @@ importers:
astro:
specifier: 5.18.1
version: 5.18.1(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(rollup@4.59.0)(sass-embedded@1.97.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
- conventional-changelog-cli:
- specifier: 5.0.0
- version: 5.0.0(conventional-commits-filter@5.0.0)
cors:
specifier: 2.8.6
version: 2.8.6
@@ -420,9 +408,6 @@ importers:
prettier:
specifier: ^3.8.1
version: 3.8.1
- semantic-release:
- specifier: 24.2.9
- version: 24.2.9(typescript@5.9.3)
sharp:
specifier: 0.34.5
version: 0.34.5
@@ -1557,22 +1542,6 @@ packages:
'@colordx/core@5.4.3':
resolution: {integrity: sha512-kIxYSfA5T8HXjav55UaaH/o/cKivF6jCCGIb8eqtcsfI46wsvlSiT8jMDyrl779qLec3c2c2oHBZo4oAhvbjrQ==}
- '@colors/colors@1.5.0':
- resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
- engines: {node: '>=0.1.90'}
-
- '@conventional-changelog/git-client@1.0.1':
- resolution: {integrity: sha512-PJEqBwAleffCMETaVm/fUgHldzBE35JFk3/9LL6NUA5EXa3qednu+UT6M7E5iBu3zIQZCULYIiZ90fBYHt6xUw==}
- engines: {node: '>=18'}
- peerDependencies:
- conventional-commits-filter: ^5.0.0
- conventional-commits-parser: ^6.0.0
- peerDependenciesMeta:
- conventional-commits-filter:
- optional: true
- conventional-commits-parser:
- optional: true
-
'@cspotcode/source-map-support@0.8.1':
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
@@ -2375,10 +2344,6 @@ packages:
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
engines: {node: '>=18.18'}
- '@hutson/parse-repository-url@5.0.0':
- resolution: {integrity: sha512-e5+YUKENATs1JgYHMzTr2MW/NDcXGfYFAuOQU8gJgF/kEh4EqKgfGrfLI67bMD4tbhZVlkigz/9YYwWcbOFthg==}
- engines: {node: '>=10.13.0'}
-
'@img/colour@1.0.0':
resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==}
engines: {node: '>=18'}
@@ -3550,60 +3515,6 @@ packages:
'@nx/workspace@22.7.1':
resolution: {integrity: sha512-wnBMgeogdGaRdxDDzZspSt1U87PMeYJhz1ygr42L9Lot9E5nCf17E85iyHl3YxcMSNslHxnHyTkq7MyQ8hHjdQ==}
- '@octokit/auth-token@6.0.0':
- resolution: {integrity: sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==}
- engines: {node: '>= 20'}
-
- '@octokit/core@7.0.6':
- resolution: {integrity: sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==}
- engines: {node: '>= 20'}
-
- '@octokit/endpoint@11.0.2':
- resolution: {integrity: sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ==}
- engines: {node: '>= 20'}
-
- '@octokit/graphql@9.0.3':
- resolution: {integrity: sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==}
- engines: {node: '>= 20'}
-
- '@octokit/openapi-types@26.0.0':
- resolution: {integrity: sha512-7AtcfKtpo77j7Ts73b4OWhOZHTKo/gGY8bB3bNBQz4H+GRSWqx2yvj8TXRsbdTE0eRmYmXOEY66jM7mJ7LzfsA==}
-
- '@octokit/openapi-types@27.0.0':
- resolution: {integrity: sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==}
-
- '@octokit/plugin-paginate-rest@13.2.1':
- resolution: {integrity: sha512-Tj4PkZyIL6eBMYcG/76QGsedF0+dWVeLhYprTmuFVVxzDW7PQh23tM0TP0z+1MvSkxB29YFZwnUX+cXfTiSdyw==}
- engines: {node: '>= 20'}
- peerDependencies:
- '@octokit/core': '>=6'
-
- '@octokit/plugin-retry@8.0.3':
- resolution: {integrity: sha512-vKGx1i3MC0za53IzYBSBXcrhmd+daQDzuZfYDd52X5S0M2otf3kVZTVP8bLA3EkU0lTvd1WEC2OlNNa4G+dohA==}
- engines: {node: '>= 20'}
- peerDependencies:
- '@octokit/core': '>=7'
-
- '@octokit/plugin-throttling@11.0.3':
- resolution: {integrity: sha512-34eE0RkFCKycLl2D2kq7W+LovheM/ex3AwZCYN8udpi6bxsyjZidb2McXs69hZhLmJlDqTSP8cH+jSRpiaijBg==}
- engines: {node: '>= 20'}
- peerDependencies:
- '@octokit/core': ^7.0.0
-
- '@octokit/request-error@7.1.0':
- resolution: {integrity: sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==}
- engines: {node: '>= 20'}
-
- '@octokit/request@10.0.7':
- resolution: {integrity: sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA==}
- engines: {node: '>= 20'}
-
- '@octokit/types@15.0.2':
- resolution: {integrity: sha512-rR+5VRjhYSer7sC51krfCctQhVTmjyUMAaShfPB8mscVa8tSoLyon3coxQmXu0ahJoLVWl8dSGD/3OGZlFV44Q==}
-
- '@octokit/types@16.0.0':
- resolution: {integrity: sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==}
-
'@oslojs/encoding@1.1.0':
resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==}
@@ -3824,18 +3735,6 @@ packages:
engines: {node: '>=18'}
hasBin: true
- '@pnpm/config.env-replace@1.1.0':
- resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==}
- engines: {node: '>=12.22.0'}
-
- '@pnpm/network.ca-file@1.0.2':
- resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==}
- engines: {node: '>=12.22.0'}
-
- '@pnpm/npm-conf@2.3.1':
- resolution: {integrity: sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==}
- engines: {node: '>=12'}
-
'@rolldown/binding-android-arm64@1.0.0-rc.4':
resolution: {integrity: sha512-vRq9f4NzvbdZavhQbjkJBx7rRebDKYR9zHfO/Wg486+I7bSecdUapzCm5cyXoK+LHokTxgSq7A5baAXUZkIz0w==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -4161,59 +4060,6 @@ packages:
resolution: {integrity: sha512-1renEbBZz9Yw3A0GUOJ6x6E1jd2Vu/fX5tEGiFNbIoWaNwa71SlFTvKKqaYxiYQkrpc7oexVJ2ymuvOfgTbI1w==}
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
- '@sec-ant/readable-stream@0.4.1':
- resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
-
- '@semantic-release/changelog@6.0.3':
- resolution: {integrity: sha512-dZuR5qByyfe3Y03TpmCvAxCyTnp7r5XwtHRf/8vD9EAn4ZWbavUX8adMtXYzE86EVh0gyLA7lm5yW4IV30XUag==}
- engines: {node: '>=14.17'}
- peerDependencies:
- semantic-release: '>=18.0.0'
-
- '@semantic-release/commit-analyzer@13.0.1':
- resolution: {integrity: sha512-wdnBPHKkr9HhNhXOhZD5a2LNl91+hs8CC2vsAVYxtZH3y0dV3wKn+uZSN61rdJQZ8EGxzWB3inWocBHV9+u/CQ==}
- engines: {node: '>=20.8.1'}
- peerDependencies:
- semantic-release: '>=20.1.0'
-
- '@semantic-release/error@3.0.0':
- resolution: {integrity: sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==}
- engines: {node: '>=14.17'}
-
- '@semantic-release/error@4.0.0':
- resolution: {integrity: sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==}
- engines: {node: '>=18'}
-
- '@semantic-release/git@10.0.1':
- resolution: {integrity: sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w==}
- engines: {node: '>=14.17'}
- peerDependencies:
- semantic-release: '>=18.0.0'
-
- '@semantic-release/github@11.0.6':
- resolution: {integrity: sha512-ctDzdSMrT3H+pwKBPdyCPty6Y47X8dSrjd3aPZ5KKIKKWTwZBE9De8GtsH3TyAlw3Uyo2stegMx6rJMXKpJwJA==}
- engines: {node: '>=20.8.1'}
- peerDependencies:
- semantic-release: '>=24.1.0'
-
- '@semantic-release/npm@12.0.1':
- resolution: {integrity: sha512-/6nntGSUGK2aTOI0rHPwY3ZjgY9FkXmEHbW9Kr+62NVOsyqpKKeP0lrCH+tphv+EsNdJNmqqwijTEnVWUMQ2Nw==}
- engines: {node: '>=20.8.1'}
- peerDependencies:
- semantic-release: '>=20.1.0'
-
- '@semantic-release/npm@12.0.2':
- resolution: {integrity: sha512-+M9/Lb35IgnlUO6OSJ40Ie+hUsZLuph2fqXC/qrKn0fMvUU/jiCjpoL6zEm69vzcmaZJ8yNKtMBEKHWN49WBbQ==}
- engines: {node: '>=20.8.1'}
- peerDependencies:
- semantic-release: '>=20.1.0'
-
- '@semantic-release/release-notes-generator@14.1.0':
- resolution: {integrity: sha512-CcyDRk7xq+ON/20YNR+1I/jP7BYKICr1uKd1HHpROSnnTdGqOTburi4jcRiTYz0cpfhxSloQO3cGhnoot7IEkA==}
- engines: {node: '>=20.8.1'}
- peerDependencies:
- semantic-release: '>=20.1.0'
-
'@shikijs/core@3.22.0':
resolution: {integrity: sha512-iAlTtSDDbJiRpvgL5ugKEATDtHdUVkqgHDm/gbD2ZS9c88mx7G1zSYjjOxp5Qa0eaW0MAQosFRmJSk354PRoQA==}
@@ -4270,10 +4116,6 @@ packages:
resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==}
engines: {node: '>=18'}
- '@sindresorhus/merge-streams@4.0.0':
- resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
- engines: {node: '>=18'}
-
'@sinonjs/commons@3.0.1':
resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==}
@@ -4555,9 +4397,6 @@ packages:
'@types/node@24.13.1':
resolution: {integrity: sha512-RSpUJGmvsJ1ZeBehQZFhIdpsz+bIpES0nIQXko4Ybq+N+kX6XvOq3Jo+iJ82FWLdblFq85AsMikd3m35jgezYg==}
- '@types/normalize-package-data@2.4.4':
- resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
-
'@types/parse-json@4.0.2':
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
@@ -4582,9 +4421,6 @@ packages:
'@types/semver@7.5.8':
resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
- '@types/semver@7.7.1':
- resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==}
-
'@types/send@0.17.6':
resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==}
@@ -4933,9 +4769,6 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
- add-stream@1.0.0:
- resolution: {integrity: sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==}
-
address@1.2.2:
resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==}
engines: {node: '>= 10.0.0'}
@@ -4970,10 +4803,6 @@ packages:
resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
engines: {node: '>=8'}
- aggregate-error@5.0.0:
- resolution: {integrity: sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==}
- engines: {node: '>=18'}
-
ajv-formats@2.1.1:
resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
peerDependencies:
@@ -5055,10 +4884,6 @@ packages:
resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
engines: {node: '>=12'}
- ansi-styles@3.2.1:
- resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
- engines: {node: '>=4'}
-
ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
@@ -5100,9 +4925,6 @@ packages:
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
- argv-formatter@1.0.0:
- resolution: {integrity: sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==}
-
aria-query@5.3.2:
resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
engines: {node: '>= 0.4'}
@@ -5114,9 +4936,6 @@ packages:
array-flatten@1.1.1:
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
- array-ify@1.0.0:
- resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==}
-
array-includes@3.1.9:
resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==}
engines: {node: '>= 0.4'}
@@ -5300,9 +5119,6 @@ packages:
resolution: {integrity: sha512-2Imdcw3LznDuxAbJM26RHniOLAzE6WgrK8OuvVXCQtNBS8rsnD9zsSEa3fHl4hHpUY7BYTlrpvtPVbvu9G6neg==}
engines: {node: '>=18.0.0'}
- before-after-hook@4.0.0:
- resolution: {integrity: sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==}
-
better-sqlite3@12.9.0:
resolution: {integrity: sha512-wqUv4Gm3toFpHDQmaKD4QhZm3g1DjUBI0yzS4UBl6lElUmXFYdTQmmEDpAFa5o8FiFiymURypEnfVHzILKaxqQ==}
engines: {node: 20.x || 22.x || 23.x || 24.x || 25.x}
@@ -5334,9 +5150,6 @@ packages:
boolbase@1.0.0:
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
- bottleneck@2.19.5:
- resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==}
-
boxen@8.0.1:
resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==}
engines: {node: '>=18'}
@@ -5465,10 +5278,6 @@ packages:
ccount@2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
- chalk@2.4.2:
- resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
- engines: {node: '>=4'}
-
chalk@3.0.0:
resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==}
engines: {node: '>=8'}
@@ -5545,10 +5354,6 @@ packages:
resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
engines: {node: '>=6'}
- clean-stack@5.3.0:
- resolution: {integrity: sha512-9ngPTOhYGQqNVSfeJkYXHmF7AGWp4/nN5D/QqNQs3Dvxd1Kk/WpjHfNujKHYUQ/5CoGyOyFNoWSPk5afzP0QVg==}
- engines: {node: '>=14.16'}
-
cli-boxes@3.0.0:
resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==}
engines: {node: '>=10'}
@@ -5561,11 +5366,6 @@ packages:
resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==}
engines: {node: '>=18'}
- cli-highlight@2.1.11:
- resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==}
- engines: {node: '>=8.0.0', npm: '>=5.0.0'}
- hasBin: true
-
cli-spinners@2.6.1:
resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==}
engines: {node: '>=6'}
@@ -5578,10 +5378,6 @@ packages:
resolution: {integrity: sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw==}
engines: {node: '>=18.20'}
- cli-table3@0.6.5:
- resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==}
- engines: {node: 10.* || >= 12.*}
-
cli-truncate@2.1.0:
resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==}
engines: {node: '>=8'}
@@ -5597,9 +5393,6 @@ packages:
cliui@6.0.0:
resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
- cliui@7.0.4:
- resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
-
cliui@8.0.1:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'}
@@ -5633,16 +5426,10 @@ packages:
collect-v8-coverage@1.0.3:
resolution: {integrity: sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==}
- color-convert@1.9.3:
- resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
-
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
- color-name@1.1.3:
- resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
-
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
@@ -5688,9 +5475,6 @@ packages:
common-path-prefix@3.0.0:
resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==}
- compare-func@2.0.0:
- resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==}
-
compare-version@0.1.2:
resolution: {integrity: sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==}
engines: {node: '>=0.10.0'}
@@ -5706,9 +5490,6 @@ packages:
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
- config-chain@1.1.13:
- resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==}
-
config-file-ts@0.2.8-rc1:
resolution: {integrity: sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==}
@@ -5731,78 +5512,6 @@ packages:
resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
engines: {node: '>= 0.6'}
- conventional-changelog-angular@8.1.0:
- resolution: {integrity: sha512-GGf2Nipn1RUCAktxuVauVr1e3r8QrLP/B0lEUsFktmGqc3ddbQkhoJZHJctVU829U1c6mTSWftrVOCHaL85Q3w==}
- engines: {node: '>=18'}
-
- conventional-changelog-atom@5.0.0:
- resolution: {integrity: sha512-WfzCaAvSCFPkznnLgLnfacRAzjgqjLUjvf3MftfsJzQdDICqkOOpcMtdJF3wTerxSpv2IAAjX8doM3Vozqle3g==}
- engines: {node: '>=18'}
-
- conventional-changelog-cli@5.0.0:
- resolution: {integrity: sha512-9Y8fucJe18/6ef6ZlyIlT2YQUbczvoQZZuYmDLaGvcSBP+M6h+LAvf7ON7waRxKJemcCII8Yqu5/8HEfskTxJQ==}
- engines: {node: '>=18'}
- deprecated: This package is no longer maintained. Please use the conventional-changelog package instead.
- hasBin: true
-
- conventional-changelog-codemirror@5.0.0:
- resolution: {integrity: sha512-8gsBDI5Y3vrKUCxN6Ue8xr6occZ5nsDEc4C7jO/EovFGozx8uttCAyfhRrvoUAWi2WMm3OmYs+0mPJU7kQdYWQ==}
- engines: {node: '>=18'}
-
- conventional-changelog-conventionalcommits@8.0.0:
- resolution: {integrity: sha512-eOvlTO6OcySPyyyk8pKz2dP4jjElYunj9hn9/s0OB+gapTO8zwS9UQWrZ1pmF2hFs3vw1xhonOLGcGjy/zgsuA==}
- engines: {node: '>=18'}
-
- conventional-changelog-core@8.0.0:
- resolution: {integrity: sha512-EATUx5y9xewpEe10UEGNpbSHRC6cVZgO+hXQjofMqpy+gFIrcGvH3Fl6yk2VFKh7m+ffenup2N7SZJYpyD9evw==}
- engines: {node: '>=18'}
-
- conventional-changelog-ember@5.0.0:
- resolution: {integrity: sha512-RPflVfm5s4cSO33GH/Ey26oxhiC67akcxSKL8CLRT3kQX2W3dbE19sSOM56iFqUJYEwv9mD9r6k79weWe1urfg==}
- engines: {node: '>=18'}
-
- conventional-changelog-eslint@6.0.0:
- resolution: {integrity: sha512-eiUyULWjzq+ybPjXwU6NNRflApDWlPEQEHvI8UAItYW/h22RKkMnOAtfCZxMmrcMO1OKUWtcf2MxKYMWe9zJuw==}
- engines: {node: '>=18'}
-
- conventional-changelog-express@5.0.0:
- resolution: {integrity: sha512-D8Q6WctPkQpvr2HNCCmwU5GkX22BVHM0r4EW8vN0230TSyS/d6VQJDAxGb84lbg0dFjpO22MwmsikKL++Oo/oQ==}
- engines: {node: '>=18'}
-
- conventional-changelog-jquery@6.0.0:
- resolution: {integrity: sha512-2kxmVakyehgyrho2ZHBi90v4AHswkGzHuTaoH40bmeNqUt20yEkDOSpw8HlPBfvEQBwGtbE+5HpRwzj6ac2UfA==}
- engines: {node: '>=18'}
-
- conventional-changelog-jshint@5.0.0:
- resolution: {integrity: sha512-gGNphSb/opc76n2eWaO6ma4/Wqu3tpa2w7i9WYqI6Cs2fncDSI2/ihOfMvXveeTTeld0oFvwMVNV+IYQIk3F3g==}
- engines: {node: '>=18'}
-
- conventional-changelog-preset-loader@5.0.0:
- resolution: {integrity: sha512-SetDSntXLk8Jh1NOAl1Gu5uLiCNSYenB5tm0YVeZKePRIgDW9lQImromTwLa3c/Gae298tsgOM+/CYT9XAl0NA==}
- engines: {node: '>=18'}
-
- conventional-changelog-writer@8.2.0:
- resolution: {integrity: sha512-Y2aW4596l9AEvFJRwFGJGiQjt2sBYTjPD18DdvxX9Vpz0Z7HQ+g1Z+6iYDAm1vR3QOJrDBkRHixHK/+FhkR6Pw==}
- engines: {node: '>=18'}
- hasBin: true
-
- conventional-changelog@6.0.0:
- resolution: {integrity: sha512-tuUH8H/19VjtD9Ig7l6TQRh+Z0Yt0NZ6w/cCkkyzUbGQTnUEmKfGtkC9gGfVgCfOL1Rzno5NgNF4KY8vR+Jo3w==}
- engines: {node: '>=18'}
-
- conventional-commits-filter@5.0.0:
- resolution: {integrity: sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==}
- engines: {node: '>=18'}
-
- conventional-commits-parser@6.2.1:
- resolution: {integrity: sha512-20pyHgnO40rvfI0NGF/xiEoFMkXDtkF8FwHvk5BokoFoCuTQRI8vrNCNFWUOfuolKJMm1tPCHc8GgYEtr1XRNA==}
- engines: {node: '>=18'}
- hasBin: true
-
- convert-hrtime@5.0.0:
- resolution: {integrity: sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==}
- engines: {node: '>=12'}
-
convert-source-map@1.9.0:
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
@@ -5905,10 +5614,6 @@ packages:
crossws@0.3.5:
resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==}
- crypto-random-string@4.0.0:
- resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==}
- engines: {node: '>=12'}
-
css-declaration-sorter@7.3.1:
resolution: {integrity: sha512-gz6x+KkgNCjxq3Var03pRYLhyNfwhkKF1g/yoLgDNtFvVu0/fOLV9C8fFEZRjACp/XQLumjAYo7JVjzH3wLbxA==}
engines: {node: ^14 || ^16 || >=18}
@@ -6201,10 +5906,6 @@ packages:
dir-compare@4.2.0:
resolution: {integrity: sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==}
- dir-glob@3.0.1:
- resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
- engines: {node: '>=8'}
-
dlv@1.1.3:
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
@@ -6241,10 +5942,6 @@ packages:
domutils@3.2.2:
resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
- dot-prop@5.3.0:
- resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==}
- engines: {node: '>=8'}
-
dotenv-expand@11.0.7:
resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==}
engines: {node: '>=12'}
@@ -6365,9 +6062,6 @@ packages:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
- duplexer2@0.1.4:
- resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==}
-
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
@@ -6434,9 +6128,6 @@ packages:
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
- emojilib@2.4.0:
- resolution: {integrity: sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==}
-
emojis-list@3.0.0:
resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==}
engines: {node: '>= 4'}
@@ -6467,10 +6158,6 @@ packages:
resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
engines: {node: '>=0.12'}
- env-ci@11.2.0:
- resolution: {integrity: sha512-D5kWfzkmaOQDioPmiviWAVtKmpPT4/iJmMVQxWxMPJTFyTkdc5JQUfc5iXEeWxcOdsYTKSAiA/Age4NUOqKsRA==}
- engines: {node: ^18.17 || >=20.6.1}
-
env-paths@2.2.1:
resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
engines: {node: '>=6'}
@@ -6758,14 +6445,6 @@ packages:
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
engines: {node: '>=10'}
- execa@8.0.1:
- resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
- engines: {node: '>=16.17'}
-
- execa@9.6.1:
- resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==}
- engines: {node: ^18.19.0 || >=20.5.0}
-
exit-x@0.2.2:
resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==}
engines: {node: '>= 0.8.0'}
@@ -6806,9 +6485,6 @@ packages:
resolution: {integrity: sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==}
engines: {'0': node >=0.6.0}
- fast-content-type-parse@3.0.0:
- resolution: {integrity: sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==}
-
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
@@ -6844,18 +6520,10 @@ packages:
picomatch:
optional: true
- figures@2.0.0:
- resolution: {integrity: sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==}
- engines: {node: '>=4'}
-
figures@3.2.0:
resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==}
engines: {node: '>=8'}
- figures@6.1.0:
- resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==}
- engines: {node: '>=18'}
-
file-entry-cache@8.0.0:
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
engines: {node: '>=16.0.0'}
@@ -6890,14 +6558,6 @@ packages:
resolution: {integrity: sha512-WgZ+nKbELDa6N3i/9nrHeNznm+lY3z4YfhDDWgW+5P0pdmMj26bxaxU11ookgY3NyP9GC7HvZ9etp0jRFqGEeQ==}
engines: {node: '>=8'}
- find-up-simple@1.0.1:
- resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==}
- engines: {node: '>=18'}
-
- find-up@2.1.0:
- resolution: {integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==}
- engines: {node: '>=4'}
-
find-up@4.1.0:
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
engines: {node: '>=8'}
@@ -6910,10 +6570,6 @@ packages:
resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- find-versions@6.0.0:
- resolution: {integrity: sha512-2kCCtc+JvcZ86IGAz3Z2Y0A1baIz9fL31pH/0S1IqZr9Iwnjq8izfPtrCyQKO6TLMPELLsQMre7VDqeIKCsHkA==}
- engines: {node: '>=18'}
-
fix-path@5.0.0:
resolution: {integrity: sha512-erEWGGCN7RIu1bXTCfNVpVBdm0f5mwcbeja+4QXiEZzIQukP401sbpu8gd3Ny1vS34YNeswyMO0TdT2tP5OlHA==}
engines: {node: '>=20'}
@@ -6983,9 +6639,6 @@ packages:
resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
engines: {node: '>= 0.8'}
- from2@2.3.0:
- resolution: {integrity: sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==}
-
fs-constants@1.0.0:
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
@@ -6993,10 +6646,6 @@ packages:
resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
engines: {node: '>=12'}
- fs-extra@11.3.3:
- resolution: {integrity: sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==}
- engines: {node: '>=14.14'}
-
fs-extra@11.3.5:
resolution: {integrity: sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==}
engines: {node: '>=14.14'}
@@ -7040,10 +6689,6 @@ packages:
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
- function-timeout@1.0.2:
- resolution: {integrity: sha512-939eZS4gJ3htTHAldmyyuzlrD58P03fHG49v2JfFXbV6OhvZKRC9j2yAtdHw/zrp2zXHuv05zMIy40F0ge7spA==}
- engines: {node: '>=18'}
-
function.prototype.name@1.1.8:
resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==}
engines: {node: '>= 0.4'}
@@ -7091,18 +6736,6 @@ packages:
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
engines: {node: '>=10'}
- get-stream@7.0.1:
- resolution: {integrity: sha512-3M8C1EOFN6r8AMUhwUAACIoXZJEOufDU5+0gFFN5uNs6XYOralD2Pqkl7m046va6x77FwposWXbAhPPIOus7mQ==}
- engines: {node: '>=16'}
-
- get-stream@8.0.1:
- resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
- engines: {node: '>=16'}
-
- get-stream@9.0.1:
- resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==}
- engines: {node: '>=18'}
-
get-symbol-description@1.1.0:
resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
engines: {node: '>= 0.4'}
@@ -7110,21 +6743,6 @@ packages:
get-tsconfig@4.13.0:
resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==}
- git-log-parser@1.2.1:
- resolution: {integrity: sha512-PI+sPDvHXNPl5WNOErAK05s3j0lgwUzMN6o8cyQrDaKfT3qd7TmNJKeXX+SknI5I0QhG5fVPAEwSY4tRGDtYoQ==}
-
- git-raw-commits@5.0.0:
- resolution: {integrity: sha512-I2ZXrXeOc0KrCvC7swqtIFXFN+rbjnC7b2T943tvemIOVNl+XP8YnA9UVwqFhzzLClnSA60KR/qEjLpXzs73Qg==}
- engines: {node: '>=18'}
- deprecated: This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead.
- hasBin: true
-
- git-semver-tags@8.0.0:
- resolution: {integrity: sha512-N7YRIklvPH3wYWAR2vysaqGLPRcpwQ0GKdlqTiVN5w1UmCdaeY3K8s6DMKRCh54DDdzyt/OAB6C8jgVtb7Y2Fg==}
- engines: {node: '>=18'}
- deprecated: This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead.
- hasBin: true
-
github-from-package@0.0.0:
resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
@@ -7205,9 +6823,6 @@ packages:
resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==}
engines: {node: '>=10.19.0'}
- graceful-fs@4.2.10:
- resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
-
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
@@ -7229,10 +6844,6 @@ packages:
resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
engines: {node: '>= 0.4'}
- has-flag@3.0.0:
- resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
- engines: {node: '>=4'}
-
has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
@@ -7300,9 +6911,6 @@ packages:
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
hasBin: true
- highlight.js@10.7.3:
- resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==}
-
hls.js@1.6.13:
resolution: {integrity: sha512-hNEzjZNHf5bFrUNvdS4/1RjIanuJ6szpWNfTaX5I6WfGynWXGT7K/YQLYtemSvFExzeMdgdE4SsyVLJbd5PcZA==}
@@ -7314,22 +6922,10 @@ packages:
resolution: {integrity: sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w==}
engines: {node: '>=16.9.0'}
- hook-std@4.0.0:
- resolution: {integrity: sha512-IHI4bEVOt3vRUDJ+bFA9VUJlo7SzvFARPNLw75pqSmAOP2HmTWfFJtPvLBrDrlgjEYXY9zs7SFdHPQaJShkSCQ==}
- engines: {node: '>=20'}
-
hosted-git-info@4.1.0:
resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==}
engines: {node: '>=10'}
- hosted-git-info@7.0.2:
- resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==}
- engines: {node: ^16.14.0 || >=18.0.0}
-
- hosted-git-info@8.1.0:
- resolution: {integrity: sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==}
- engines: {node: ^18.17.0 || >=20.5.0}
-
hosted-git-info@9.0.2:
resolution: {integrity: sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==}
engines: {node: ^20.17.0 || >=22.9.0}
@@ -7431,14 +7027,6 @@ packages:
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
engines: {node: '>=10.17.0'}
- human-signals@5.0.0:
- resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
- engines: {node: '>=16.17.0'}
-
- human-signals@8.0.1:
- resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==}
- engines: {node: '>=18.18.0'}
-
humanize-ms@1.2.1:
resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==}
@@ -7500,10 +7088,6 @@ packages:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
engines: {node: '>=6'}
- import-from-esm@2.0.0:
- resolution: {integrity: sha512-YVt14UZCgsX1vZQ3gKjkWVdBdHQ6eu3MPU1TBgL1H5orXe2+jWD006WCPPtOuwlQm10NuzOW5WawiF1Q9veW8g==}
- engines: {node: '>=18.20'}
-
import-local@3.2.0:
resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==}
engines: {node: '>=8'}
@@ -7520,14 +7104,6 @@ packages:
resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
engines: {node: '>=8'}
- indent-string@5.0.0:
- resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
- engines: {node: '>=12'}
-
- index-to-position@1.2.0:
- resolution: {integrity: sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==}
- engines: {node: '>=18'}
-
individual@2.0.0:
resolution: {integrity: sha512-pWt8hBCqJsUWI/HtcfWod7+N9SgAqyPEaF7JQjwzjn5vGrpg6aQ5qeAFQ7dx//UH4J1O+7xqew+gCeeFt6xN/g==}
@@ -7558,10 +7134,6 @@ packages:
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
- into-stream@7.0.0:
- resolution: {integrity: sha512-2dYz766i9HprMBasCMvHMuazJ7u4WzhJwo5kb3iPSiW/iRYV6uPari3zHoqZlnuaR7V1bEiNMxikhp37rdBXbw==}
- engines: {node: '>=12'}
-
ip-address@10.1.0:
resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==}
engines: {node: '>= 12'}
@@ -7718,10 +7290,6 @@ packages:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
- is-obj@2.0.0:
- resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==}
- engines: {node: '>=8'}
-
is-plain-obj@3.0.0:
resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==}
engines: {node: '>=10'}
@@ -7760,14 +7328,6 @@ packages:
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
engines: {node: '>=8'}
- is-stream@3.0.0:
- resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
- is-stream@4.0.1:
- resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
- engines: {node: '>=18'}
-
is-string@1.1.1:
resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==}
engines: {node: '>= 0.4'}
@@ -7845,10 +7405,6 @@ packages:
peerDependencies:
ws: '*'
- issue-parser@7.0.1:
- resolution: {integrity: sha512-3YZcUUR2Wt1WsapF+S/WiA2WmlW0cWAoPccMqne7AxEBhCdFeTPjfv/Axb8V2gyCgY3nRw+ksZ3xSUX+R47iAg==}
- engines: {node: ^18.17 || >=20.6.1}
-
istanbul-lib-coverage@3.2.2:
resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
engines: {node: '>=8'}
@@ -7877,10 +7433,6 @@ packages:
engines: {node: '>=10'}
hasBin: true
- java-properties@1.0.2:
- resolution: {integrity: sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==}
- engines: {node: '>= 0.6.0'}
-
jest-changed-files@30.2.0:
resolution: {integrity: sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
@@ -8077,9 +7629,6 @@ packages:
json-buffer@3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
- json-parse-better-errors@1.0.2:
- resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==}
-
json-parse-even-better-errors@2.3.1:
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
@@ -8212,10 +7761,6 @@ packages:
resolution: {integrity: sha512-NYHA0MRPjvNX+vSw8Xxg6FLKxzAG+e7Pt8RqAQA/EehzHVXq9SxDqJIN3JL1hK0dweb884y8kIh6rkWvPyg9Wg==}
hasBin: true
- load-json-file@4.0.0:
- resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==}
- engines: {node: '>=4'}
-
loader-runner@4.3.1:
resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==}
engines: {node: '>=6.11.5'}
@@ -8224,10 +7769,6 @@ packages:
resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==}
engines: {node: '>=8.9.0'}
- locate-path@2.0.0:
- resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==}
- engines: {node: '>=4'}
-
locate-path@5.0.0:
resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
engines: {node: '>=8'}
@@ -8240,12 +7781,6 @@ packages:
resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- lodash-es@4.18.1:
- resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==}
-
- lodash.capitalize@4.2.1:
- resolution: {integrity: sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==}
-
lodash.clonedeepwith@4.5.0:
resolution: {integrity: sha512-QRBRSxhbtsX1nc0baxSkkK5WlVTTm/s48DSukcGcWZwIyI8Zz+lB+kFiELJXtzfH4Aj6kMWQ1VWW4U5uUDgZMA==}
@@ -8259,12 +7794,6 @@ packages:
resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead.
- lodash.isplainobject@4.0.6:
- resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
-
- lodash.isstring@4.0.1:
- resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
-
lodash.memoize@4.1.2:
resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
@@ -8274,9 +7803,6 @@ packages:
lodash.uniq@4.5.0:
resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==}
- lodash.uniqby@4.7.0:
- resolution: {integrity: sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==}
-
lodash@4.18.1:
resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
@@ -8340,10 +7866,6 @@ packages:
magicast@0.5.2:
resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==}
- make-asynchronous@1.0.1:
- resolution: {integrity: sha512-T9BPOmEOhp6SmV25SwLVcHK4E6JyG/coH3C6F1NjNXSziv/fd4GmsqMk8YR6qpPOswfaOCApSNkZv6fxoaYFcQ==}
- engines: {node: '>=18'}
-
make-dir@2.1.0:
resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==}
engines: {node: '>=6'}
@@ -8373,17 +7895,6 @@ packages:
markdown-table@3.0.4:
resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
- marked-terminal@7.3.0:
- resolution: {integrity: sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw==}
- engines: {node: '>=16.0.0'}
- peerDependencies:
- marked: '>=1 <16'
-
- marked@15.0.12:
- resolution: {integrity: sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==}
- engines: {node: '>= 18'}
- hasBin: true
-
marked@18.0.5:
resolution: {integrity: sha512-S6GcvALHg6K4ohtu4E7x0a1AqhAjp6cV8KhLSyN9qVapnzJkusVBxZRcIU9AeYsbe6P1hKDusSbEOzGyyuce6w==}
engines: {node: '>= 20'}
@@ -8468,10 +7979,6 @@ packages:
memfs@4.51.1:
resolution: {integrity: sha512-Eyt3XrufitN2ZL9c/uIRMyDwXanLI88h/L3MoWqNY747ha3dMR9dWqp8cRT5ntjZ0U1TNuq4U91ZXK0sMBjYOQ==}
- meow@13.2.0:
- resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==}
- engines: {node: '>=18'}
-
merge-descriptors@1.0.3:
resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==}
@@ -8625,19 +8132,10 @@ packages:
engines: {node: '>=4.0.0'}
hasBin: true
- mime@4.1.0:
- resolution: {integrity: sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw==}
- engines: {node: '>=16'}
- hasBin: true
-
mimic-fn@2.1.0:
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
engines: {node: '>=6'}
- mimic-fn@4.0.0:
- resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
- engines: {node: '>=12'}
-
mimic-function@5.0.1:
resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
engines: {node: '>=18'}
@@ -8837,9 +8335,6 @@ packages:
resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==}
engines: {node: '>= 10'}
- nerf-dart@1.0.0:
- resolution: {integrity: sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==}
-
ng-mocks@14.15.1:
resolution: {integrity: sha512-qytFlHgR8YkyH2Hsc6ssGHf817pku6UvV1vpKelh9K07+2IYxfgZJrAyTAGmwH0+9i9hjtdoTrZSP5A4KdQu4Q==}
peerDependencies:
@@ -8882,10 +8377,6 @@ packages:
node-api-version@0.2.1:
resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==}
- node-emoji@2.2.0:
- resolution: {integrity: sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==}
- engines: {node: '>=18'}
-
node-fetch-native@1.6.7:
resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==}
@@ -8937,10 +8428,6 @@ packages:
engines: {node: ^20.17.0 || >=22.9.0}
hasBin: true
- normalize-package-data@6.0.2:
- resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==}
- engines: {node: ^16.14.0 || >=18.0.0}
-
normalize-path@3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
@@ -8949,10 +8436,6 @@ packages:
resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==}
engines: {node: '>=10'}
- normalize-url@8.1.1:
- resolution: {integrity: sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==}
- engines: {node: '>=14.16'}
-
npm-bundled@5.0.0:
resolution: {integrity: sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw==}
engines: {node: ^20.17.0 || >=22.9.0}
@@ -8985,88 +8468,6 @@ packages:
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
engines: {node: '>=8'}
- npm-run-path@5.3.0:
- resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
- npm-run-path@6.0.0:
- resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==}
- engines: {node: '>=18'}
-
- npm@10.9.4:
- resolution: {integrity: sha512-OnUG836FwboQIbqtefDNlyR0gTHzIfwRfE3DuiNewBvnMnWEpB0VEXwBlFVgqpNzIgYo/MHh3d2Hel/pszapAA==}
- engines: {node: ^18.17.0 || >=20.5.0}
- hasBin: true
- bundledDependencies:
- - '@isaacs/string-locale-compare'
- - '@npmcli/arborist'
- - '@npmcli/config'
- - '@npmcli/fs'
- - '@npmcli/map-workspaces'
- - '@npmcli/package-json'
- - '@npmcli/promise-spawn'
- - '@npmcli/redact'
- - '@npmcli/run-script'
- - '@sigstore/tuf'
- - abbrev
- - archy
- - cacache
- - chalk
- - ci-info
- - cli-columns
- - fastest-levenshtein
- - fs-minipass
- - glob
- - graceful-fs
- - hosted-git-info
- - ini
- - init-package-json
- - is-cidr
- - json-parse-even-better-errors
- - libnpmaccess
- - libnpmdiff
- - libnpmexec
- - libnpmfund
- - libnpmhook
- - libnpmorg
- - libnpmpack
- - libnpmpublish
- - libnpmsearch
- - libnpmteam
- - libnpmversion
- - make-fetch-happen
- - minimatch
- - minipass
- - minipass-pipeline
- - ms
- - node-gyp
- - nopt
- - normalize-package-data
- - npm-audit-report
- - npm-install-checks
- - npm-package-arg
- - npm-pick-manifest
- - npm-profile
- - npm-registry-fetch
- - npm-user-validate
- - p-map
- - pacote
- - parse-conflict-json
- - proc-log
- - qrcode-terminal
- - read
- - semver
- - spdx-expression-parse
- - ssri
- - supports-color
- - tar
- - text-table
- - tiny-relative-date
- - treeverse
- - validate-npm-package-name
- - which
- - write-file-atomic
-
nth-check@2.1.1:
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
@@ -9148,10 +8549,6 @@ packages:
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
engines: {node: '>=6'}
- onetime@6.0.0:
- resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
- engines: {node: '>=12'}
-
onetime@7.0.0:
resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
engines: {node: '>=18'}
@@ -9207,26 +8604,6 @@ packages:
resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==}
engines: {node: '>=8'}
- p-each-series@3.0.0:
- resolution: {integrity: sha512-lastgtAdoH9YaLyDa5i5z64q+kzOcQHsQ5SsZJD3q0VEyI8mq872S3geuNbRUQLVAE9siMfgKrpj7MloKFHruw==}
- engines: {node: '>=12'}
-
- p-event@6.0.1:
- resolution: {integrity: sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w==}
- engines: {node: '>=16.17'}
-
- p-filter@4.1.0:
- resolution: {integrity: sha512-37/tPdZ3oJwHaS3gNJdenCDB3Tz26i9sjhnguBtvN0vYlRIiDNnvTWkuh+0hETV9rLPdJ3rlL3yVOYPIAnM8rw==}
- engines: {node: '>=18'}
-
- p-is-promise@3.0.0:
- resolution: {integrity: sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==}
- engines: {node: '>=8'}
-
- p-limit@1.3.0:
- resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==}
- engines: {node: '>=4'}
-
p-limit@2.3.0:
resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
engines: {node: '>=6'}
@@ -9243,10 +8620,6 @@ packages:
resolution: {integrity: sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==}
engines: {node: '>=18'}
- p-locate@2.0.0:
- resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==}
- engines: {node: '>=4'}
-
p-locate@4.1.0:
resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
engines: {node: '>=8'}
@@ -9271,14 +8644,6 @@ packages:
resolution: {integrity: sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==}
engines: {node: '>=18'}
- p-reduce@2.1.0:
- resolution: {integrity: sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==}
- engines: {node: '>=8'}
-
- p-reduce@3.0.0:
- resolution: {integrity: sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==}
- engines: {node: '>=12'}
-
p-retry@6.2.1:
resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==}
engines: {node: '>=16.17'}
@@ -9287,10 +8652,6 @@ packages:
resolution: {integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==}
engines: {node: '>=14.16'}
- p-try@1.0.0:
- resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==}
- engines: {node: '>=4'}
-
p-try@2.2.0:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
@@ -9313,25 +8674,13 @@ packages:
parse-entities@4.0.2:
resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
- parse-json@4.0.0:
- resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==}
- engines: {node: '>=4'}
-
parse-json@5.2.0:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
- parse-json@8.3.0:
- resolution: {integrity: sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==}
- engines: {node: '>=18'}
-
parse-latin@7.0.0:
resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==}
- parse-ms@4.0.0:
- resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==}
- engines: {node: '>=18'}
-
parse-node-version@1.0.1:
resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==}
engines: {node: '>= 0.10'}
@@ -9343,21 +8692,12 @@ packages:
parse5-html-rewriting-stream@8.0.0:
resolution: {integrity: sha512-wzh11mj8KKkno1pZEu+l2EVeWsuKDfR5KNWZOTsslfUX8lPDZx77m9T0kIoAVkFtD1nx6YF8oh4BnPHvxMtNMw==}
- parse5-htmlparser2-tree-adapter@6.0.1:
- resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==}
-
parse5-sax-parser@8.0.0:
resolution: {integrity: sha512-/dQ8UzHZwnrzs3EvDj6IkKrD/jIZyTlB+8XrHJvcjNgRdmWruNdN9i9RK/JtxakmlUdPwKubKPTCqvbTgzGhrw==}
parse5@4.0.0:
resolution: {integrity: sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==}
- parse5@5.1.1:
- resolution: {integrity: sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==}
-
- parse5@6.0.1:
- resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==}
-
parse5@7.3.0:
resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
@@ -9368,10 +8708,6 @@ packages:
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
engines: {node: '>= 0.8'}
- path-exists@3.0.0:
- resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==}
- engines: {node: '>=4'}
-
path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
@@ -9388,10 +8724,6 @@ packages:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
- path-key@4.0.0:
- resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
- engines: {node: '>=12'}
-
path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
@@ -9443,10 +8775,6 @@ packages:
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
engines: {node: '>=0.10.0'}
- pify@3.0.0:
- resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==}
- engines: {node: '>=4'}
-
pify@4.0.1:
resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
engines: {node: '>=6'}
@@ -9467,10 +8795,6 @@ packages:
resolution: {integrity: sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==}
hasBin: true
- pkg-conf@2.1.0:
- resolution: {integrity: sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==}
- engines: {node: '>=4'}
-
pkg-dir@4.2.0:
resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
engines: {node: '>=8'}
@@ -9823,10 +9147,6 @@ packages:
resolution: {integrity: sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
- pretty-ms@9.3.0:
- resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==}
- engines: {node: '>=18'}
-
prismjs@1.30.0:
resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
engines: {node: '>=6'}
@@ -9869,9 +9189,6 @@ packages:
property-information@7.1.0:
resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
- proto-list@1.2.4:
- resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
-
proxy-addr@2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'}
@@ -9957,14 +9274,6 @@ packages:
read-cache@1.0.0:
resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
- read-package-up@11.0.0:
- resolution: {integrity: sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==}
- engines: {node: '>=18'}
-
- read-pkg@9.0.1:
- resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==}
- engines: {node: '>=18'}
-
readable-stream@2.3.8:
resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
@@ -10029,10 +9338,6 @@ packages:
resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==}
engines: {node: '>=4'}
- registry-auth-token@5.1.0:
- resolution: {integrity: sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==}
- engines: {node: '>=14'}
-
regjsgen@0.8.0:
resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==}
@@ -10421,20 +9726,6 @@ packages:
resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==}
engines: {node: '>=10'}
- semantic-release@24.2.9:
- resolution: {integrity: sha512-phCkJ6pjDi9ANdhuF5ElS10GGdAKY6R1Pvt9lT3SFhOwM4T7QZE7MLpBDbNruUx/Q3gFD92/UOFringGipRqZA==}
- engines: {node: '>=20.8.1'}
- hasBin: true
-
- semver-diff@5.0.0:
- resolution: {integrity: sha512-0HbGtOm+S7T6NGQ/pxJSJipJvc4DK3FcRVMRkhsIwJDJ4Jcz5DQC1cPPzB5GhzyHjwttW878HaWQq46CkL3cqg==}
- engines: {node: '>=12'}
- deprecated: Deprecated as the semver package now supports this built-in.
-
- semver-regex@4.0.5:
- resolution: {integrity: sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==}
- engines: {node: '>=12'}
-
semver@5.7.2:
resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
hasBin: true
@@ -10563,10 +9854,6 @@ packages:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'}
- signale@1.4.0:
- resolution: {integrity: sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==}
- engines: {node: '>=6'}
-
sigstore@4.1.0:
resolution: {integrity: sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==}
engines: {node: ^20.17.0 || >=22.9.0}
@@ -10589,10 +9876,6 @@ packages:
engines: {node: '>=14.0.0', npm: '>=6.0.0'}
hasBin: true
- skin-tone@2.0.0:
- resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==}
- engines: {node: '>=8'}
-
slash@3.0.0:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
@@ -10665,18 +9948,9 @@ packages:
space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
- spawn-error-forwarder@1.0.0:
- resolution: {integrity: sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==}
-
- spdx-correct@3.2.0:
- resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
-
spdx-exceptions@2.5.0:
resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==}
- spdx-expression-parse@3.0.1:
- resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
-
spdx-expression-parse@4.0.0:
resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==}
@@ -10690,9 +9964,6 @@ packages:
resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==}
engines: {node: '>=6.0.0'}
- split2@1.0.0:
- resolution: {integrity: sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==}
-
sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
@@ -10731,9 +10002,6 @@ packages:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'}
- stream-combiner2@1.1.1:
- resolution: {integrity: sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==}
-
stream-replace-string@2.0.0:
resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==}
@@ -10802,14 +10070,6 @@ packages:
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
engines: {node: '>=6'}
- strip-final-newline@3.0.0:
- resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
- engines: {node: '>=12'}
-
- strip-final-newline@4.0.0:
- resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==}
- engines: {node: '>=18'}
-
strip-json-comments@2.0.1:
resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
engines: {node: '>=0.10.0'}
@@ -10845,14 +10105,6 @@ packages:
resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==}
engines: {node: '>= 8.0'}
- super-regex@1.1.0:
- resolution: {integrity: sha512-WHkws2ZflZe41zj6AolvvmaTrWds/VuyeYr9iPVv/oQeaIoVxMKaushfFWpOGDT+GuBrM/sVqF8KUCYQlSSTdQ==}
- engines: {node: '>=18'}
-
- supports-color@5.5.0:
- resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
- engines: {node: '>=4'}
-
supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
@@ -10861,10 +10113,6 @@ packages:
resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
engines: {node: '>=10'}
- supports-hyperlinks@3.2.0:
- resolution: {integrity: sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==}
- engines: {node: '>=14.18'}
-
supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
@@ -10919,10 +10167,6 @@ packages:
resolution: {integrity: sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg==}
engines: {node: '>=18'}
- temp-dir@3.0.0:
- resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==}
- engines: {node: '>=14.16'}
-
temp-file@3.4.0:
resolution: {integrity: sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==}
@@ -10930,14 +10174,6 @@ packages:
resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==}
engines: {node: '>=6.0.0'}
- tempfile@5.0.0:
- resolution: {integrity: sha512-bX655WZI/F7EoTDw9JvQURqAXiPHi8o8+yFxPF2lWYyz1aHnmMRuXWqL6YB6GmeO0o4DIYWHLgGNi/X64T+X4Q==}
- engines: {node: '>=14.18'}
-
- tempy@3.1.0:
- resolution: {integrity: sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==}
- engines: {node: '>=14.16'}
-
terser-webpack-plugin@5.3.16:
resolution: {integrity: sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==}
engines: {node: '>= 10.13.0'}
@@ -10976,16 +10212,9 @@ packages:
peerDependencies:
tslib: ^2
- through2@2.0.5:
- resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==}
-
thunky@1.1.0:
resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==}
- time-span@5.1.0:
- resolution: {integrity: sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==}
- engines: {node: '>=12'}
-
tiny-async-pool@1.3.0:
resolution: {integrity: sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA==}
@@ -11043,10 +10272,6 @@ packages:
resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==}
engines: {node: '>=18'}
- traverse@0.6.8:
- resolution: {integrity: sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==}
- engines: {node: '>= 0.4'}
-
tree-dump@1.1.0:
resolution: {integrity: sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==}
engines: {node: '>=10.0'}
@@ -11188,14 +10413,6 @@ packages:
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
engines: {node: '>=10'}
- type-fest@1.4.0:
- resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==}
- engines: {node: '>=10'}
-
- type-fest@2.19.0:
- resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
- engines: {node: '>=12.20'}
-
type-fest@4.41.0:
resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
engines: {node: '>=16'}
@@ -11275,10 +10492,6 @@ packages:
resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==}
engines: {node: '>=4'}
- unicode-emoji-modifier-base@1.0.0:
- resolution: {integrity: sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==}
- engines: {node: '>=4'}
-
unicode-match-property-ecmascript@2.0.0:
resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==}
engines: {node: '>=4'}
@@ -11291,10 +10504,6 @@ packages:
resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==}
engines: {node: '>=4'}
- unicorn-magic@0.1.0:
- resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==}
- engines: {node: '>=18'}
-
unicorn-magic@0.3.0:
resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==}
engines: {node: '>=18'}
@@ -11325,10 +10534,6 @@ packages:
resolution: {integrity: sha512-4Lup7Ezn8W3d52/xBhZBVdx323ckxa7DEvd9kPQHppTkLoJXw6ltrBCyj5pnrxj0qKDxYMJ56CoxNuFCscdTiw==}
engines: {node: ^20.17.0 || >=22.9.0}
- unique-string@3.0.0:
- resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==}
- engines: {node: '>=12'}
-
unist-util-find-after@5.0.0:
resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==}
@@ -11359,9 +10564,6 @@ packages:
unist-util-visit@5.1.0:
resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==}
- universal-user-agent@7.0.3:
- resolution: {integrity: sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==}
-
universalify@0.1.2:
resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
engines: {node: '>= 4.0.0'}
@@ -11455,10 +10657,6 @@ packages:
url-join@4.0.1:
resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==}
- url-join@5.0.0:
- resolution: {integrity: sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
url-toolkit@2.2.5:
resolution: {integrity: sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg==}
@@ -11489,9 +10687,6 @@ packages:
resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==}
engines: {node: '>=10.12.0'}
- validate-npm-package-license@3.0.4:
- resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
-
validate-npm-package-name@7.0.2:
resolution: {integrity: sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==}
engines: {node: ^20.17.0 || >=22.9.0}
@@ -11656,9 +10851,6 @@ packages:
web-namespaces@2.0.1:
resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
- web-worker@1.2.0:
- resolution: {integrity: sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==}
-
webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
@@ -11870,10 +11062,6 @@ packages:
xmlchars@2.2.0:
resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
- xtend@4.0.2:
- resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
- engines: {node: '>=0.4'}
-
xxhash-wasm@1.1.0:
resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==}
@@ -11912,10 +11100,6 @@ packages:
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
engines: {node: '>=6'}
- yargs-parser@20.2.9:
- resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
- engines: {node: '>=10'}
-
yargs-parser@21.1.1:
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
engines: {node: '>=12'}
@@ -11928,10 +11112,6 @@ packages:
resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
engines: {node: '>=8'}
- yargs@16.2.0:
- resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
- engines: {node: '>=10'}
-
yargs@17.7.2:
resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
engines: {node: '>=12'}
@@ -13583,17 +12763,6 @@ snapshots:
'@colordx/core@5.4.3': {}
- '@colors/colors@1.5.0':
- optional: true
-
- '@conventional-changelog/git-client@1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1)':
- dependencies:
- '@types/semver': 7.7.1
- semver: 7.7.4
- optionalDependencies:
- conventional-commits-filter: 5.0.0
- conventional-commits-parser: 6.2.1
-
'@cspotcode/source-map-support@0.8.1':
dependencies:
'@jridgewell/trace-mapping': 0.3.9
@@ -14150,8 +13319,6 @@ snapshots:
'@humanwhocodes/retry@0.4.3': {}
- '@hutson/parse-repository-url@5.0.0': {}
-
'@img/colour@1.0.0': {}
'@img/sharp-darwin-arm64@0.34.5':
@@ -15839,71 +15006,6 @@ snapshots:
- '@swc/core'
- debug
- '@octokit/auth-token@6.0.0': {}
-
- '@octokit/core@7.0.6':
- dependencies:
- '@octokit/auth-token': 6.0.0
- '@octokit/graphql': 9.0.3
- '@octokit/request': 10.0.7
- '@octokit/request-error': 7.1.0
- '@octokit/types': 16.0.0
- before-after-hook: 4.0.0
- universal-user-agent: 7.0.3
-
- '@octokit/endpoint@11.0.2':
- dependencies:
- '@octokit/types': 16.0.0
- universal-user-agent: 7.0.3
-
- '@octokit/graphql@9.0.3':
- dependencies:
- '@octokit/request': 10.0.7
- '@octokit/types': 16.0.0
- universal-user-agent: 7.0.3
-
- '@octokit/openapi-types@26.0.0': {}
-
- '@octokit/openapi-types@27.0.0': {}
-
- '@octokit/plugin-paginate-rest@13.2.1(@octokit/core@7.0.6)':
- dependencies:
- '@octokit/core': 7.0.6
- '@octokit/types': 15.0.2
-
- '@octokit/plugin-retry@8.0.3(@octokit/core@7.0.6)':
- dependencies:
- '@octokit/core': 7.0.6
- '@octokit/request-error': 7.1.0
- '@octokit/types': 16.0.0
- bottleneck: 2.19.5
-
- '@octokit/plugin-throttling@11.0.3(@octokit/core@7.0.6)':
- dependencies:
- '@octokit/core': 7.0.6
- '@octokit/types': 16.0.0
- bottleneck: 2.19.5
-
- '@octokit/request-error@7.1.0':
- dependencies:
- '@octokit/types': 16.0.0
-
- '@octokit/request@10.0.7':
- dependencies:
- '@octokit/endpoint': 11.0.2
- '@octokit/request-error': 7.1.0
- '@octokit/types': 16.0.0
- fast-content-type-parse: 3.0.0
- universal-user-agent: 7.0.3
-
- '@octokit/types@15.0.2':
- dependencies:
- '@octokit/openapi-types': 26.0.0
-
- '@octokit/types@16.0.0':
- dependencies:
- '@octokit/openapi-types': 27.0.0
-
'@oslojs/encoding@1.1.0': {}
'@oxc-project/types@0.113.0': {}
@@ -16046,18 +15148,6 @@ snapshots:
dependencies:
playwright: 1.57.0
- '@pnpm/config.env-replace@1.1.0': {}
-
- '@pnpm/network.ca-file@1.0.2':
- dependencies:
- graceful-fs: 4.2.10
-
- '@pnpm/npm-conf@2.3.1':
- dependencies:
- '@pnpm/config.env-replace': 1.1.0
- '@pnpm/network.ca-file': 1.0.2
- config-chain: 1.1.13
-
'@rolldown/binding-android-arm64@1.0.0-rc.4':
optional: true
@@ -16280,120 +15370,6 @@ snapshots:
transitivePeerDependencies:
- chokidar
- '@sec-ant/readable-stream@0.4.1': {}
-
- '@semantic-release/changelog@6.0.3(semantic-release@24.2.9(typescript@5.9.3))':
- dependencies:
- '@semantic-release/error': 3.0.0
- aggregate-error: 3.1.0
- fs-extra: 11.3.3
- lodash: 4.18.1
- semantic-release: 24.2.9(typescript@5.9.3)
-
- '@semantic-release/commit-analyzer@13.0.1(semantic-release@24.2.9(typescript@5.9.3))':
- dependencies:
- conventional-changelog-angular: 8.1.0
- conventional-changelog-writer: 8.2.0
- conventional-commits-filter: 5.0.0
- conventional-commits-parser: 6.2.1
- debug: 4.4.3
- import-from-esm: 2.0.0
- lodash-es: 4.18.1
- micromatch: 4.0.8
- semantic-release: 24.2.9(typescript@5.9.3)
- transitivePeerDependencies:
- - supports-color
-
- '@semantic-release/error@3.0.0': {}
-
- '@semantic-release/error@4.0.0': {}
-
- '@semantic-release/git@10.0.1(semantic-release@24.2.9(typescript@5.9.3))':
- dependencies:
- '@semantic-release/error': 3.0.0
- aggregate-error: 3.1.0
- debug: 4.4.3
- dir-glob: 3.0.1
- execa: 5.1.1
- lodash: 4.18.1
- micromatch: 4.0.8
- p-reduce: 2.1.0
- semantic-release: 24.2.9(typescript@5.9.3)
- transitivePeerDependencies:
- - supports-color
-
- '@semantic-release/github@11.0.6(semantic-release@24.2.9(typescript@5.9.3))':
- dependencies:
- '@octokit/core': 7.0.6
- '@octokit/plugin-paginate-rest': 13.2.1(@octokit/core@7.0.6)
- '@octokit/plugin-retry': 8.0.3(@octokit/core@7.0.6)
- '@octokit/plugin-throttling': 11.0.3(@octokit/core@7.0.6)
- '@semantic-release/error': 4.0.0
- aggregate-error: 5.0.0
- debug: 4.4.3
- dir-glob: 3.0.1
- http-proxy-agent: 7.0.2
- https-proxy-agent: 7.0.6
- issue-parser: 7.0.1
- lodash-es: 4.18.1
- mime: 4.1.0
- p-filter: 4.1.0
- semantic-release: 24.2.9(typescript@5.9.3)
- tinyglobby: 0.2.15
- url-join: 5.0.0
- transitivePeerDependencies:
- - supports-color
-
- '@semantic-release/npm@12.0.1(semantic-release@24.2.9(typescript@5.9.3))':
- dependencies:
- '@semantic-release/error': 4.0.0
- aggregate-error: 5.0.0
- execa: 9.6.1
- fs-extra: 11.3.3
- lodash-es: 4.18.1
- nerf-dart: 1.0.0
- normalize-url: 8.1.1
- npm: 10.9.4
- rc: 1.2.8
- read-pkg: 9.0.1
- registry-auth-token: 5.1.0
- semantic-release: 24.2.9(typescript@5.9.3)
- semver: 7.7.3
- tempy: 3.1.0
-
- '@semantic-release/npm@12.0.2(semantic-release@24.2.9(typescript@5.9.3))':
- dependencies:
- '@semantic-release/error': 4.0.0
- aggregate-error: 5.0.0
- execa: 9.6.1
- fs-extra: 11.3.3
- lodash-es: 4.18.1
- nerf-dart: 1.0.0
- normalize-url: 8.1.1
- npm: 10.9.4
- rc: 1.2.8
- read-pkg: 9.0.1
- registry-auth-token: 5.1.0
- semantic-release: 24.2.9(typescript@5.9.3)
- semver: 7.7.4
- tempy: 3.1.0
-
- '@semantic-release/release-notes-generator@14.1.0(semantic-release@24.2.9(typescript@5.9.3))':
- dependencies:
- conventional-changelog-angular: 8.1.0
- conventional-changelog-writer: 8.2.0
- conventional-commits-filter: 5.0.0
- conventional-commits-parser: 6.2.1
- debug: 4.4.3
- get-stream: 7.0.1
- import-from-esm: 2.0.0
- into-stream: 7.0.0
- lodash-es: 4.18.1
- read-package-up: 11.0.0
- semantic-release: 24.2.9(typescript@5.9.3)
- transitivePeerDependencies:
- - supports-color
-
'@shikijs/core@3.22.0':
dependencies:
'@shikijs/types': 3.22.0
@@ -16465,8 +15441,6 @@ snapshots:
'@sindresorhus/merge-streams@2.3.0': {}
- '@sindresorhus/merge-streams@4.0.0': {}
-
'@sinonjs/commons@3.0.1':
dependencies:
type-detect: 4.0.8
@@ -16776,8 +15750,6 @@ snapshots:
dependencies:
undici-types: 7.18.2
- '@types/normalize-package-data@2.4.4': {}
-
'@types/parse-json@4.0.2': {}
'@types/plist@3.0.5':
@@ -16802,8 +15774,6 @@ snapshots:
'@types/semver@7.5.8': {}
- '@types/semver@7.7.1': {}
-
'@types/send@0.17.6':
dependencies:
'@types/mime': 1.3.5
@@ -17179,8 +16149,6 @@ snapshots:
acorn@8.15.0: {}
- add-stream@1.0.0: {}
-
address@1.2.2: {}
adm-zip@0.5.10: {}
@@ -17218,11 +16186,6 @@ snapshots:
clean-stack: 2.2.0
indent-string: 4.0.0
- aggregate-error@5.0.0:
- dependencies:
- clean-stack: 5.3.0
- indent-string: 5.0.0
-
ajv-formats@2.1.1(ajv@8.18.0):
optionalDependencies:
ajv: 8.18.0
@@ -17328,10 +16291,6 @@ snapshots:
ansi-regex@6.2.2: {}
- ansi-styles@3.2.1:
- dependencies:
- color-convert: 1.9.3
-
ansi-styles@4.3.0:
dependencies:
color-convert: 2.0.1
@@ -17400,8 +16359,6 @@ snapshots:
argparse@2.0.1: {}
- argv-formatter@1.0.0: {}
-
aria-query@5.3.2: {}
array-buffer-byte-length@1.0.2:
@@ -17411,8 +16368,6 @@ snapshots:
array-flatten@1.1.1: {}
- array-ify@1.0.0: {}
-
array-includes@3.1.9:
dependencies:
call-bind: 1.0.8
@@ -17792,8 +16747,6 @@ snapshots:
postcss-media-query-parser: 0.2.3
postcss-safe-parser: 7.0.1(postcss@8.5.6)
- before-after-hook@4.0.0: {}
-
better-sqlite3@12.9.0:
dependencies:
bindings: 1.5.0
@@ -17851,8 +16804,6 @@ snapshots:
boolbase@1.0.0: {}
- bottleneck@2.19.5: {}
-
boxen@8.0.1:
dependencies:
ansi-align: 3.0.1
@@ -18047,12 +16998,6 @@ snapshots:
ccount@2.0.1: {}
- chalk@2.4.2:
- dependencies:
- ansi-styles: 3.2.1
- escape-string-regexp: 1.0.5
- supports-color: 5.5.0
-
chalk@3.0.0:
dependencies:
ansi-styles: 4.3.0
@@ -18115,10 +17060,6 @@ snapshots:
clean-stack@2.2.0: {}
- clean-stack@5.3.0:
- dependencies:
- escape-string-regexp: 5.0.0
-
cli-boxes@3.0.0: {}
cli-cursor@3.1.0:
@@ -18129,27 +17070,12 @@ snapshots:
dependencies:
restore-cursor: 5.1.0
- cli-highlight@2.1.11:
- dependencies:
- chalk: 4.1.2
- highlight.js: 10.7.3
- mz: 2.7.0
- parse5: 5.1.1
- parse5-htmlparser2-tree-adapter: 6.0.1
- yargs: 16.2.0
-
cli-spinners@2.6.1: {}
cli-spinners@2.9.2: {}
cli-spinners@3.4.0: {}
- cli-table3@0.6.5:
- dependencies:
- string-width: 4.2.3
- optionalDependencies:
- '@colors/colors': 1.5.0
-
cli-truncate@2.1.0:
dependencies:
slice-ansi: 3.0.0
@@ -18169,12 +17095,6 @@ snapshots:
strip-ansi: 6.0.1
wrap-ansi: 6.2.0
- cliui@7.0.4:
- dependencies:
- string-width: 4.2.3
- strip-ansi: 6.0.1
- wrap-ansi: 7.0.0
-
cliui@8.0.1:
dependencies:
string-width: 4.2.3
@@ -18207,16 +17127,10 @@ snapshots:
collect-v8-coverage@1.0.3: {}
- color-convert@1.9.3:
- dependencies:
- color-name: 1.1.3
-
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
- color-name@1.1.3: {}
-
color-name@1.1.4: {}
colorette@2.0.20: {}
@@ -18249,11 +17163,6 @@ snapshots:
common-path-prefix@3.0.0: {}
- compare-func@2.0.0:
- dependencies:
- array-ify: 1.0.0
- dot-prop: 5.3.0
-
compare-version@0.1.2: {}
compressible@2.0.18:
@@ -18274,11 +17183,6 @@ snapshots:
concat-map@0.0.1: {}
- config-chain@1.1.13:
- dependencies:
- ini: 1.3.8
- proto-list: 1.2.4
-
config-file-ts@0.2.8-rc1:
dependencies:
glob: 10.5.0
@@ -18296,87 +17200,6 @@ snapshots:
content-type@1.0.5: {}
- conventional-changelog-angular@8.1.0:
- dependencies:
- compare-func: 2.0.0
-
- conventional-changelog-atom@5.0.0: {}
-
- conventional-changelog-cli@5.0.0(conventional-commits-filter@5.0.0):
- dependencies:
- add-stream: 1.0.0
- conventional-changelog: 6.0.0(conventional-commits-filter@5.0.0)
- meow: 13.2.0
- tempfile: 5.0.0
- transitivePeerDependencies:
- - conventional-commits-filter
-
- conventional-changelog-codemirror@5.0.0: {}
-
- conventional-changelog-conventionalcommits@8.0.0:
- dependencies:
- compare-func: 2.0.0
-
- conventional-changelog-core@8.0.0(conventional-commits-filter@5.0.0):
- dependencies:
- '@hutson/parse-repository-url': 5.0.0
- add-stream: 1.0.0
- conventional-changelog-writer: 8.2.0
- conventional-commits-parser: 6.2.1
- git-raw-commits: 5.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1)
- git-semver-tags: 8.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1)
- hosted-git-info: 7.0.2
- normalize-package-data: 6.0.2
- read-package-up: 11.0.0
- read-pkg: 9.0.1
- transitivePeerDependencies:
- - conventional-commits-filter
-
- conventional-changelog-ember@5.0.0: {}
-
- conventional-changelog-eslint@6.0.0: {}
-
- conventional-changelog-express@5.0.0: {}
-
- conventional-changelog-jquery@6.0.0: {}
-
- conventional-changelog-jshint@5.0.0:
- dependencies:
- compare-func: 2.0.0
-
- conventional-changelog-preset-loader@5.0.0: {}
-
- conventional-changelog-writer@8.2.0:
- dependencies:
- conventional-commits-filter: 5.0.0
- handlebars: 4.7.8
- meow: 13.2.0
- semver: 7.7.4
-
- conventional-changelog@6.0.0(conventional-commits-filter@5.0.0):
- dependencies:
- conventional-changelog-angular: 8.1.0
- conventional-changelog-atom: 5.0.0
- conventional-changelog-codemirror: 5.0.0
- conventional-changelog-conventionalcommits: 8.0.0
- conventional-changelog-core: 8.0.0(conventional-commits-filter@5.0.0)
- conventional-changelog-ember: 5.0.0
- conventional-changelog-eslint: 6.0.0
- conventional-changelog-express: 5.0.0
- conventional-changelog-jquery: 6.0.0
- conventional-changelog-jshint: 5.0.0
- conventional-changelog-preset-loader: 5.0.0
- transitivePeerDependencies:
- - conventional-commits-filter
-
- conventional-commits-filter@5.0.0: {}
-
- conventional-commits-parser@6.2.1:
- dependencies:
- meow: 13.2.0
-
- convert-hrtime@5.0.0: {}
-
convert-source-map@1.9.0: {}
convert-source-map@2.0.0: {}
@@ -18485,10 +17308,6 @@ snapshots:
dependencies:
uncrypto: 0.1.3
- crypto-random-string@4.0.0:
- dependencies:
- type-fest: 1.4.0
-
css-declaration-sorter@7.3.1(postcss@8.5.6):
dependencies:
postcss: 8.5.6
@@ -18753,10 +17572,6 @@ snapshots:
minimatch: 3.1.2
p-limit: 3.1.0
- dir-glob@3.0.1:
- dependencies:
- path-type: 4.0.0
-
dlv@1.1.3: {}
dmg-builder@26.0.12(electron-builder-squirrel-windows@26.0.12):
@@ -18814,10 +17629,6 @@ snapshots:
domelementtype: 2.3.0
domhandler: 5.0.3
- dot-prop@5.3.0:
- dependencies:
- is-obj: 2.0.0
-
dotenv-expand@11.0.7:
dependencies:
dotenv: 16.6.1
@@ -18852,10 +17663,6 @@ snapshots:
es-errors: 1.3.0
gopd: 1.2.0
- duplexer2@0.1.4:
- dependencies:
- readable-stream: 2.3.8
-
eastasianwidth@0.2.0: {}
ee-first@1.1.1: {}
@@ -18960,8 +17767,6 @@ snapshots:
emoji-regex@9.2.2: {}
- emojilib@2.4.0: {}
-
emojis-list@3.0.0: {}
encodeurl@2.0.0: {}
@@ -18987,11 +17792,6 @@ snapshots:
entities@6.0.1: {}
- env-ci@11.2.0:
- dependencies:
- execa: 8.0.1
- java-properties: 1.0.2
-
env-paths@2.2.1: {}
env-paths@3.0.0: {}
@@ -19467,33 +18267,6 @@ snapshots:
signal-exit: 3.0.7
strip-final-newline: 2.0.0
- execa@8.0.1:
- dependencies:
- cross-spawn: 7.0.6
- get-stream: 8.0.1
- human-signals: 5.0.0
- is-stream: 3.0.0
- merge-stream: 2.0.0
- npm-run-path: 5.3.0
- onetime: 6.0.0
- signal-exit: 4.1.0
- strip-final-newline: 3.0.0
-
- execa@9.6.1:
- dependencies:
- '@sindresorhus/merge-streams': 4.0.0
- cross-spawn: 7.0.6
- figures: 6.1.0
- get-stream: 9.0.1
- human-signals: 8.0.1
- is-plain-obj: 4.1.0
- is-stream: 4.0.1
- npm-run-path: 6.0.0
- pretty-ms: 9.3.0
- signal-exit: 4.1.0
- strip-final-newline: 4.0.0
- yoctocolors: 2.1.2
-
exit-x@0.2.2: {}
expand-template@2.0.3: {}
@@ -19592,8 +18365,6 @@ snapshots:
extsprintf@1.4.1:
optional: true
- fast-content-type-parse@3.0.0: {}
-
fast-deep-equal@3.1.3: {}
fast-glob@3.3.3:
@@ -19626,18 +18397,10 @@ snapshots:
optionalDependencies:
picomatch: 4.0.4
- figures@2.0.0:
- dependencies:
- escape-string-regexp: 1.0.5
-
figures@3.2.0:
dependencies:
escape-string-regexp: 1.0.5
- figures@6.1.0:
- dependencies:
- is-unicode-supported: 2.1.0
-
file-entry-cache@8.0.0:
dependencies:
flat-cache: 4.0.1
@@ -19688,12 +18451,6 @@ snapshots:
dependencies:
find-file-up: 2.0.1
- find-up-simple@1.0.1: {}
-
- find-up@2.1.0:
- dependencies:
- locate-path: 2.0.0
-
find-up@4.1.0:
dependencies:
locate-path: 5.0.0
@@ -19709,11 +18466,6 @@ snapshots:
locate-path: 7.2.0
path-exists: 5.0.0
- find-versions@6.0.0:
- dependencies:
- semver-regex: 4.0.5
- super-regex: 1.1.0
-
fix-path@5.0.0:
dependencies:
shell-path: 3.1.0
@@ -19784,11 +18536,6 @@ snapshots:
fresh@2.0.0: {}
- from2@2.3.0:
- dependencies:
- inherits: 2.0.4
- readable-stream: 2.3.8
-
fs-constants@1.0.0: {}
fs-extra@10.1.0:
@@ -19797,12 +18544,6 @@ snapshots:
jsonfile: 6.2.0
universalify: 2.0.1
- fs-extra@11.3.3:
- dependencies:
- graceful-fs: 4.2.11
- jsonfile: 6.2.0
- universalify: 2.0.1
-
fs-extra@11.3.5:
dependencies:
graceful-fs: 4.2.11
@@ -19848,8 +18589,6 @@ snapshots:
function-bind@1.1.2: {}
- function-timeout@1.0.2: {}
-
function.prototype.name@1.1.8:
dependencies:
call-bind: 1.0.8
@@ -19897,15 +18636,6 @@ snapshots:
get-stream@6.0.1: {}
- get-stream@7.0.1: {}
-
- get-stream@8.0.1: {}
-
- get-stream@9.0.1:
- dependencies:
- '@sec-ant/readable-stream': 0.4.1
- is-stream: 4.0.1
-
get-symbol-description@1.1.0:
dependencies:
call-bound: 1.0.4
@@ -19916,31 +18646,6 @@ snapshots:
dependencies:
resolve-pkg-maps: 1.0.0
- git-log-parser@1.2.1:
- dependencies:
- argv-formatter: 1.0.0
- spawn-error-forwarder: 1.0.0
- split2: 1.0.0
- stream-combiner2: 1.1.1
- through2: 2.0.5
- traverse: 0.6.8
-
- git-raw-commits@5.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1):
- dependencies:
- '@conventional-changelog/git-client': 1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1)
- meow: 13.2.0
- transitivePeerDependencies:
- - conventional-commits-filter
- - conventional-commits-parser
-
- git-semver-tags@8.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1):
- dependencies:
- '@conventional-changelog/git-client': 1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1)
- meow: 13.2.0
- transitivePeerDependencies:
- - conventional-commits-filter
- - conventional-commits-parser
-
github-from-package@0.0.0: {}
github-slugger@2.0.0: {}
@@ -20048,8 +18753,6 @@ snapshots:
p-cancelable: 2.1.1
responselike: 2.0.1
- graceful-fs@4.2.10: {}
-
graceful-fs@4.2.11: {}
h3@1.15.10:
@@ -20079,8 +18782,6 @@ snapshots:
has-bigints@1.1.0: {}
- has-flag@3.0.0: {}
-
has-flag@4.0.0: {}
has-property-descriptors@1.0.2:
@@ -20235,8 +18936,6 @@ snapshots:
he@1.2.0: {}
- highlight.js@10.7.3: {}
-
hls.js@1.6.13: {}
homedir-polyfill@1.0.3:
@@ -20245,20 +18944,10 @@ snapshots:
hono@4.12.14: {}
- hook-std@4.0.0: {}
-
hosted-git-info@4.1.0:
dependencies:
lru-cache: 6.0.0
- hosted-git-info@7.0.2:
- dependencies:
- lru-cache: 10.4.3
-
- hosted-git-info@8.1.0:
- dependencies:
- lru-cache: 10.4.3
-
hosted-git-info@9.0.2:
dependencies:
lru-cache: 11.2.4
@@ -20425,10 +19114,6 @@ snapshots:
human-signals@2.1.0: {}
- human-signals@5.0.0: {}
-
- human-signals@8.0.1: {}
-
humanize-ms@1.2.1:
dependencies:
ms: 2.1.3
@@ -20481,13 +19166,6 @@ snapshots:
parent-module: 1.0.1
resolve-from: 4.0.0
- import-from-esm@2.0.0:
- dependencies:
- debug: 4.4.3
- import-meta-resolve: 4.2.0
- transitivePeerDependencies:
- - supports-color
-
import-local@3.2.0:
dependencies:
pkg-dir: 4.2.0
@@ -20499,10 +19177,6 @@ snapshots:
indent-string@4.0.0: {}
- indent-string@5.0.0: {}
-
- index-to-position@1.2.0: {}
-
individual@2.0.0: {}
infer-owner@1.0.4: {}
@@ -20528,11 +19202,6 @@ snapshots:
hasown: 2.0.3
side-channel: 1.1.0
- into-stream@7.0.0:
- dependencies:
- from2: 2.3.0
- p-is-promise: 3.0.0
-
ip-address@10.1.0: {}
ip-address@10.2.0: {}
@@ -20661,8 +19330,6 @@ snapshots:
is-number@7.0.0: {}
- is-obj@2.0.0: {}
-
is-plain-obj@3.0.0: {}
is-plain-obj@4.1.0: {}
@@ -20692,10 +19359,6 @@ snapshots:
is-stream@2.0.1: {}
- is-stream@3.0.0: {}
-
- is-stream@4.0.1: {}
-
is-string@1.1.1:
dependencies:
call-bound: 1.0.4
@@ -20756,14 +19419,6 @@ snapshots:
dependencies:
ws: 8.18.0
- issue-parser@7.0.1:
- dependencies:
- lodash.capitalize: 4.2.1
- lodash.escaperegexp: 4.1.2
- lodash.isplainobject: 4.0.6
- lodash.isstring: 4.0.1
- lodash.uniqby: 4.7.0
-
istanbul-lib-coverage@3.2.2: {}
istanbul-lib-instrument@6.0.3:
@@ -20807,8 +19462,6 @@ snapshots:
filelist: 1.0.4
picocolors: 1.1.1
- java-properties@1.0.2: {}
-
jest-changed-files@30.2.0:
dependencies:
execa: 5.1.1
@@ -21214,8 +19867,6 @@ snapshots:
json-buffer@3.0.1: {}
- json-parse-better-errors@1.0.2: {}
-
json-parse-even-better-errors@2.3.1: {}
json-parse-even-better-errors@5.0.0: {}
@@ -21368,13 +20019,6 @@ snapshots:
'@lmdb/lmdb-win32-x64': 3.5.1
optional: true
- load-json-file@4.0.0:
- dependencies:
- graceful-fs: 4.2.11
- parse-json: 4.0.0
- pify: 3.0.0
- strip-bom: 3.0.0
-
loader-runner@4.3.1: {}
loader-utils@2.0.4:
@@ -21383,11 +20027,6 @@ snapshots:
emojis-list: 3.0.0
json5: 2.2.3
- locate-path@2.0.0:
- dependencies:
- p-locate: 2.0.0
- path-exists: 3.0.0
-
locate-path@5.0.0:
dependencies:
p-locate: 4.1.0
@@ -21400,10 +20039,6 @@ snapshots:
dependencies:
p-locate: 6.0.0
- lodash-es@4.18.1: {}
-
- lodash.capitalize@4.2.1: {}
-
lodash.clonedeepwith@4.5.0: {}
lodash.debounce@4.0.8: {}
@@ -21412,18 +20047,12 @@ snapshots:
lodash.isequal@4.5.0: {}
- lodash.isplainobject@4.0.6: {}
-
- lodash.isstring@4.0.1: {}
-
lodash.memoize@4.1.2: {}
lodash.merge@4.6.2: {}
lodash.uniq@4.5.0: {}
- lodash.uniqby@4.7.0: {}
-
lodash@4.18.1: {}
log-symbols@4.1.0:
@@ -21498,12 +20127,6 @@ snapshots:
'@babel/types': 7.29.0
source-map-js: 1.2.1
- make-asynchronous@1.0.1:
- dependencies:
- p-event: 6.0.1
- type-fest: 4.41.0
- web-worker: 1.2.0
-
make-dir@2.1.0:
dependencies:
pify: 4.0.1
@@ -21562,19 +20185,6 @@ snapshots:
markdown-table@3.0.4: {}
- marked-terminal@7.3.0(marked@15.0.12):
- dependencies:
- ansi-escapes: 7.2.0
- ansi-regex: 6.2.2
- chalk: 5.6.2
- cli-highlight: 2.1.11
- cli-table3: 0.6.5
- marked: 15.0.12
- node-emoji: 2.2.0
- supports-hyperlinks: 3.2.0
-
- marked@15.0.12: {}
-
marked@18.0.5: {}
material-design-icons-iconfont@6.7.0: {}
@@ -21771,8 +20381,6 @@ snapshots:
tree-dump: 1.1.0(tslib@2.8.1)
tslib: 2.8.1
- meow@13.2.0: {}
-
merge-descriptors@1.0.3: {}
merge-descriptors@2.0.0: {}
@@ -22068,12 +20676,8 @@ snapshots:
mime@2.6.0: {}
- mime@4.1.0: {}
-
mimic-fn@2.1.0: {}
- mimic-fn@4.0.0: {}
-
mimic-function@5.0.1: {}
mimic-response@1.0.1: {}
@@ -22267,8 +20871,6 @@ snapshots:
neotraverse@0.6.18: {}
- nerf-dart@1.0.0: {}
-
ng-mocks@14.15.1(3bd9032d10655768ae17cd8d4331ec90):
dependencies:
'@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
@@ -22311,13 +20913,6 @@ snapshots:
dependencies:
semver: 7.7.4
- node-emoji@2.2.0:
- dependencies:
- '@sindresorhus/is': 4.6.0
- char-regex: 1.0.2
- emojilib: 2.4.0
- skin-tone: 2.0.0
-
node-fetch-native@1.6.7: {}
node-fetch@2.7.0(encoding@0.1.13):
@@ -22370,18 +20965,10 @@ snapshots:
dependencies:
abbrev: 4.0.0
- normalize-package-data@6.0.2:
- dependencies:
- hosted-git-info: 7.0.2
- semver: 7.7.4
- validate-npm-package-license: 3.0.4
-
normalize-path@3.0.0: {}
normalize-url@6.1.0: {}
- normalize-url@8.1.1: {}
-
npm-bundled@5.0.0:
dependencies:
npm-normalize-package-bin: 5.0.0
@@ -22428,17 +21015,6 @@ snapshots:
dependencies:
path-key: 3.1.1
- npm-run-path@5.3.0:
- dependencies:
- path-key: 4.0.0
-
- npm-run-path@6.0.0:
- dependencies:
- path-key: 4.0.0
- unicorn-magic: 0.3.0
-
- npm@10.9.4: {}
-
nth-check@2.1.1:
dependencies:
boolbase: 1.0.0
@@ -22662,10 +21238,6 @@ snapshots:
dependencies:
mimic-fn: 2.1.0
- onetime@6.0.0:
- dependencies:
- mimic-fn: 4.0.0
-
onetime@7.0.0:
dependencies:
mimic-function: 5.0.1
@@ -22774,22 +21346,6 @@ snapshots:
p-cancelable@2.1.1: {}
- p-each-series@3.0.0: {}
-
- p-event@6.0.1:
- dependencies:
- p-timeout: 6.1.4
-
- p-filter@4.1.0:
- dependencies:
- p-map: 7.0.4
-
- p-is-promise@3.0.0: {}
-
- p-limit@1.3.0:
- dependencies:
- p-try: 1.0.0
-
p-limit@2.3.0:
dependencies:
p-try: 2.2.0
@@ -22806,10 +21362,6 @@ snapshots:
dependencies:
yocto-queue: 1.2.2
- p-locate@2.0.0:
- dependencies:
- p-limit: 1.3.0
-
p-locate@4.1.0:
dependencies:
p-limit: 2.3.0
@@ -22833,10 +21385,6 @@ snapshots:
eventemitter3: 5.0.1
p-timeout: 6.1.4
- p-reduce@2.1.0: {}
-
- p-reduce@3.0.0: {}
-
p-retry@6.2.1:
dependencies:
'@types/retry': 0.12.2
@@ -22845,8 +21393,6 @@ snapshots:
p-timeout@6.1.4: {}
- p-try@1.0.0: {}
-
p-try@2.2.0: {}
package-json-from-dist@1.0.1: {}
@@ -22889,11 +21435,6 @@ snapshots:
is-decimal: 2.0.1
is-hexadecimal: 2.0.1
- parse-json@4.0.0:
- dependencies:
- error-ex: 1.3.4
- json-parse-better-errors: 1.0.2
-
parse-json@5.2.0:
dependencies:
'@babel/code-frame': 7.27.1
@@ -22901,12 +21442,6 @@ snapshots:
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
- parse-json@8.3.0:
- dependencies:
- '@babel/code-frame': 7.27.1
- index-to-position: 1.2.0
- type-fest: 4.41.0
-
parse-latin@7.0.0:
dependencies:
'@types/nlcst': 2.0.3
@@ -22916,8 +21451,6 @@ snapshots:
unist-util-visit-children: 3.0.0
vfile: 6.0.3
- parse-ms@4.0.0: {}
-
parse-node-version@1.0.1: {}
parse-passwd@1.0.0: {}
@@ -22928,20 +21461,12 @@ snapshots:
parse5: 8.0.0
parse5-sax-parser: 8.0.0
- parse5-htmlparser2-tree-adapter@6.0.1:
- dependencies:
- parse5: 6.0.1
-
parse5-sax-parser@8.0.0:
dependencies:
parse5: 8.0.0
parse5@4.0.0: {}
- parse5@5.1.1: {}
-
- parse5@6.0.1: {}
-
parse5@7.3.0:
dependencies:
entities: 6.0.1
@@ -22952,8 +21477,6 @@ snapshots:
parseurl@1.3.3: {}
- path-exists@3.0.0: {}
-
path-exists@4.0.0: {}
path-exists@5.0.0: {}
@@ -22962,8 +21485,6 @@ snapshots:
path-key@3.1.1: {}
- path-key@4.0.0: {}
-
path-parse@1.0.7: {}
path-scurry@1.11.1:
@@ -22998,8 +21519,6 @@ snapshots:
pify@2.3.0: {}
- pify@3.0.0: {}
-
pify@4.0.1:
optional: true
@@ -23015,11 +21534,6 @@ snapshots:
dependencies:
'@babel/runtime': 7.28.4
- pkg-conf@2.1.0:
- dependencies:
- find-up: 2.1.0
- load-json-file: 4.0.0
-
pkg-dir@4.2.0:
dependencies:
find-up: 4.1.0
@@ -23349,10 +21863,6 @@ snapshots:
ansi-styles: 5.2.0
react-is: 18.3.1
- pretty-ms@9.3.0:
- dependencies:
- parse-ms: 4.0.0
-
prismjs@1.30.0: {}
proc-log@2.0.1: {}
@@ -23379,8 +21889,6 @@ snapshots:
property-information@7.1.0: {}
- proto-list@1.2.4: {}
-
proxy-addr@2.0.7:
dependencies:
forwarded: 0.2.0
@@ -23466,20 +21974,6 @@ snapshots:
dependencies:
pify: 2.3.0
- read-package-up@11.0.0:
- dependencies:
- find-up-simple: 1.0.1
- read-pkg: 9.0.1
- type-fest: 4.41.0
-
- read-pkg@9.0.1:
- dependencies:
- '@types/normalize-package-data': 2.4.4
- normalize-package-data: 6.0.2
- parse-json: 8.3.0
- type-fest: 4.41.0
- unicorn-magic: 0.1.0
-
readable-stream@2.3.8:
dependencies:
core-util-is: 1.0.3
@@ -23580,10 +22074,6 @@ snapshots:
unicode-match-property-ecmascript: 2.0.0
unicode-match-property-value-ecmascript: 2.2.1
- registry-auth-token@5.1.0:
- dependencies:
- '@pnpm/npm-conf': 2.3.1
-
regjsgen@0.8.0: {}
regjsparser@0.13.0:
@@ -24034,47 +22524,6 @@ snapshots:
'@types/node-forge': 1.3.14
node-forge: 1.4.0
- semantic-release@24.2.9(typescript@5.9.3):
- dependencies:
- '@semantic-release/commit-analyzer': 13.0.1(semantic-release@24.2.9(typescript@5.9.3))
- '@semantic-release/error': 4.0.0
- '@semantic-release/github': 11.0.6(semantic-release@24.2.9(typescript@5.9.3))
- '@semantic-release/npm': 12.0.2(semantic-release@24.2.9(typescript@5.9.3))
- '@semantic-release/release-notes-generator': 14.1.0(semantic-release@24.2.9(typescript@5.9.3))
- aggregate-error: 5.0.0
- cosmiconfig: 9.0.0(typescript@5.9.3)
- debug: 4.4.3
- env-ci: 11.2.0
- execa: 9.6.1
- figures: 6.1.0
- find-versions: 6.0.0
- get-stream: 6.0.1
- git-log-parser: 1.2.1
- hook-std: 4.0.0
- hosted-git-info: 8.1.0
- import-from-esm: 2.0.0
- lodash-es: 4.18.1
- marked: 15.0.12
- marked-terminal: 7.3.0(marked@15.0.12)
- micromatch: 4.0.8
- p-each-series: 3.0.0
- p-reduce: 3.0.0
- read-package-up: 11.0.0
- resolve-from: 5.0.0
- semver: 7.7.3
- semver-diff: 5.0.0
- signale: 1.4.0
- yargs: 17.7.2
- transitivePeerDependencies:
- - supports-color
- - typescript
-
- semver-diff@5.0.0:
- dependencies:
- semver: 7.7.4
-
- semver-regex@4.0.5: {}
-
semver@5.7.2: {}
semver@6.3.1: {}
@@ -24281,12 +22730,6 @@ snapshots:
signal-exit@4.1.0: {}
- signale@1.4.0:
- dependencies:
- chalk: 2.4.2
- figures: 2.0.0
- pkg-conf: 2.1.0
-
sigstore@4.1.0:
dependencies:
'@sigstore/bundle': 4.0.0
@@ -24319,10 +22762,6 @@ snapshots:
arg: 5.0.2
sax: 1.4.3
- skin-tone@2.0.0:
- dependencies:
- unicode-emoji-modifier-base: 1.0.0
-
slash@3.0.0: {}
slash@5.1.0: {}
@@ -24401,20 +22840,8 @@ snapshots:
space-separated-tokens@2.0.2: {}
- spawn-error-forwarder@1.0.0: {}
-
- spdx-correct@3.2.0:
- dependencies:
- spdx-expression-parse: 3.0.1
- spdx-license-ids: 3.0.22
-
spdx-exceptions@2.5.0: {}
- spdx-expression-parse@3.0.1:
- dependencies:
- spdx-exceptions: 2.5.0
- spdx-license-ids: 3.0.22
-
spdx-expression-parse@4.0.0:
dependencies:
spdx-exceptions: 2.5.0
@@ -24443,10 +22870,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- split2@1.0.0:
- dependencies:
- through2: 2.0.5
-
sprintf-js@1.0.3: {}
ssri@13.0.1:
@@ -24476,11 +22899,6 @@ snapshots:
es-errors: 1.3.0
internal-slot: 1.1.0
- stream-combiner2@1.1.1:
- dependencies:
- duplexer2: 0.1.4
- readable-stream: 2.3.8
-
stream-replace-string@2.0.0: {}
streamroller@3.1.5:
@@ -24569,10 +22987,6 @@ snapshots:
strip-final-newline@2.0.0: {}
- strip-final-newline@3.0.0: {}
-
- strip-final-newline@4.0.0: {}
-
strip-json-comments@2.0.1: {}
strip-json-comments@3.1.1: {}
@@ -24611,16 +23025,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- super-regex@1.1.0:
- dependencies:
- function-timeout: 1.0.2
- make-asynchronous: 1.0.1
- time-span: 5.1.0
-
- supports-color@5.5.0:
- dependencies:
- has-flag: 3.0.0
-
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
@@ -24629,11 +23033,6 @@ snapshots:
dependencies:
has-flag: 4.0.0
- supports-hyperlinks@3.2.0:
- dependencies:
- has-flag: 4.0.0
- supports-color: 7.2.0
-
supports-preserve-symlinks-flag@1.0.0: {}
svgo@4.0.0:
@@ -24730,8 +23129,6 @@ snapshots:
minizlib: 3.1.0
yallist: 5.0.0
- temp-dir@3.0.0: {}
-
temp-file@3.4.0:
dependencies:
async-exit-hook: 2.0.1
@@ -24742,17 +23139,6 @@ snapshots:
mkdirp: 0.5.6
rimraf: 2.6.3
- tempfile@5.0.0:
- dependencies:
- temp-dir: 3.0.0
-
- tempy@3.1.0:
- dependencies:
- is-stream: 3.0.0
- temp-dir: 3.0.0
- type-fest: 2.19.0
- unique-string: 3.0.0
-
terser-webpack-plugin@5.3.16(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.28.1)(webpack@5.104.1(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.28.1)):
dependencies:
'@jridgewell/trace-mapping': 0.3.31
@@ -24790,17 +23176,8 @@ snapshots:
dependencies:
tslib: 2.8.1
- through2@2.0.5:
- dependencies:
- readable-stream: 2.3.8
- xtend: 4.0.2
-
thunky@1.1.0: {}
- time-span@5.1.0:
- dependencies:
- convert-hrtime: 5.0.0
-
tiny-async-pool@1.3.0:
dependencies:
semver: 5.7.2
@@ -24848,8 +23225,6 @@ snapshots:
dependencies:
punycode: 2.3.1
- traverse@0.6.8: {}
-
tree-dump@1.1.0(tslib@2.8.1):
dependencies:
tslib: 2.8.1
@@ -24991,10 +23366,6 @@ snapshots:
type-fest@0.21.3: {}
- type-fest@1.4.0: {}
-
- type-fest@2.19.0: {}
-
type-fest@4.41.0: {}
type-is@1.6.18:
@@ -25082,8 +23453,6 @@ snapshots:
unicode-canonical-property-names-ecmascript@2.0.1: {}
- unicode-emoji-modifier-base@1.0.0: {}
-
unicode-match-property-ecmascript@2.0.0:
dependencies:
unicode-canonical-property-names-ecmascript: 2.0.1
@@ -25093,8 +23462,6 @@ snapshots:
unicode-property-aliases-ecmascript@2.2.0: {}
- unicorn-magic@0.1.0: {}
-
unicorn-magic@0.3.0: {}
unified@11.0.5:
@@ -25133,10 +23500,6 @@ snapshots:
dependencies:
imurmurhash: 0.1.4
- unique-string@3.0.0:
- dependencies:
- crypto-random-string: 4.0.0
-
unist-util-find-after@5.0.0:
dependencies:
'@types/unist': 3.0.3
@@ -25183,8 +23546,6 @@ snapshots:
unist-util-is: 6.0.1
unist-util-visit-parents: 6.0.2
- universal-user-agent@7.0.3: {}
-
universalify@0.1.2: {}
universalify@2.0.1: {}
@@ -25246,8 +23607,6 @@ snapshots:
url-join@4.0.1: {}
- url-join@5.0.0: {}
-
url-toolkit@2.2.5: {}
utf8-byte-length@1.0.5: {}
@@ -25268,11 +23627,6 @@ snapshots:
'@types/istanbul-lib-coverage': 2.0.6
convert-source-map: 2.0.0
- validate-npm-package-license@3.0.4:
- dependencies:
- spdx-correct: 3.2.0
- spdx-expression-parse: 3.0.1
-
validate-npm-package-name@7.0.2: {}
varint@6.0.0: {}
@@ -25424,8 +23778,6 @@ snapshots:
web-namespaces@2.0.1: {}
- web-worker@1.2.0: {}
-
webidl-conversions@3.0.1: {}
webidl-conversions@7.0.0: {}
@@ -25672,8 +24024,6 @@ snapshots:
xmlchars@2.2.0: {}
- xtend@4.0.2: {}
-
xxhash-wasm@1.1.0: {}
y18n@4.0.3: {}
@@ -25697,8 +24047,6 @@ snapshots:
camelcase: 5.3.1
decamelize: 1.2.0
- yargs-parser@20.2.9: {}
-
yargs-parser@21.1.1: {}
yargs-parser@22.0.0: {}
@@ -25717,16 +24065,6 @@ snapshots:
y18n: 4.0.3
yargs-parser: 18.1.3
- yargs@16.2.0:
- dependencies:
- cliui: 7.0.4
- escalade: 3.2.0
- get-caller-file: 2.0.5
- require-directory: 2.1.1
- string-width: 4.2.3
- y18n: 5.0.8
- yargs-parser: 20.2.9
-
yargs@17.7.2:
dependencies:
cliui: 8.0.1
diff --git a/tools/release/build-release-notes.mjs b/tools/release/build-release-notes.mjs
new file mode 100644
index 000000000..7f7a27de1
--- /dev/null
+++ b/tools/release/build-release-notes.mjs
@@ -0,0 +1,312 @@
+#!/usr/bin/env node
+/**
+ * Composes release surfaces from the notes accumulated in `.changes/`.
+ *
+ * node tools/release/build-release-notes.mjs --validate
+ * node tools/release/build-release-notes.mjs --version 0.24.0 --format github
+ * node tools/release/build-release-notes.mjs --version 0.24.0 --format changelog
+ * node tools/release/build-release-notes.mjs --version 0.24.0 --format blog
+ * node tools/release/build-release-notes.mjs --version 0.24.0 --consume
+ *
+ * Every mode except `--consume` is a safe dry run: nothing is deleted unless
+ * `--consume` is passed explicitly.
+ */
+
+import { execFileSync } from 'node:child_process';
+import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
+import path from 'node:path';
+import process from 'node:process';
+import { fileURLToPath } from 'node:url';
+
+import { loadNotes } from './release-notes.mjs';
+import {
+ releaseSlug,
+ renderBlogScaffold,
+ renderChangelogSection,
+ renderGithubBody,
+ upsertChangelogSection,
+} from './release-notes-render.mjs';
+
+const workspaceRoot = path.resolve(
+ path.dirname(fileURLToPath(import.meta.url)),
+ '../..'
+);
+const CHANGELOG_PATH = path.join(workspaceRoot, 'CHANGELOG.md');
+const BLOG_DIR = path.join(workspaceRoot, 'apps/website/src/content/blog');
+
+/** Generated sections are inserted directly below this marker. */
+const CHANGELOG_MARKER = '';
+
+const FORMATS = new Set(['github', 'changelog', 'blog']);
+
+function parseArgs(argv) {
+ const options = {
+ format: null,
+ version: null,
+ previous: null,
+ date: new Date().toISOString().slice(0, 10),
+ dir: '.changes',
+ validate: false,
+ consume: false,
+ force: false,
+ };
+
+ for (let index = 0; index < argv.length; index += 1) {
+ const arg = argv[index];
+ const takeValue = () => {
+ const value = argv[index + 1];
+
+ if (value === undefined || value.startsWith('--')) {
+ throw new Error(`${arg} requires a value`);
+ }
+
+ index += 1;
+ return value;
+ };
+
+ switch (arg) {
+ case '--format':
+ options.format = takeValue();
+ break;
+ case '--version':
+ options.version = takeValue();
+ break;
+ case '--previous':
+ options.previous = takeValue();
+ break;
+ case '--date':
+ options.date = takeValue();
+ break;
+ case '--dir':
+ options.dir = takeValue();
+ break;
+ case '--validate':
+ options.validate = true;
+ break;
+ case '--consume':
+ options.consume = true;
+ break;
+ case '--force':
+ options.force = true;
+ break;
+ default:
+ throw new Error(`unknown argument: ${arg}`);
+ }
+ }
+
+ return options;
+}
+
+function git(args) {
+ return execFileSync('git', args, {
+ cwd: workspaceRoot,
+ encoding: 'utf8',
+ stdio: ['ignore', 'pipe', 'ignore'],
+ }).trim();
+}
+
+/**
+ * Resolves each note to the commit that added it, and to a PR number when the
+ * commit subject carries one. Authors never write a PR number themselves —
+ * they cannot know it while the branch is still local.
+ *
+ * @param {object[]} notes
+ * @returns {Map}
+ */
+function resolveLinks(notes) {
+ const links = new Map();
+
+ for (const note of notes) {
+ let output = '';
+
+ try {
+ output = git([
+ 'log',
+ '--diff-filter=A',
+ '--format=%H%x00%s',
+ '-1',
+ '--',
+ note.sourcePath,
+ ]);
+ } catch {
+ // Not a git checkout, or the note is not committed yet. Entries
+ // simply render without a reference link.
+ }
+
+ if (!output) {
+ continue;
+ }
+
+ const [commit, subject = ''] = output.split('\0');
+ const prMatch = subject.match(/\(#(\d+)\)\s*$/);
+
+ links.set(note.sourcePath, {
+ commit,
+ pr: prMatch ? Number(prMatch[1]) : undefined,
+ });
+ }
+
+ return links;
+}
+
+/** Latest `v*` tag, used for the CHANGELOG compare link. */
+function detectPreviousVersion() {
+ try {
+ return git(['describe', '--tags', '--abbrev=0', '--match=v*']).replace(
+ /^v/,
+ ''
+ );
+ } catch {
+ return null;
+ }
+}
+
+/**
+ * The release version is the one in the root package.json — bumping it is the
+ * deliberate act that starts a release. `--version` stays available as an
+ * override (dry runs, previewing a version before the bump), but the default
+ * keeps a single source of truth and lets the package scripts run bare.
+ */
+function resolveVersion(options) {
+ let version = options.version;
+
+ if (!version) {
+ version = JSON.parse(
+ readFileSync(path.join(workspaceRoot, 'package.json'), 'utf8')
+ ).version;
+
+ // stderr, so `--format github` keeps a clean pipeable stdout.
+ console.error(`Using version ${version} from package.json.`);
+ }
+
+ if (!/^\d+\.\d+\.\d+$/.test(version)) {
+ throw new Error(
+ `version must be a bare semver like 0.24.0, got "${version}"`
+ );
+ }
+
+ return version;
+}
+
+function writeChangelog(section, version) {
+ const { content, replaced } = upsertChangelogSection(
+ readFileSync(CHANGELOG_PATH, 'utf8'),
+ section,
+ version,
+ CHANGELOG_MARKER
+ );
+
+ if (replaced) {
+ console.error(`Replacing existing CHANGELOG.md section for ${version}.`);
+ }
+
+ writeFileSync(CHANGELOG_PATH, content, 'utf8');
+
+ return CHANGELOG_PATH;
+}
+
+function writeBlogScaffold(content, version, force) {
+ const target = path.join(
+ BLOG_DIR,
+ `${releaseSlug(version)}-release-notes.mdx`
+ );
+
+ if (existsSync(target) && !force) {
+ throw new Error(
+ [
+ `${path.relative(workspaceRoot, target)} already exists.`,
+ 'The website publishes one post per minor version, so a patch',
+ 'release edits the existing post instead of creating a new one.',
+ 'Pass --force only to regenerate it from scratch.',
+ ].join(' ')
+ );
+ }
+
+ writeFileSync(target, content, 'utf8');
+
+ return target;
+}
+
+function main() {
+ const options = parseArgs(process.argv.slice(2));
+ const notesDir = path.resolve(workspaceRoot, options.dir);
+ const { notes, errors } = loadNotes(notesDir);
+
+ if (errors.length > 0) {
+ console.error('Invalid release notes:\n');
+ for (const error of errors) {
+ console.error(` ${error}`);
+ }
+ console.error(
+ '\nSee .changes/README.md for the expected format.'
+ );
+ process.exit(1);
+ }
+
+ if (options.validate) {
+ console.log(`${notes.length} release note(s) valid.`);
+ }
+
+ if (options.format) {
+ if (!FORMATS.has(options.format)) {
+ throw new Error(
+ `unknown --format "${options.format}" (expected ${[...FORMATS].join(', ')})`
+ );
+ }
+
+ const version = resolveVersion(options);
+ const links = resolveLinks(notes);
+
+ if (notes.length === 0) {
+ throw new Error(
+ `no notes found in ${path.relative(workspaceRoot, notesDir)}/ — nothing to render`
+ );
+ }
+
+ if (options.format === 'github') {
+ process.stdout.write(`${renderGithubBody(notes, { links })}\n`);
+ }
+
+ if (options.format === 'changelog') {
+ const section = renderChangelogSection(notes, {
+ version,
+ date: options.date,
+ previousVersion: options.previous ?? detectPreviousVersion(),
+ links,
+ });
+ const target = writeChangelog(section, version);
+ console.log(`Updated ${path.relative(workspaceRoot, target)}`);
+ }
+
+ if (options.format === 'blog') {
+ const content = renderBlogScaffold(notes, {
+ version,
+ date: options.date,
+ links,
+ });
+ const target = writeBlogScaffold(content, version, options.force);
+ console.log(`Wrote ${path.relative(workspaceRoot, target)}`);
+ }
+ }
+
+ if (options.consume) {
+ for (const note of notes) {
+ rmSync(note.sourcePath);
+ }
+
+ console.log(`Removed ${notes.length} consumed note(s).`);
+ }
+
+ if (!options.format && !options.validate && !options.consume) {
+ throw new Error(
+ 'nothing to do — pass --validate, --format , or --consume'
+ );
+ }
+}
+
+try {
+ main();
+} catch (error) {
+ console.error(error.message);
+ process.exit(1);
+}
diff --git a/tools/release/extract-changelog-section.mjs b/tools/release/extract-changelog-section.mjs
new file mode 100644
index 000000000..65a5aa697
--- /dev/null
+++ b/tools/release/extract-changelog-section.mjs
@@ -0,0 +1,99 @@
+#!/usr/bin/env node
+/**
+ * Prints the CHANGELOG.md section for one version to stdout.
+ *
+ * node tools/release/extract-changelog-section.mjs 0.24.0
+ *
+ * Used by the tag-build release job to put the authored notes into the
+ * GitHub release body. `.changes/*.md` files are consumed before the tag
+ * exists, so at tag time the changelog section IS the authored source of
+ * truth — this reads what the generator already wrote.
+ *
+ * Exits non-zero when the section is missing so a forgotten
+ * `release:notes:changelog` fails the release instead of silently shipping
+ * PR-title-only notes.
+ */
+
+import { readFileSync } from 'node:fs';
+import path from 'node:path';
+import process from 'node:process';
+import { fileURLToPath } from 'node:url';
+
+const workspaceRoot = path.resolve(
+ path.dirname(fileURLToPath(import.meta.url)),
+ '../..'
+);
+
+/**
+ * @param {string} changelog full CHANGELOG.md content
+ * @param {string} version bare semver, e.g. `0.24.0`
+ * @returns {string | null} section body without its own H1 heading
+ */
+export function extractSection(changelog, version) {
+ const lines = changelog.replace(/\r\n/g, '\n').split('\n');
+ // The CLI validates its argument, but this function is exported on its
+ // own — escape every regex metacharacter rather than only dots so no
+ // caller can inject pattern syntax.
+ const escapedVersion = version.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ // Matches both heading shapes used in this file:
+ // # [0.24.0](compare-url) (2026-08-01)
+ // # 0.24.0 (2026-08-01)
+ const headingPattern = new RegExp(
+ `^#\\s+\\[?${escapedVersion}\\]?\\s*[( ]`
+ );
+ const start = lines.findIndex((line) => headingPattern.test(line));
+
+ if (start === -1) {
+ return null;
+ }
+
+ let end = lines.length;
+
+ for (let index = start + 1; index < lines.length; index += 1) {
+ if (/^#\s/.test(lines[index])) {
+ end = index;
+ break;
+ }
+ }
+
+ return lines.slice(start + 1, end).join('\n').trim();
+}
+
+function main() {
+ const version = process.argv[2];
+
+ if (!version || !/^\d+\.\d+\.\d+$/.test(version)) {
+ console.error(
+ 'Usage: extract-changelog-section.mjs (for example 0.24.0)'
+ );
+ process.exit(2);
+ }
+
+ const changelogPath = path.join(workspaceRoot, 'CHANGELOG.md');
+ const section = extractSection(readFileSync(changelogPath, 'utf8'), version);
+
+ if (section === null) {
+ console.error(
+ [
+ `CHANGELOG.md has no section for ${version}.`,
+ 'The release flow writes it before tagging:',
+ ' pnpm run release:notes:changelog',
+ ' node tools/release/build-release-notes.mjs --consume',
+ 'Commit the changelog, then re-tag.',
+ ].join('\n')
+ );
+ process.exit(1);
+ }
+
+ if (section === '') {
+ console.error(`CHANGELOG.md section for ${version} is empty.`);
+ process.exit(1);
+ }
+
+ process.stdout.write(`${section}\n`);
+}
+
+// Allow importing extractSection from tests without running the CLI.
+if (process.argv[1] === fileURLToPath(import.meta.url)) {
+ main();
+}
diff --git a/tools/release/project.json b/tools/release/project.json
new file mode 100644
index 000000000..d3d47110b
--- /dev/null
+++ b/tools/release/project.json
@@ -0,0 +1,32 @@
+{
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "name": "release-tools",
+ "projectType": "library",
+ "sourceRoot": "tools/release",
+ "targets": {
+ "test": {
+ "executor": "nx:run-commands",
+ "cache": true,
+ "inputs": [
+ "{workspaceRoot}/tools/release/release-notes.mjs",
+ "{workspaceRoot}/tools/release/release-notes-render.mjs",
+ "{workspaceRoot}/tools/release/extract-changelog-section.mjs",
+ "{workspaceRoot}/tools/release/release-notes.test.mjs"
+ ],
+ "options": {
+ "command": "node --test tools/release/release-notes.test.mjs",
+ "cwd": "{workspaceRoot}"
+ }
+ },
+ "lint": {
+ "inputs": [
+ "default",
+ "{workspaceRoot}/eslint.config.mjs",
+ "{workspaceRoot}/tools/eslint-rules/**/*",
+ "{workspaceRoot}/tools/eslint/**/*"
+ ],
+ "command": "eslint \"tools/release/*.mjs\""
+ }
+ },
+ "tags": ["scope:tools", "domain:release", "type:tool"]
+}
diff --git a/tools/release/release-notes-render.mjs b/tools/release/release-notes-render.mjs
new file mode 100644
index 000000000..a8e4006b4
--- /dev/null
+++ b/tools/release/release-notes-render.mjs
@@ -0,0 +1,324 @@
+/**
+ * Renderers turning grouped `.changes/*.md` notes into the three release
+ * surfaces: the GitHub release body, the CHANGELOG.md section, and the
+ * website blog scaffold.
+ */
+
+import { extractSection } from './extract-changelog-section.mjs';
+import { groupNotes, REPO_URL } from './release-notes.mjs';
+
+const MONTHS = [
+ 'January',
+ 'February',
+ 'March',
+ 'April',
+ 'May',
+ 'June',
+ 'July',
+ 'August',
+ 'September',
+ 'October',
+ 'November',
+ 'December',
+];
+
+/**
+ * @param {string} isoDate `YYYY-MM-DD`
+ * @returns {string} e.g. `August 1, 2026`
+ */
+export function formatLongDate(isoDate) {
+ const [year, month, day] = isoDate.split('-').map(Number);
+
+ return `${MONTHS[month - 1]} ${day}, ${year}`;
+}
+
+/**
+ * Deliberately minor-scoped: the website publishes one release post per minor
+ * version (`v0-18` … `v0-22`), and its screenshot assets live under the same
+ * directory. A patch release therefore reuses its minor's post rather than
+ * starting a new one.
+ *
+ * @param {string} version
+ * @returns {string} e.g. `v0-24` for both `0.24.0` and `0.24.1`
+ */
+export function releaseSlug(version) {
+ const [major, minor] = version.split('.');
+
+ return `v${major}-${minor}`;
+}
+
+/** Collapses a note body to a single line for list entries. */
+function oneLine(body) {
+ return body.replace(/\s+/g, ' ').trim();
+}
+
+/** Trims to a word boundary; used for image alt text, never for prose. */
+function truncate(text, max) {
+ if (text.length <= max) {
+ return text;
+ }
+
+ const cut = text.slice(0, max);
+ const lastSpace = cut.lastIndexOf(' ');
+
+ return `${(lastSpace > max / 2 ? cut.slice(0, lastSpace) : cut).trimEnd()}…`;
+}
+
+/**
+ * MDX parses `<` and `{` as markup. Note bodies are plain prose written by
+ * humans and agents, so escape them rather than letting a stray character
+ * break the website build. The closing counterparts are escaped too, so a
+ * body like `` renders as written instead of half-escaped.
+ */
+function escapeMdx(text) {
+ return text
+ .replace(//g, '>')
+ .replace(/\{/g, '{')
+ .replace(/\}/g, '}');
+}
+
+/**
+ * @param {object} note
+ * @param {Map} links
+ * @returns {string} trailing `([#123](url), closes [#45](url))` or ''
+ */
+function formatReferences(note, links) {
+ const parts = [];
+ const link = links.get(note.sourcePath);
+
+ if (link?.pr) {
+ parts.push(`[#${link.pr}](${REPO_URL}/pull/${link.pr})`);
+ } else if (link?.commit) {
+ parts.push(
+ `[${link.commit.slice(0, 7)}](${REPO_URL}/commit/${link.commit})`
+ );
+ }
+
+ for (const issue of note.issues) {
+ parts.push(`closes [#${issue}](${REPO_URL}/issues/${issue})`);
+ }
+
+ return parts.length > 0 ? ` (${parts.join(', ')})` : '';
+}
+
+function formatEntry(note, links) {
+ return `- **${note.area}** — ${oneLine(note.body)}${formatReferences(note, links)}`;
+}
+
+/**
+ * GitHub release body. `internal` notes are omitted: the release page is read
+ * by users, and GitHub still appends its own full commit list below.
+ *
+ * @param {object[]} notes
+ * @param {{ links?: Map }} [options]
+ * @returns {string}
+ */
+export function renderGithubBody(notes, { links = new Map() } = {}) {
+ const sections = groupNotes(notes)
+ .filter((group) => group.type !== 'internal')
+ .map((group) => {
+ const entries = group.notes
+ .map((note) => formatEntry(note, links))
+ .join('\n');
+
+ return `## ${group.heading}\n\n${entries}`;
+ });
+
+ return sections.join('\n\n');
+}
+
+/**
+ * CHANGELOG.md section. Unlike the release body this keeps `internal` notes,
+ * collapsed, so the file stays a complete record.
+ *
+ * @param {object[]} notes
+ * @param {{ version: string, date: string, previousVersion?: string | null, links?: Map }} options
+ * @returns {string}
+ */
+export function renderChangelogSection(
+ notes,
+ { version, date, previousVersion = null, links = new Map() }
+) {
+ const heading = previousVersion
+ ? `# [${version}](${REPO_URL}/compare/v${previousVersion}...v${version}) (${date})`
+ : `# ${version} (${date})`;
+
+ const blocks = [heading];
+
+ for (const group of groupNotes(notes)) {
+ const entries = group.notes
+ .map((note) => formatEntry(note, links))
+ .join('\n');
+
+ if (group.type === 'internal') {
+ blocks.push(
+ `\nInternal changes
\n\n${entries}\n\n `
+ );
+ continue;
+ }
+
+ blocks.push(`### ${group.heading}\n\n${entries}`);
+ }
+
+ return `${blocks.join('\n\n')}\n`;
+}
+
+/**
+ * Inserts a version section below the marker, replacing any existing section
+ * for the same version — rerunning `--format changelog` after correcting a
+ * note must not prepend a duplicate.
+ *
+ * @param {string} changelog full CHANGELOG.md content
+ * @param {string} section rendered section (from renderChangelogSection)
+ * @param {string} version bare semver the section describes
+ * @param {string} marker insertion marker line
+ * @returns {{ content: string, replaced: boolean }}
+ */
+export function upsertChangelogSection(changelog, section, version, marker) {
+ if (!changelog.includes(marker)) {
+ throw new Error(
+ `changelog is missing the \`${marker}\` marker that new sections are inserted below`
+ );
+ }
+
+ let current = changelog;
+ const replaced = extractSection(current, version) !== null;
+
+ if (replaced) {
+ const lines = current.split('\n');
+ const headingIndex = lines.findIndex(
+ (line) =>
+ line.startsWith(`# [${version}]`) ||
+ line.startsWith(`# ${version} `)
+ );
+ let end = lines.length;
+
+ for (let index = headingIndex + 1; index < lines.length; index += 1) {
+ if (/^#\s/.test(lines[index])) {
+ end = index;
+ break;
+ }
+ }
+
+ current = [...lines.slice(0, headingIndex), ...lines.slice(end)].join(
+ '\n'
+ );
+ }
+
+ // Rebuild around the marker instead of string-replacing into it, so the
+ // blank-line count on both sides of the section stays exact regardless of
+ // whether a removal just happened.
+ const markerIndex = current.indexOf(marker);
+ const before = current.slice(0, markerIndex);
+ const after = current
+ .slice(markerIndex + marker.length)
+ .replace(/^\n+/, '');
+
+ return {
+ content: `${before}${marker}\n\n${section.trim()}\n\n${after}`,
+ replaced,
+ };
+}
+
+/**
+ * Blog entries carrying a `screenshot:` slug become their own subsection with
+ * an image slider; the rest stay bullets.
+ */
+function renderBlogGroup(group, { slug, links }) {
+ const bullets = group.notes.filter((note) => !note.screenshot);
+ const featured = group.notes.filter((note) => note.screenshot);
+ const blocks = [`## ${group.heading}`];
+
+ if (bullets.length > 0) {
+ blocks.push(
+ bullets
+ .map(
+ (note) =>
+ `- **${note.area}** — ${escapeMdx(oneLine(note.body))}${formatReferences(note, links)}`
+ )
+ .join('\n')
+ );
+ }
+
+ for (const note of featured) {
+ // The heading is editorial work — a note body makes a terrible one.
+ // Leave a visible TODO instead of pretending otherwise; the whole
+ // scaffold ships as `draft: true` anyway.
+ // Embedded in a single-quoted JS string inside MDX. Backslashes must
+ // be escaped before apostrophes, or a body ending in `\` produces an
+ // unterminated string and breaks the website build.
+ const alt = truncate(oneLine(note.body), 120)
+ .replace(/\\/g, '\\\\')
+ .replace(/'/g, "\\'");
+ const images = ['dark', 'light']
+ .map(
+ (theme) =>
+ ` {\n src: '/iptvnator/blog/${slug}/screenshots/${note.screenshot}-${theme}.png',\n alt: '${alt}',\n },`
+ )
+ .join('\n');
+
+ blocks.push(`### TODO headline (${note.area})`);
+ blocks.push(
+ `${escapeMdx(oneLine(note.body))}${formatReferences(note, links)}`
+ );
+ blocks.push(``);
+ }
+
+ return blocks.join('\n\n');
+}
+
+/**
+ * Scaffold for `apps/website/src/content/blog/v0-24-release-notes.mdx`.
+ * Deliberately incomplete: `draft: true`, TODO markers for the narrative and
+ * description. The prose is editorial work, only the inventory is mechanical.
+ *
+ * @param {object[]} notes
+ * @param {{ version: string, date: string, links?: Map }} options
+ * @returns {string}
+ */
+export function renderBlogScaffold(notes, { version, date, links = new Map() }) {
+ const slug = releaseSlug(version);
+ const shortVersion = slug.replace('-', '.');
+ const sections = groupNotes(notes)
+ .filter((group) => group.type !== 'internal')
+ .map((group) => renderBlogGroup(group, { slug, links }));
+
+ const frontmatter = [
+ '---',
+ `title: ${shortVersion} - Release Notes`,
+ 'description: TODO — one sentence naming the two or three headline changes.',
+ 'featured: true',
+ `pubDate: ${date}`,
+ 'author: 4gray',
+ `heroImage: /iptvnator/blog/${slug}/hero.jpg`,
+ 'tags:',
+ ' - release',
+ ' - release-notes',
+ ` - ${shortVersion}`,
+ 'draft: true',
+ '---',
+ ].join('\n');
+
+ const imports = [
+ "import BlogImageSlider from '../../components/blog/BlogImageSlider.astro';",
+ "import ReleaseMeta from '../../components/blog/ReleaseMeta.astro';",
+ ].join('\n');
+
+ const meta = [
+ '',
+ ].join('\n');
+
+ return [
+ frontmatter,
+ imports,
+ '{/* TODO: narrative intro — what this release is about, not what it contains. */}',
+ meta,
+ ...sections,
+ '',
+ ].join('\n\n');
+}
diff --git a/tools/release/release-notes.mjs b/tools/release/release-notes.mjs
new file mode 100644
index 000000000..8f50c4027
--- /dev/null
+++ b/tools/release/release-notes.mjs
@@ -0,0 +1,260 @@
+/**
+ * Parsing and validation for `.changes/*.md` release notes.
+ *
+ * One file per user-visible change, written by the PR author while the
+ * context is still fresh. The generator (build-release-notes.mjs) turns the
+ * accumulated files into the GitHub release body, the CHANGELOG.md section,
+ * and the website blog scaffold.
+ *
+ * Deliberately dependency-free: a hand-rolled parser for this tiny, closed
+ * schema is more predictable than a YAML engine, and it can reject unknown
+ * keys — which is what catches agent typos.
+ */
+
+import { readdirSync, readFileSync } from 'node:fs';
+import path from 'node:path';
+
+export const REPO_URL = 'https://github.com/4gray/iptvnator';
+
+/** Render order. `internal` is last and is excluded from user-facing output. */
+export const NOTE_TYPES = ['breaking', 'feature', 'fix', 'perf', 'internal'];
+
+export const TYPE_HEADINGS = {
+ breaking: 'Breaking changes',
+ feature: 'Features',
+ fix: 'Fixes',
+ perf: 'Performance',
+ internal: 'Internal',
+};
+
+const KNOWN_KEYS = new Set(['type', 'area', 'issues', 'screenshot']);
+const SLUG_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
+const DELIMITER = '---';
+
+/** Keeps entries to a sentence or three; essays belong in the blog post. */
+const MAX_BODY_LENGTH = 400;
+
+/**
+ * Splits a note into its frontmatter lines and body.
+ *
+ * @param {string} content raw file content
+ * @returns {{ frontmatterLines: string[], body: string }}
+ */
+function splitFrontmatter(content) {
+ const lines = content.replace(/\r\n/g, '\n').split('\n');
+
+ if (lines[0]?.trim() !== DELIMITER) {
+ throw new Error('missing opening `---` frontmatter delimiter');
+ }
+
+ const closingIndex = lines.findIndex(
+ (line, index) => index > 0 && line.trim() === DELIMITER
+ );
+
+ if (closingIndex === -1) {
+ throw new Error('missing closing `---` frontmatter delimiter');
+ }
+
+ return {
+ frontmatterLines: lines.slice(1, closingIndex),
+ body: lines.slice(closingIndex + 1).join('\n').trim(),
+ };
+}
+
+/**
+ * Parses a single `key: value` frontmatter line.
+ *
+ * Trailing `# comment` text is stripped: no value in this schema (enum slug,
+ * area slug, issue numbers) can legitimately contain `#`, and the documented
+ * examples carry explanatory comments.
+ *
+ * @param {string} line
+ * @returns {[string, string] | null} key/value pair, or null for blank lines
+ */
+function parseFrontmatterLine(line) {
+ const withoutComment = line.replace(/\s+#.*$/, '').trim();
+
+ if (!withoutComment) {
+ return null;
+ }
+
+ const separatorIndex = withoutComment.indexOf(':');
+
+ if (separatorIndex === -1) {
+ throw new Error(`frontmatter line is not \`key: value\`: "${line.trim()}"`);
+ }
+
+ const key = withoutComment.slice(0, separatorIndex).trim();
+ const value = withoutComment
+ .slice(separatorIndex + 1)
+ .trim()
+ .replace(/^['"]|['"]$/g, '');
+
+ return [key, value];
+}
+
+/**
+ * @param {string} value e.g. `[1187, 1188]` or `1187`
+ * @returns {number[]}
+ */
+function parseIssueList(value) {
+ const inner = value.startsWith('[') ? value.replace(/^\[|\]$/g, '') : value;
+
+ return inner
+ .split(',')
+ .map((entry) => entry.trim().replace(/^#/, ''))
+ .filter(Boolean)
+ .map((entry) => Number(entry));
+}
+
+/**
+ * Parses a note file into a structured record. Shape errors throw; semantic
+ * errors are reported by validateNote() so a run can list every problem at
+ * once instead of failing on the first one.
+ *
+ * @param {string} content
+ * @param {string} sourcePath path used in error messages and PR resolution
+ * @returns {{ type: string, area: string, issues: number[], screenshot: string | null, body: string, sourcePath: string }}
+ */
+export function parseNote(content, sourcePath) {
+ const { frontmatterLines, body } = splitFrontmatter(content);
+ const fields = new Map();
+
+ for (const line of frontmatterLines) {
+ const parsed = parseFrontmatterLine(line);
+
+ if (!parsed) {
+ continue;
+ }
+
+ const [key, value] = parsed;
+
+ if (fields.has(key)) {
+ throw new Error(`duplicate frontmatter key: \`${key}\``);
+ }
+
+ fields.set(key, value);
+ }
+
+ return {
+ type: fields.get('type') ?? '',
+ area: fields.get('area') ?? '',
+ issues: fields.has('issues') ? parseIssueList(fields.get('issues')) : [],
+ screenshot: fields.get('screenshot') ?? null,
+ unknownKeys: [...fields.keys()].filter((key) => !KNOWN_KEYS.has(key)),
+ body,
+ sourcePath,
+ };
+}
+
+/**
+ * @param {ReturnType} note
+ * @returns {string[]} human-readable problems, empty when the note is valid
+ */
+export function validateNote(note) {
+ const errors = [];
+
+ if (!note.type) {
+ errors.push('`type` is required');
+ } else if (!NOTE_TYPES.includes(note.type)) {
+ errors.push(
+ `unknown \`type\`: "${note.type}" (expected one of ${NOTE_TYPES.join(', ')})`
+ );
+ }
+
+ if (!note.area) {
+ errors.push('`area` is required (use the conventional-commit scope)');
+ } else if (!SLUG_PATTERN.test(note.area)) {
+ errors.push(`\`area\` must be a lowercase slug, got "${note.area}"`);
+ }
+
+ if (!note.body) {
+ errors.push('body is empty — describe the change for a user');
+ } else if (note.body.length > MAX_BODY_LENGTH) {
+ errors.push(
+ `body is ${note.body.length} characters, max ${MAX_BODY_LENGTH} — keep it to a few sentences and put detail in the blog post`
+ );
+ }
+
+ for (const issue of note.issues) {
+ if (!Number.isInteger(issue) || issue <= 0) {
+ errors.push(`\`issues\` must be positive integers, got "${issue}"`);
+ }
+ }
+
+ if (note.screenshot !== null && !SLUG_PATTERN.test(note.screenshot)) {
+ errors.push(
+ `\`screenshot\` must be a lowercase slug from the screenshot manifest, got "${note.screenshot}"`
+ );
+ }
+
+ for (const key of note.unknownKeys) {
+ errors.push(
+ `unknown frontmatter key: \`${key}\` (expected ${[...KNOWN_KEYS].join(', ')})`
+ );
+ }
+
+ return errors;
+}
+
+/**
+ * Reads and parses every note in a directory, sorted by filename so output
+ * ordering is stable across machines.
+ *
+ * @param {string} directory
+ * @returns {{ notes: object[], errors: string[] }}
+ */
+export function loadNotes(directory) {
+ let entries = [];
+
+ try {
+ entries = readdirSync(directory);
+ } catch (error) {
+ if (error.code === 'ENOENT') {
+ return { notes: [], errors: [] };
+ }
+
+ throw error;
+ }
+
+ const files = entries
+ .filter((name) => name.endsWith('.md') && name !== 'README.md')
+ .sort();
+
+ const notes = [];
+ const errors = [];
+
+ for (const name of files) {
+ const sourcePath = path.join(directory, name);
+
+ try {
+ const note = parseNote(readFileSync(sourcePath, 'utf8'), sourcePath);
+ const problems = validateNote(note);
+
+ if (problems.length > 0) {
+ errors.push(...problems.map((problem) => `${name}: ${problem}`));
+ continue;
+ }
+
+ notes.push(note);
+ } catch (error) {
+ errors.push(`${name}: ${error.message}`);
+ }
+ }
+
+ return { notes, errors };
+}
+
+/**
+ * Groups notes by type in render order, dropping empty groups.
+ *
+ * @param {object[]} notes
+ * @returns {{ type: string, heading: string, notes: object[] }[]}
+ */
+export function groupNotes(notes) {
+ return NOTE_TYPES.map((type) => ({
+ type,
+ heading: TYPE_HEADINGS[type],
+ notes: notes.filter((note) => note.type === type),
+ })).filter((group) => group.notes.length > 0);
+}
diff --git a/tools/release/release-notes.test.mjs b/tools/release/release-notes.test.mjs
new file mode 100644
index 000000000..6445d5f59
--- /dev/null
+++ b/tools/release/release-notes.test.mjs
@@ -0,0 +1,517 @@
+import assert from 'node:assert/strict';
+import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
+import { tmpdir } from 'node:os';
+import path from 'node:path';
+import { after, describe, it } from 'node:test';
+
+import {
+ groupNotes,
+ loadNotes,
+ parseNote,
+ validateNote,
+} from './release-notes.mjs';
+import {
+ formatLongDate,
+ releaseSlug,
+ renderBlogScaffold,
+ renderChangelogSection,
+ renderGithubBody,
+ upsertChangelogSection,
+} from './release-notes-render.mjs';
+import { extractSection } from './extract-changelog-section.mjs';
+
+const tempDirs = [];
+
+function makeNotesDir(files) {
+ const directory = mkdtempSync(path.join(tmpdir(), 'release-notes-'));
+ tempDirs.push(directory);
+
+ for (const [name, content] of Object.entries(files)) {
+ writeFileSync(path.join(directory, name), content, 'utf8');
+ }
+
+ return directory;
+}
+
+function note(overrides = {}) {
+ return {
+ type: 'feature',
+ area: 'playback',
+ issues: [],
+ screenshot: null,
+ unknownKeys: [],
+ body: 'Series now show an Up Next rail beside the player.',
+ sourcePath: '.changes/playback-up-next.md',
+ ...overrides,
+ };
+}
+
+after(() => {
+ for (const directory of tempDirs) {
+ rmSync(directory, { recursive: true, force: true });
+ }
+});
+
+describe('parseNote', () => {
+ it('parses frontmatter, issue list and body', () => {
+ const parsed = parseNote(
+ [
+ '---',
+ 'type: feature',
+ 'area: playback',
+ 'issues: [1187, 1188]',
+ 'screenshot: up-next-rail',
+ '---',
+ '',
+ 'Series now show an Up Next rail.',
+ '',
+ ].join('\n'),
+ '.changes/playback-up-next.md'
+ );
+
+ assert.equal(parsed.type, 'feature');
+ assert.equal(parsed.area, 'playback');
+ assert.deepEqual(parsed.issues, [1187, 1188]);
+ assert.equal(parsed.screenshot, 'up-next-rail');
+ assert.equal(parsed.body, 'Series now show an Up Next rail.');
+ assert.deepEqual(parsed.unknownKeys, []);
+ });
+
+ it('strips trailing comments and quotes, and accepts a bare issue', () => {
+ const parsed = parseNote(
+ [
+ '---',
+ 'type: fix # one of feature | fix | perf',
+ "area: 'm3u'",
+ 'issues: 1204',
+ '---',
+ 'Playlists with very long URLs parse again.',
+ ].join('\n'),
+ 'x.md'
+ );
+
+ assert.equal(parsed.type, 'fix');
+ assert.equal(parsed.area, 'm3u');
+ assert.deepEqual(parsed.issues, [1204]);
+ });
+
+ it('records unknown keys instead of dropping them silently', () => {
+ const parsed = parseNote(
+ ['---', 'type: fix', 'area: m3u', 'scope: m3u', '---', 'Body.'].join(
+ '\n'
+ ),
+ 'x.md'
+ );
+
+ assert.deepEqual(parsed.unknownKeys, ['scope']);
+ });
+
+ it('rejects a missing or unterminated frontmatter block', () => {
+ assert.throws(
+ () => parseNote('type: fix\nBody.', 'x.md'),
+ /missing opening/
+ );
+ assert.throws(
+ () => parseNote('---\ntype: fix\nBody.', 'x.md'),
+ /missing closing/
+ );
+ });
+
+ it('rejects duplicate keys', () => {
+ assert.throws(
+ () =>
+ parseNote(
+ ['---', 'type: fix', 'type: feature', '---', 'Body.'].join(
+ '\n'
+ ),
+ 'x.md'
+ ),
+ /duplicate frontmatter key/
+ );
+ });
+});
+
+describe('validateNote', () => {
+ it('accepts a well-formed note', () => {
+ assert.deepEqual(validateNote(note()), []);
+ });
+
+ it('rejects an unknown type', () => {
+ const errors = validateNote(note({ type: 'chore' }));
+
+ assert.equal(errors.length, 1);
+ assert.match(errors[0], /unknown `type`: "chore"/);
+ });
+
+ it('rejects an unknown frontmatter key', () => {
+ const errors = validateNote(note({ unknownKeys: ['scope'] }));
+
+ assert.match(errors[0], /unknown frontmatter key: `scope`/);
+ });
+
+ it('rejects an empty body and an essay', () => {
+ assert.match(validateNote(note({ body: '' }))[0], /body is empty/);
+ assert.match(
+ validateNote(note({ body: 'x'.repeat(401) }))[0],
+ /max 400/
+ );
+ });
+
+ it('rejects a non-slug area and screenshot', () => {
+ assert.match(
+ validateNote(note({ area: 'Playback Engine' }))[0],
+ /`area` must be a lowercase slug/
+ );
+ assert.match(
+ validateNote(note({ screenshot: 'Up Next' }))[0],
+ /`screenshot` must be a lowercase slug/
+ );
+ });
+
+ it('rejects non-numeric issues', () => {
+ assert.match(
+ validateNote(note({ issues: [Number.NaN] }))[0],
+ /`issues` must be positive integers/
+ );
+ });
+});
+
+describe('loadNotes', () => {
+ it('returns an empty result for a missing directory', () => {
+ const result = loadNotes(path.join(tmpdir(), 'definitely-not-here-9d3f'));
+
+ assert.deepEqual(result, { notes: [], errors: [] });
+ });
+
+ it('skips README.md and reports per-file errors', () => {
+ const directory = makeNotesDir({
+ 'README.md': '# How to write notes',
+ 'a-good.md': '---\ntype: fix\narea: m3u\n---\nParses again.',
+ 'b-bad.md': '---\ntype: chore\narea: m3u\n---\nNope.',
+ });
+
+ const { notes, errors } = loadNotes(directory);
+
+ assert.equal(notes.length, 1);
+ assert.equal(notes[0].area, 'm3u');
+ assert.equal(errors.length, 1);
+ assert.match(errors[0], /^b-bad\.md: unknown `type`/);
+ });
+
+ it('sorts notes by filename for stable output', () => {
+ const directory = makeNotesDir({
+ 'z-last.md': '---\ntype: fix\narea: zzz\n---\nLast.',
+ 'a-first.md': '---\ntype: fix\narea: aaa\n---\nFirst.',
+ });
+
+ assert.deepEqual(
+ loadNotes(directory).notes.map((entry) => entry.area),
+ ['aaa', 'zzz']
+ );
+ });
+});
+
+describe('groupNotes', () => {
+ it('orders groups by severity and drops empty ones', () => {
+ const grouped = groupNotes([
+ note({ type: 'fix' }),
+ note({ type: 'breaking' }),
+ note({ type: 'feature' }),
+ ]);
+
+ assert.deepEqual(
+ grouped.map((group) => group.type),
+ ['breaking', 'feature', 'fix']
+ );
+ });
+});
+
+describe('renderGithubBody', () => {
+ it('groups entries, prefixes the area and links the PR', () => {
+ const links = new Map([
+ ['.changes/playback-up-next.md', { commit: 'abc1234', pr: 1231 }],
+ ]);
+
+ const body = renderGithubBody([note({ issues: [1187] })], { links });
+
+ assert.match(body, /^## Features\n\n- \*\*playback\*\* — Series now/);
+ assert.match(body, /\[#1231\]\(https:\/\/github\.com\/4gray\/iptvnator\/pull\/1231\)/);
+ assert.match(body, /closes \[#1187\]/);
+ });
+
+ it('falls back to a commit link when the note carries no PR', () => {
+ const links = new Map([
+ ['.changes/playback-up-next.md', { commit: 'abcdef1234567' }],
+ ]);
+
+ assert.match(renderGithubBody([note()], { links }), /\[abcdef1\]\(.*\/commit\/abcdef1234567\)/);
+ });
+
+ it('omits internal notes from the user-facing body', () => {
+ const body = renderGithubBody([
+ note({ type: 'internal', body: 'Split the store feature.' }),
+ note(),
+ ]);
+
+ assert.match(body, /## Features/);
+ assert.doesNotMatch(body, /Internal|Split the store feature/);
+ });
+});
+
+describe('renderChangelogSection', () => {
+ it('links the compare range when a previous version is known', () => {
+ const section = renderChangelogSection([note()], {
+ version: '0.24.0',
+ date: '2026-08-01',
+ previousVersion: '0.23.0',
+ });
+
+ assert.match(
+ section,
+ /^# \[0\.24\.0\]\(https:\/\/github\.com\/4gray\/iptvnator\/compare\/v0\.23\.0\.\.\.v0\.24\.0\) \(2026-08-01\)/
+ );
+ });
+
+ it('keeps internal notes but collapses them', () => {
+ const section = renderChangelogSection(
+ [note(), note({ type: 'internal', body: 'Split the store.' })],
+ { version: '0.24.0', date: '2026-08-01' }
+ );
+
+ assert.match(section, /### Features/);
+ assert.match(section, /Internal changes<\/summary>/);
+ assert.match(section, /Split the store\./);
+ });
+});
+
+describe('renderBlogScaffold', () => {
+ it('emits a draft with TODO markers and a release meta block', () => {
+ const content = renderBlogScaffold([note()], {
+ version: '0.24.0',
+ date: '2026-08-01',
+ });
+
+ assert.match(content, /^---\ntitle: v0\.24 - Release Notes/);
+ assert.match(content, /draft: true/);
+ assert.match(content, /TODO/);
+ assert.match(content, /releaseDate="August 1, 2026"/);
+ });
+
+ it('gives screenshot notes their own section with a dark/light slider', () => {
+ const content = renderBlogScaffold(
+ [note({ screenshot: 'up-next-rail' })],
+ { version: '0.24.0', date: '2026-08-01' }
+ );
+
+ assert.match(content, /### TODO headline \(playback\)/);
+ assert.match(
+ content,
+ /\/iptvnator\/blog\/v0-24\/screenshots\/up-next-rail-dark\.png/
+ );
+ assert.match(
+ content,
+ /\/iptvnator\/blog\/v0-24\/screenshots\/up-next-rail-light\.png/
+ );
+ });
+
+ it('truncates a long body for image alt text without cutting mid-word', () => {
+ const body = `${'Series show the rest of the season beside the player '.repeat(4)}now.`;
+ const content = renderBlogScaffold(
+ [note({ body, screenshot: 'up-next-rail' })],
+ { version: '0.24.0', date: '2026-08-01' }
+ );
+ const alt = content.match(/alt: '([^']*)'/)[1];
+
+ assert.ok(alt.length <= 121, `alt was ${alt.length} characters`);
+ assert.match(alt, /…$/);
+ assert.doesNotMatch(alt, /\s…$/);
+ });
+
+ it('escapes backslashes and apostrophes inside the alt string literal', () => {
+ const content = renderBlogScaffold(
+ [
+ note({
+ body: "Windows paths like C:\\Users no longer break the app's import.",
+ screenshot: 'windows-import',
+ }),
+ ],
+ { version: '0.24.0', date: '2026-08-01' }
+ );
+ const alt = content.match(/alt: '(.*)',/)[1];
+
+ assert.match(alt, /C:\\\\Users/);
+ assert.match(alt, /app\\'s/);
+ // An odd number of trailing backslashes would escape the closing quote.
+ assert.doesNotMatch(alt, /(^|[^\\])(\\\\)*\\$/);
+ });
+
+ it('escapes characters MDX would parse as markup', () => {
+ const content = renderBlogScaffold(
+ [note({ body: 'Channels named and {vod} now sort correctly.' })],
+ { version: '0.24.0', date: '2026-08-01' }
+ );
+
+ assert.doesNotMatch(content, //);
+ assert.doesNotMatch(content, /\{vod\}/);
+ assert.match(content, /<live>/);
+ assert.match(content, /{vod}/);
+ });
+
+ it('imports only the components it emits', () => {
+ const content = renderBlogScaffold([note()], {
+ version: '0.24.0',
+ date: '2026-08-01',
+ });
+
+ assert.match(content, /import ReleaseMeta from/);
+ assert.match(content, /import BlogImageSlider from/);
+ });
+});
+
+describe('upsertChangelogSection', () => {
+ const marker = '';
+ const base = [
+ '# Changelog',
+ '',
+ marker,
+ '',
+ '# [0.12.0](https://example.com) (2023-03-11)',
+ '',
+ '- old entry',
+ ].join('\n');
+
+ it('inserts a new section below the marker', () => {
+ const { content, replaced } = upsertChangelogSection(
+ base,
+ '# [0.24.0](url) (2026-08-01)\n\n### Features\n\n- entry',
+ '0.24.0',
+ marker
+ );
+
+ assert.equal(replaced, false);
+ assert.match(
+ content,
+ /\n\n# \[0\.24\.0\]\(url\) \(2026-08-01\)/
+ );
+ assert.match(content, /- entry\n\n# \[0\.12\.0\]/);
+ });
+
+ it('replaces an existing section for the same version instead of duplicating', () => {
+ const first = upsertChangelogSection(
+ base,
+ '# [0.24.0](url) (2026-08-01)\n\n- v1 entry',
+ '0.24.0',
+ marker
+ ).content;
+ const { content, replaced } = upsertChangelogSection(
+ first,
+ '# [0.24.0](url) (2026-08-02)\n\n- v2 entry',
+ '0.24.0',
+ marker
+ );
+
+ assert.equal(replaced, true);
+ assert.equal(content.match(/^# \[0\.24\.0\]/gm).length, 1);
+ assert.match(content, /v2 entry/);
+ assert.doesNotMatch(content, /v1 entry/);
+ assert.match(content, /- v2 entry\n\n# \[0\.12\.0\]/);
+ });
+
+ it('keeps other versions untouched when replacing', () => {
+ const first = upsertChangelogSection(
+ base,
+ '# [0.24.0](url) (2026-08-01)\n\n- v1',
+ '0.24.0',
+ marker
+ ).content;
+ const { content } = upsertChangelogSection(
+ first,
+ '# [0.24.1](url) (2026-08-09)\n\n- patch',
+ '0.24.1',
+ marker
+ );
+
+ assert.match(content, /0\.24\.1.*\n\n- patch\n\n# \[0\.24\.0\]/);
+ assert.match(content, /- v1\n\n# \[0\.12\.0\]/);
+ });
+
+ it('throws when the marker is missing', () => {
+ assert.throws(
+ () => upsertChangelogSection('# Changelog', '# s', '0.24.0', marker),
+ /missing the/
+ );
+ });
+});
+
+describe('extractSection', () => {
+ const changelog = [
+ '# Changelog',
+ '',
+ 'Intro paragraph with a pointer.',
+ '',
+ '',
+ '',
+ '# [0.24.0](https://github.com/4gray/iptvnator/compare/v0.23.0...v0.24.0) (2026-08-01)',
+ '',
+ '### Features',
+ '',
+ '- **playback** — Up Next rail.',
+ '',
+ '',
+ 'Internal changes
',
+ '',
+ '- **deps** — parser bump.',
+ '',
+ ' ',
+ '',
+ '# [0.12.0](https://github.com/4gray/iptvnator/compare/v0.11.1...v0.12.0) (2023-03-11)',
+ '',
+ '### Bug Fixes',
+ '',
+ '- old entry',
+ ].join('\n');
+
+ it('returns the section body without its own heading', () => {
+ const section = extractSection(changelog, '0.24.0');
+
+ assert.match(section, /^### Features/);
+ assert.match(section, /Up Next rail/);
+ assert.match(section, /<\/details>$/);
+ });
+
+ it('stops at the next release heading', () => {
+ const section = extractSection(changelog, '0.24.0');
+
+ assert.doesNotMatch(section, /0\.12\.0|old entry/);
+ });
+
+ it('matches the plain heading shape without a compare link', () => {
+ const plain = '# 0.24.0 (2026-08-01)\n\n### Fixes\n\n- entry';
+
+ assert.match(extractSection(plain, '0.24.0'), /^### Fixes/);
+ });
+
+ it('does not match a different patch of the same minor', () => {
+ assert.equal(extractSection(changelog, '0.24.1'), null);
+ });
+
+ it('returns null when the version is absent', () => {
+ assert.equal(extractSection(changelog, '9.9.9'), null);
+ });
+
+ it('treats regex metacharacters in the version as literals', () => {
+ // `.` must not act as a wildcard: 0x24y0 would match an unescaped 0.24.0
+ assert.equal(extractSection('# 0x24y0 (2026-08-01)\n\n- e', '0.24.0'), null);
+ // Injected pattern syntax must not throw or widen the match.
+ assert.equal(extractSection(changelog, '0.24.0|0.12.0'), null);
+ assert.equal(extractSection(changelog, '.*'), null);
+ assert.equal(extractSection(changelog, '0.24\\.0'), null);
+ });
+});
+
+describe('helpers', () => {
+ it('formats dates and release slugs', () => {
+ assert.equal(formatLongDate('2026-08-01'), 'August 1, 2026');
+ assert.equal(releaseSlug('0.24.0'), 'v0-24');
+ });
+});