mirror of
https://github.com/murashit/codex-panel.git
synced 2026-07-22 06:57:10 +00:00
chore(release): adopt Conventional Commits and generated release notes
This commit is contained in:
parent
84b920d0da
commit
8fc051ebd4
15 changed files with 859 additions and 10 deletions
|
|
@ -14,15 +14,16 @@ Use this skill when delegating Codex Panel release work to an agent. `docs/relea
|
|||
- Do not create GitHub Releases locally with `gh release create`; the tag-triggered GitHub Actions workflow owns release creation and asset attachment.
|
||||
- Keep internal validation notes, procedural details, and implementation reasoning out of release notes.
|
||||
- Release notes must be short, public-facing bullets under the single `## Changes` section required by `docs/release.md`.
|
||||
- Treat the release notes produced by `release:prepare` as a draft. Conventional Commit types select candidate bullets, but the full release diff remains the source for checking completeness and user-facing accuracy.
|
||||
|
||||
## Delegation Procedure
|
||||
|
||||
1. Read `docs/release.md`, `package.json`, `manifest.json`, `versions.json`, and existing `.github/release-notes/` files.
|
||||
2. Identify the target release version and the commit range since the previous released tag.
|
||||
3. Follow the preparation step in `docs/release.md`.
|
||||
4. Draft `.github/release-notes/X.Y.Z.md` from the full diff since the previous released tag, not only the latest commit.
|
||||
5. Before committing, ask the user to approve the release version, release-note bullets, and included commit range.
|
||||
6. After approval, follow `docs/release.md` for the commit, preflight, tag, and push sequence.
|
||||
3. Inspect the full diff since the previous released tag, then follow the preparation step in `docs/release.md`; it updates version files and generates `.github/release-notes/X.Y.Z.md` from Conventional Commits.
|
||||
4. Review the generated draft against the full diff. Rewrite bullets for users, combine related implementation commits, reorder by importance, add an omitted user-facing change when a commit was misclassified, and replace the empty placeholder when no candidate commit was generated.
|
||||
5. Before committing, ask the user to approve the release version, reviewed release-note bullets, and included commit range.
|
||||
6. After approval, follow `docs/release.md` for the Conventional Commit, preflight, tag, and push sequence. Do not rely on a local hook; preflight explicitly checks commits since the previous version in `versions.json`.
|
||||
7. After pushing, let GitHub Actions create or update the GitHub Release.
|
||||
|
||||
## Failure Handling
|
||||
|
|
|
|||
5
.github/dependabot.yml
vendored
5
.github/dependabot.yml
vendored
|
|
@ -4,6 +4,8 @@ updates:
|
|||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
commit-message:
|
||||
prefix: "ci(deps)"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
|
||||
|
|
@ -11,6 +13,9 @@ updates:
|
|||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
commit-message:
|
||||
prefix: "chore(deps)"
|
||||
prefix-development: "chore(deps)"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
open-pull-requests-limit: 5
|
||||
|
|
|
|||
15
.github/workflows/check.yml
vendored
15
.github/workflows/check.yml
vendored
|
|
@ -18,6 +18,7 @@ jobs:
|
|||
- name: Checkout
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Node.js
|
||||
|
|
@ -32,6 +33,20 @@ jobs:
|
|||
- name: Check recorded API baselines
|
||||
run: npm run api:baseline -- --recorded-only
|
||||
|
||||
- name: Check pull request commit messages
|
||||
if: github.event_name == 'pull_request'
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: npm run commitlint -- --from "$BASE_SHA" --to "$HEAD_SHA" --verbose
|
||||
|
||||
- name: Check pushed commit messages
|
||||
if: github.event_name == 'push'
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.before }}
|
||||
HEAD_SHA: ${{ github.sha }}
|
||||
run: npm run commitlint -- --from "$BASE_SHA" --to "$HEAD_SHA" --verbose
|
||||
|
||||
- name: Check release metadata
|
||||
run: npm run release:check
|
||||
|
||||
|
|
|
|||
9
.github/workflows/release.yml
vendored
9
.github/workflows/release.yml
vendored
|
|
@ -19,6 +19,7 @@ jobs:
|
|||
- name: Checkout
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Node.js
|
||||
|
|
@ -35,6 +36,14 @@ jobs:
|
|||
env:
|
||||
RELEASE_VERSION: ${{ github.ref_name }}
|
||||
|
||||
- name: Check release commit messages
|
||||
env:
|
||||
TAG: ${{ github.ref_name }}
|
||||
run: |
|
||||
PREVIOUS_TAG="$(node -p 'Object.keys(require("./versions.json")).at(-2)')"
|
||||
git rev-parse --verify "refs/tags/$PREVIOUS_TAG"
|
||||
npm run commitlint -- --from "$PREVIOUS_TAG" --to "$TAG" --verbose
|
||||
|
||||
- name: Run checks and build
|
||||
run: npm run check
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ This repository contains the Codex Panel Obsidian plugin.
|
|||
|
||||
Jujutsu is the recommended local change-management workflow when available.
|
||||
|
||||
Commits after the `5.0.0` tag must follow Conventional Commits. Use the repository's allowed types and examples in `docs/development.md`, and validate the relevant commit range explicitly because Jujutsu does not rely on local Git hooks.
|
||||
|
||||
## What To Read
|
||||
|
||||
- Read `README.md` for user-facing behavior, requirements, commands, privacy, and compatibility.
|
||||
|
|
|
|||
9
commitlint.config.mjs
Normal file
9
commitlint.config.mjs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
export default {
|
||||
defaultIgnores: false,
|
||||
extends: ["@commitlint/config-conventional"],
|
||||
ignores: [(message) => /^Merge pull request #\d+ from \S+/.test(message)],
|
||||
rules: {
|
||||
"subject-case": [0],
|
||||
"type-enum": [2, "always", ["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "revert", "test"]],
|
||||
},
|
||||
};
|
||||
|
|
@ -14,6 +14,21 @@ Use Node.js 26, matching `.node-version`, CI, and the installed Node type defini
|
|||
|
||||
Use this as the normal edit loop: make the change, run `npm run fix`, then run `npm run check`. Treat `npm run fix` as trusted mechanical cleanup for formatting, import ordering, and Knip safe fixes; review the resulting diff at normal change-boundary checkpoints rather than after each tool adjustment.
|
||||
|
||||
## Commit Messages
|
||||
|
||||
Commits after the `5.0.0` tag follow [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/):
|
||||
|
||||
```text
|
||||
feat(composer): add daily note context suggestions
|
||||
fix(threads): prevent manual titles from being overwritten
|
||||
refactor(chat): move session wiring into the runtime
|
||||
chore(release): 5.0.1
|
||||
```
|
||||
|
||||
Use one of `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, or `test`. Scopes are optional and are not restricted to a fixed list. Keep the description concise and omit a trailing period. Both lowercase and uppercase starts are accepted so Dependabot's generated `Bump ...` descriptions follow the same validation path. Use `!` before the colon or a `BREAKING CHANGE:` footer for a disruptive change.
|
||||
|
||||
CI checks every commit introduced by a pull request or direct push. GitHub-generated `Merge pull request ...` commits are the only format exemption; write manual reverts as `revert: ...`, and rewrite `fixup!` or `squash!` commits before publication. Run `npm run commitlint -- --from <base> --to <head> --verbose` for the same local check; local Git hooks are optional and are not a substitute for CI in the Jujutsu-first workflow.
|
||||
|
||||
Use focused scripts such as `npm run typecheck`, `npm run test`, or `npm run build` only when diagnosing a specific failure or when a full check would obscure the signal while iterating. Do not treat focused scripts as a substitute for the final `npm run check`. CI and release preflight run the same `npm run check` command as local development.
|
||||
|
||||
Keep rule suppressions local and include the Obsidian-specific reason when a native Obsidian UI pattern intentionally diverges from a generic browser rule.
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ Release work is Jujutsu-first in a colocated Git repository; Git is still used t
|
|||
|
||||
Plugin versions use SemVer-shaped numbers for Obsidian distribution, but they are not a library API compatibility contract. Prefer patch releases for fixes, dependency updates, internal changes, and compatibility refreshes that preserve existing workflows, including routine Codex CLI app-server compatibility updates. Prefer minor releases for user-visible capabilities, settings, workflow additions, or supported-runtime baseline changes such as raising the minimum supported Obsidian app/API version. Reserve major releases for disruptive workflow, settings, storage, or support-policy changes.
|
||||
|
||||
Create a release by preparing the next version, editing the generated release notes, committing the release changes, then running the preflight before pushing the matching tag:
|
||||
Create a release by preparing the next version, reviewing and editing the generated release notes, committing the release changes, then running the preflight before pushing the matching tag:
|
||||
|
||||
```sh
|
||||
npm run release:prepare -- X.Y.Z
|
||||
# Edit .github/release-notes/X.Y.Z.md.
|
||||
# Review and edit .github/release-notes/X.Y.Z.md.
|
||||
jj status
|
||||
jj commit -m "Bump version to X.Y.Z"
|
||||
jj commit -m "chore(release): X.Y.Z"
|
||||
jj bookmark move main --to @-
|
||||
npm run release:preflight
|
||||
jj tag set X.Y.Z -r main
|
||||
|
|
@ -20,7 +20,9 @@ jj git push --remote origin --bookmark main
|
|||
git push origin X.Y.Z
|
||||
```
|
||||
|
||||
`release:prepare` updates the version files and creates a `## Changes` release notes template. `release:preflight` verifies the local Jujutsu/Git state, release metadata, API baselines, lockfile, and the same `npm run check` validation used by CI after the release commit is on `main`.
|
||||
`release:prepare` updates the version files and generates a `## Changes` release notes draft from Conventional Commits after the previous version tag. It includes `feat`, `fix`, `perf`, and commits marked as breaking changes; other commit types are omitted. Review the generated bullets for user-facing wording, combine related implementation commits, and reorder them by importance before committing. If there are no included commits, preparation leaves an empty bullet to replace manually.
|
||||
|
||||
`release:preflight` verifies all commit messages since the previous tag, the local Jujutsu/Git state, release metadata, API baselines, lockfile, and the same `npm run check` validation used by CI after the release commit is on `main`.
|
||||
|
||||
Release notes should normally include only user-facing changes. Internal implementation changes, validation details, and release procedure notes should be omitted when minor; when they are important enough to mention, group them into at most one concise bullet.
|
||||
|
||||
|
|
|
|||
601
package-lock.json
generated
601
package-lock.json
generated
|
|
@ -18,8 +18,12 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^2.5.2",
|
||||
"@commitlint/cli": "^21.2.1",
|
||||
"@commitlint/config-conventional": "^21.2.0",
|
||||
"@types/node": "^26.1.0",
|
||||
"concurrently": "^10.0.3",
|
||||
"conventional-changelog-conventionalcommits": "^10.2.1",
|
||||
"conventional-commits-parser": "^7.1.0",
|
||||
"esbuild": "^0.28.0",
|
||||
"eslint": "^10.6.0",
|
||||
"eslint-plugin-obsidianmd": "^0.4.1",
|
||||
|
|
@ -86,6 +90,31 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.29.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
|
||||
"integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.29.7",
|
||||
"js-tokens": "^4.0.0",
|
||||
"picocolors": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.29.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
|
||||
"integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@biomejs/biome": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.2.tgz",
|
||||
|
|
@ -297,6 +326,328 @@
|
|||
"w3c-keyname": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/cli": {
|
||||
"version": "21.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-21.2.1.tgz",
|
||||
"integrity": "sha512-blsZGe29hJ72VGEFVl72IVYX+1vsfINpjA9yWQA6i7OKD/McGEOXg08sKIRKjFk4JvzhV/9n0l3i6NooPLTNfg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@commitlint/config-conventional": "^21.2.0",
|
||||
"@commitlint/format": "^21.2.0",
|
||||
"@commitlint/lint": "^21.2.0",
|
||||
"@commitlint/load": "^21.2.0",
|
||||
"@commitlint/read": "^21.2.1",
|
||||
"@commitlint/types": "^21.2.0",
|
||||
"tinyexec": "^1.0.0",
|
||||
"yargs": "^18.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"commitlint": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/config-conventional": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-21.2.0.tgz",
|
||||
"integrity": "sha512-Qf8WRDVcyVd14if6VTWenebxFbKnVnbzPUJjlzjkyJGeHK2xCGd63Dr1XZzj0plXKQb9P0BfOxoc1HVeCo2BWQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@commitlint/types": "^21.2.0",
|
||||
"conventional-changelog-conventionalcommits": "^10.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/config-validator": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-21.2.0.tgz",
|
||||
"integrity": "sha512-t7AzNHAKeIdo/3NRGwzpufKHsKkPHmFs/56N2Fnsh0/r0rGtnQzTxk6vnFgjaGr4hdSQKNB50/KAhR9Yk4LJKA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@commitlint/types": "^21.2.0",
|
||||
"ajv": "^8.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/config-validator/node_modules/ajv": {
|
||||
"version": "8.20.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
|
||||
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/config-validator/node_modules/json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@commitlint/ensure": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-21.2.0.tgz",
|
||||
"integrity": "sha512-76IF9vDNS13lAzEEik9eKwzt8f9hYhWiwVXZ2AnyLCz5/f511FsEQ3pw1X3/zSQpdRLQU7i5qDMVKyXi1GWjSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@commitlint/types": "^21.2.0",
|
||||
"es-toolkit": "^1.46.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/execute-rule": {
|
||||
"version": "21.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-21.0.1.tgz",
|
||||
"integrity": "sha512-RifH+FmImozKBE6mozhF4K3r2RRKP7SMi/Q/zLCmExtp5e05lhHOUYqGBlFBAGNHaZxU/WYw1XuugYK9jQzqnA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/format": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/format/-/format-21.2.0.tgz",
|
||||
"integrity": "sha512-c4q64xaav2U83t7k7RyzJerBZurPer7FxUOY0RL5L/6CZijZ7K+s6HIBGIghj0ey1P2+seRX0J9XQYtDued6tg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@commitlint/types": "^21.2.0",
|
||||
"picocolors": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/is-ignored": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-21.2.0.tgz",
|
||||
"integrity": "sha512-4/eB0vBN7L88O/oC4ajAEqi7j2ZfNgxl/+11RfAV9YosejZgDXhY2C9VcHnHJhOzPLoSy5P3Mg/46kqeyJfXKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@commitlint/types": "^21.2.0",
|
||||
"semver": "^7.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/lint": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-21.2.0.tgz",
|
||||
"integrity": "sha512-ceO5dp9pLjEZ6y6qbq/uXWXDPykqqlTsyzoQ0NzecpisSJhK3kTy9qzQoPeJuWG/IMNdV1lO0RgmzqoAlSi1uw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@commitlint/is-ignored": "^21.2.0",
|
||||
"@commitlint/parse": "^21.2.0",
|
||||
"@commitlint/rules": "^21.2.0",
|
||||
"@commitlint/types": "^21.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/load": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/load/-/load-21.2.0.tgz",
|
||||
"integrity": "sha512-RjlzWQqruRwIenJEfZtq7kG97co97nKoHpflE5YnF61tDLXxHPrdWImgzw6VL6MlFyaOcVlk74eBV8ZQmc3oIA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@commitlint/config-validator": "^21.2.0",
|
||||
"@commitlint/execute-rule": "^21.0.1",
|
||||
"@commitlint/resolve-extends": "^21.2.0",
|
||||
"@commitlint/types": "^21.2.0",
|
||||
"cosmiconfig": "^9.0.1",
|
||||
"cosmiconfig-typescript-loader": "^6.1.0",
|
||||
"es-toolkit": "^1.46.0",
|
||||
"is-plain-obj": "^4.1.0",
|
||||
"picocolors": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/message": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/message/-/message-21.2.0.tgz",
|
||||
"integrity": "sha512-YxGoiXD/HXNXLJPrQwE5poXa+XH0CBEm+mdvbHQP0g6MV/dmJyUFCzPNzZbxL93GvZ70TmtTK0Z0/IBpAqHv8g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/parse": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-21.2.0.tgz",
|
||||
"integrity": "sha512-QHWxG4d0PLTF634/AdyZ0MQS+CLn5YOuJlCFhMMlSGKFxzYGUetkHBj18xgBD+6fVzUrA2lrCdi/vlS2f/oYXg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@commitlint/types": "^21.2.0",
|
||||
"conventional-changelog-angular": "^9.0.0",
|
||||
"conventional-commits-parser": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/read": {
|
||||
"version": "21.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/read/-/read-21.2.1.tgz",
|
||||
"integrity": "sha512-hUW7EJQnNTL0vPOmVMNK4CrnrNBN0nN+JJHReFkdHO5y4iyHeEmTBwuC15OCqUTjxWo7idnH1LftfpWVIaPWIA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@commitlint/top-level": "^21.2.0",
|
||||
"@commitlint/types": "^21.2.0",
|
||||
"@conventional-changelog/git-client": "^3.0.0",
|
||||
"tinyexec": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/resolve-extends": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-21.2.0.tgz",
|
||||
"integrity": "sha512-4O/1j51+79Wth9s/MGxt/5gs0XYLDgNlYpltQfhAvLE0itusLKs9zruxbiNg1oOkmkb9L9L4USYGjEj7n87NxA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@commitlint/config-validator": "^21.2.0",
|
||||
"@commitlint/types": "^21.2.0",
|
||||
"es-toolkit": "^1.46.0",
|
||||
"global-directory": "^5.0.0",
|
||||
"resolve-from": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/resolve-extends/node_modules/resolve-from": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
|
||||
"integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/rules": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-21.2.0.tgz",
|
||||
"integrity": "sha512-C2yXMNpiB8ETZKfx5JD8+ExgF8vTU1VQMKPSUUYwqKpw9oJWQBrlXBpdU038mj2WPjof7o9UzFpmTyBeGMZwZg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@commitlint/ensure": "^21.2.0",
|
||||
"@commitlint/message": "^21.2.0",
|
||||
"@commitlint/to-lines": "^21.0.1",
|
||||
"@commitlint/types": "^21.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/to-lines": {
|
||||
"version": "21.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-21.0.1.tgz",
|
||||
"integrity": "sha512-bd1BFII7p1EQZre9Kaj+kKaMFP3cFCdt21K7DItVux9XP5WjLgJ0/Uy1pJJh9aPwVJ6SKg62PxqlZaHI8hQAXw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/top-level": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-21.2.0.tgz",
|
||||
"integrity": "sha512-Y5gmQ+KxzqCrBFJfLvFEPvvwD3LDiNZoTT2yeFBm96M8qhmqSzQc5DvX3rheAaAMjyIvMXOCLS/mWfdpONsjyQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"escalade": "^3.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/types": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/types/-/types-21.2.0.tgz",
|
||||
"integrity": "sha512-7zVFCDB2reMvJH5dmbKnOQPjZEvjdJTH8jc0U/PIPU1r3/+vf5pD1HlfitV2MWsWXrvu7u39iY1lyLUPOaN0Gw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"conventional-commits-parser": "^7.0.0",
|
||||
"picocolors": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@conventional-changelog/git-client": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@conventional-changelog/git-client/-/git-client-3.1.0.tgz",
|
||||
"integrity": "sha512-Tqa/gHco2WJWa740NRjOrfKVvzIqxkZpecb8bemaQ8sKM5PXb1UK4uTyTb/1wIqNuOVaDOFxyBdhTIQZn6gdjQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@simple-libs/child-process-utils": "^2.0.0",
|
||||
"@simple-libs/stream-utils": "^2.0.0",
|
||||
"semver": "^7.5.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"conventional-commits-filter": "^6.0.1",
|
||||
"conventional-commits-parser": "^7.0.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"conventional-commits-filter": {
|
||||
"optional": true
|
||||
},
|
||||
"conventional-commits-parser": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@conventional-changelog/template": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@conventional-changelog/template/-/template-1.2.1.tgz",
|
||||
"integrity": "sha512-TzlTVpKPjaqW6qOYjQcYUDuGsLCNsvFHVBXkYGTAnf5V37jCWrE5haKNXzz0WZUtVHjrpV76L1buANjwXMfT8w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/color-helpers": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz",
|
||||
|
|
@ -2322,6 +2673,35 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@simple-libs/child-process-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@simple-libs/child-process-utils/-/child-process-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-dvNoRKLijXnD0XoJAz94pbNuB5GQgDr55UhpSPhffDkTT0Cmcqh9jSCOtwfT2d4H6MI9E7c4SgtMuJXZ6F3c6A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@simple-libs/stream-utils": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/dangreen"
|
||||
}
|
||||
},
|
||||
"node_modules/@simple-libs/stream-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@simple-libs/stream-utils/-/stream-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-fCTuZK4QBa+39Oz9l4OGfJfz+GpwCp3AqO7Zch3to99xHPgstVsRFpeQ8LNd2o1Gv8raL2mCFwiaHh7bFSp5DQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/dangreen"
|
||||
}
|
||||
},
|
||||
"node_modules/@standard-schema/spec": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
|
||||
|
|
@ -2881,6 +3261,19 @@
|
|||
"dev": true,
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/argue-cli": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/argue-cli/-/argue-cli-3.1.0.tgz",
|
||||
"integrity": "sha512-DhBpBfXL4SS2uC0N922MMajKR3CdrTG0u2or1PNYgXMsrSzViJrbtvT0nCLlLGUI0plam/ZZCs7aAauHtW9thw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/dangreen"
|
||||
}
|
||||
},
|
||||
"node_modules/array-buffer-byte-length": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
|
||||
|
|
@ -3341,6 +3734,49 @@
|
|||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/conventional-changelog-angular": {
|
||||
"version": "9.2.1",
|
||||
"resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-9.2.1.tgz",
|
||||
"integrity": "sha512-oWSL6ZhnXbYraOFTK3PgRAQJ8fADDAEv5K6AdeyQPLvjFmhG8+ejL0jZZp/R7vTmGJaBvZEE+sE7dB4bCv7sAw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@conventional-changelog/template": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
}
|
||||
},
|
||||
"node_modules/conventional-changelog-conventionalcommits": {
|
||||
"version": "10.2.1",
|
||||
"resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-10.2.1.tgz",
|
||||
"integrity": "sha512-n4Kr1HFMTf3iMbES0TMxKIcYtUUv4rKqyQQp2JwfOEfFCOfGT3Tq4mCyJ8S9/YPyWhydjfKrrvnyl+gCjA+mJQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@conventional-changelog/template": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
}
|
||||
},
|
||||
"node_modules/conventional-commits-parser": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-7.1.0.tgz",
|
||||
"integrity": "sha512-DPp6hkUjvwIivxbkrTiLXeRswNv1A/4GFA2X6scXma0AMa9632V3TwxmrlkUIEtUktiM3Ln+RrSH2xlP3/jUTw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@simple-libs/stream-utils": "^2.0.0",
|
||||
"argue-cli": "^3.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"conventional-commits-parser": "dist/cli/index.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
}
|
||||
},
|
||||
"node_modules/convert-source-map": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
||||
|
|
@ -3348,6 +3784,61 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cosmiconfig": {
|
||||
"version": "9.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.2.tgz",
|
||||
"integrity": "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"env-paths": "^2.2.1",
|
||||
"import-fresh": "^3.3.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"parse-json": "^5.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/d-fischer"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=4.9.5"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cosmiconfig-typescript-loader": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.3.0.tgz",
|
||||
"integrity": "sha512-Akr82WH1Wfqatyiqpj8HDkO2o2KmJRu1FhKfSNJP3K4IdXwHfEyL7MOb62i1AGQVLtIQM+iCE9CGOtrfhR+mmA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"jiti": "2.6.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=v18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": "*",
|
||||
"cosmiconfig": ">=9",
|
||||
"typescript": ">=5"
|
||||
}
|
||||
},
|
||||
"node_modules/cosmiconfig-typescript-loader/node_modules/jiti": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
|
||||
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"jiti": "lib/jiti-cli.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/crelt": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
|
||||
|
|
@ -3756,6 +4247,26 @@
|
|||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/env-paths": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
|
||||
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/error-ex": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
|
||||
"integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-arrayish": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/es-abstract": {
|
||||
"version": "1.24.2",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz",
|
||||
|
|
@ -3940,6 +4451,17 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/es-toolkit": {
|
||||
"version": "1.49.0",
|
||||
"resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.49.0.tgz",
|
||||
"integrity": "sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"docs",
|
||||
"benchmarks"
|
||||
]
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
|
||||
|
|
@ -5260,6 +5782,22 @@
|
|||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/global-directory": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/global-directory/-/global-directory-5.0.0.tgz",
|
||||
"integrity": "sha512-1pgFdhK3J2LeM+dVf2Pd424yHx2ou338lC0ErNP2hPx4j8eW1Sp0XqSjNxtk6Tc4Kr5wlWtSvz8cn2yb7/SG/w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ini": "6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/globals": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
|
||||
|
|
@ -5494,6 +6032,16 @@
|
|||
"node": ">=0.8.19"
|
||||
}
|
||||
},
|
||||
"node_modules/ini": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz",
|
||||
"integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": "^20.17.0 || >=22.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/internal-slot": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
|
||||
|
|
@ -5527,6 +6075,13 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-arrayish": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
||||
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-async-function": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
|
||||
|
|
@ -5746,6 +6301,19 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-plain-obj": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
|
||||
"integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-potential-custom-element-name": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
|
||||
|
|
@ -6018,6 +6586,13 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-parse-even-better-errors": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
|
||||
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-schema-migrate": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-migrate/-/json-schema-migrate-2.0.0.tgz",
|
||||
|
|
@ -6481,6 +7056,13 @@
|
|||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lines-and-columns": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/linkedom": {
|
||||
"version": "0.18.12",
|
||||
"resolved": "https://registry.npmjs.org/linkedom/-/linkedom-0.18.12.tgz",
|
||||
|
|
@ -7444,6 +8026,25 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-json": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
|
||||
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"error-ex": "^1.3.1",
|
||||
"json-parse-even-better-errors": "^2.3.0",
|
||||
"lines-and-columns": "^1.1.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/parse5": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz",
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
"api:baseline": "node scripts/api-baseline.mjs",
|
||||
"build": "node esbuild.config.mjs",
|
||||
"build:styles": "node scripts/build-styles.mjs",
|
||||
"commitlint": "commitlint",
|
||||
"check": "concurrently --group --pad-prefix 'node:check:*' && node --run build",
|
||||
"check:biome": "biome check --diagnostic-level=warn --error-on-warnings",
|
||||
"check:css-usage": "node scripts/check-css-usage.mjs",
|
||||
|
|
@ -30,6 +31,7 @@
|
|||
"fix": "biome check --fix --skip=plugin --diagnostic-level=warn --error-on-warnings && knip --fix --no-progress",
|
||||
"generate:app-server-types": "node scripts/generate-app-server-types.mjs",
|
||||
"release:check": "node scripts/release/check.mjs",
|
||||
"release:notes": "node scripts/release/notes.mjs",
|
||||
"release:preflight": "node scripts/release/preflight.mjs",
|
||||
"release:prepare": "node scripts/release/prepare.mjs",
|
||||
"test": "vitest run --pool threads --maxWorkers 6",
|
||||
|
|
@ -37,8 +39,12 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^2.5.2",
|
||||
"@commitlint/cli": "^21.2.1",
|
||||
"@commitlint/config-conventional": "^21.2.0",
|
||||
"@types/node": "^26.1.0",
|
||||
"concurrently": "^10.0.3",
|
||||
"conventional-changelog-conventionalcommits": "^10.2.1",
|
||||
"conventional-commits-parser": "^7.1.0",
|
||||
"esbuild": "^0.28.0",
|
||||
"eslint": "^10.6.0",
|
||||
"eslint-plugin-obsidianmd": "^0.4.1",
|
||||
|
|
|
|||
73
scripts/release/notes.mjs
Normal file
73
scripts/release/notes.mjs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import { spawnSync } from "node:child_process";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import conventionalCommits from "conventional-changelog-conventionalcommits";
|
||||
import { CommitParser } from "conventional-commits-parser";
|
||||
|
||||
const releaseNoteTypes = new Set(["feat", "fix", "perf"]);
|
||||
const parser = new CommitParser(conventionalCommits().parser);
|
||||
|
||||
function fail(message) {
|
||||
throw new Error(`release notes generation failed: ${message}`);
|
||||
}
|
||||
|
||||
function runGit(args, cwd) {
|
||||
const result = spawnSync("git", args, {
|
||||
cwd,
|
||||
encoding: "utf8",
|
||||
shell: false,
|
||||
});
|
||||
if (result.error) fail(result.error.message);
|
||||
if (result.status !== 0) {
|
||||
fail(`${args.join(" ")} exited with ${result.status}: ${result.stderr.trim()}`);
|
||||
}
|
||||
return result.stdout;
|
||||
}
|
||||
|
||||
function formatSubject(subject) {
|
||||
const sentence = subject.replace(/^([a-z])/, (letter) => letter.toUpperCase());
|
||||
return /[.!?]$/.test(sentence) ? sentence : `${sentence}.`;
|
||||
}
|
||||
|
||||
export function releaseNoteForCommit(message) {
|
||||
const commit = parser.parse(message);
|
||||
if (!commit.subject) return null;
|
||||
|
||||
const isBreaking = commit.notes.length > 0;
|
||||
if (!isBreaking && !releaseNoteTypes.has(commit.type ?? "")) return null;
|
||||
|
||||
return formatSubject(commit.subject);
|
||||
}
|
||||
|
||||
export function renderReleaseNotes(messages) {
|
||||
const entries = messages.map(releaseNoteForCommit).filter((entry) => entry !== null);
|
||||
const bullets = entries.length > 0 ? entries.map((entry) => `- ${entry}`).join("\n") : "- ";
|
||||
return `## Changes\n\n${bullets}\n`;
|
||||
}
|
||||
|
||||
export function readCommitMessagesSince(tag, cwd = process.cwd()) {
|
||||
runGit(["rev-parse", "--verify", `refs/tags/${tag}`], cwd);
|
||||
const output = runGit(["log", "--format=%B%x00", `${tag}..HEAD`], cwd);
|
||||
return output
|
||||
.split("\0")
|
||||
.map((message) => message.trim())
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
export function generateReleaseNotes(tag, cwd = process.cwd()) {
|
||||
return renderReleaseNotes(readCommitMessagesSince(tag, cwd));
|
||||
}
|
||||
|
||||
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
||||
const previousTag = process.argv[2];
|
||||
if (!previousTag) {
|
||||
console.error("usage: npm run release:notes -- X.Y.Z");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
process.stdout.write(generateReleaseNotes(previousTag));
|
||||
} catch (error) {
|
||||
console.error(error instanceof Error ? error.message : error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import { spawnSync } from "node:child_process";
|
||||
import { readFileSync } from "node:fs";
|
||||
|
||||
function fail(message) {
|
||||
console.error(`release preflight failed: ${message}`);
|
||||
|
|
@ -81,6 +82,11 @@ if (maybeRun("jj", ["root"])) {
|
|||
assertGitReleaseState(packageVersion);
|
||||
}
|
||||
|
||||
const versionKeys = Object.keys(JSON.parse(readFileSync("versions.json", "utf8")));
|
||||
const previousTag = versionKeys.at(-2);
|
||||
if (!previousTag) fail("versions.json must contain a release before the prepared version");
|
||||
run("git", ["rev-parse", "--verify", `refs/tags/${previousTag}`], { capture: true });
|
||||
run("npm", ["run", "commitlint", "--", "--from", previousTag, "--to", "main", "--verbose"]);
|
||||
run("npm", ["run", "release:check"]);
|
||||
run("npm", ["run", "api:baseline"]);
|
||||
run("npm", ["ci", "--dry-run"]);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { generateReleaseNotes } from "./notes.mjs";
|
||||
import { compareVersions, isExpectedNextVersion, parseVersion } from "./versioning.mjs";
|
||||
|
||||
function fail(message) {
|
||||
|
|
@ -38,6 +39,13 @@ try {
|
|||
if (error.code !== "ENOENT") throw error;
|
||||
}
|
||||
|
||||
let releaseNotes;
|
||||
try {
|
||||
releaseNotes = generateReleaseNotes(previousVersionKey);
|
||||
} catch (error) {
|
||||
fail(error instanceof Error ? error.message : String(error));
|
||||
}
|
||||
|
||||
packageJson.version = releaseVersion;
|
||||
packageLockJson.version = releaseVersion;
|
||||
if (!packageLockJson.packages?.[""]) fail('package-lock.json is missing packages[""]');
|
||||
|
|
@ -51,7 +59,7 @@ await writeFile("manifest.json", `${JSON.stringify(manifestJson, null, 2)}\n`);
|
|||
await writeFile("versions.json", `${JSON.stringify(versionsJson, null, 2)}\n`);
|
||||
|
||||
await mkdir(notesDir, { recursive: true });
|
||||
await writeFile(notesPath, "## Changes\n\n- \n");
|
||||
await writeFile(notesPath, releaseNotes);
|
||||
|
||||
console.log(`prepared release ${releaseVersion}`);
|
||||
console.log(`edit ${notesPath}, then run npm run release:preflight after committing`);
|
||||
console.log(`review and edit ${notesPath}, then run npm run release:preflight after committing`);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,16 @@ afterEach(async () => {
|
|||
});
|
||||
|
||||
describe("development scripts", () => {
|
||||
it("enforces Conventional Commits except for GitHub merge commits", () => {
|
||||
for (const message of ["feat: add side chats", "Merge pull request #123 from owner/feature"]) {
|
||||
expect(runCommitlint(message), message).toBe(0);
|
||||
}
|
||||
|
||||
for (const message of ['Revert "feat: add side chats"', "v5.1.0", "fixup! feat: add side chats", "squash! feat: add side chats"]) {
|
||||
expect(runCommitlint(message), message).toBe(1);
|
||||
}
|
||||
});
|
||||
|
||||
it("fails style builds when CSS files are missing from the style order file", async () => {
|
||||
const cwd = await styleOrderFixture();
|
||||
|
||||
|
|
@ -172,6 +182,34 @@ describe("development scripts", () => {
|
|||
expect(result.stderr).toContain("codex-panel__unused");
|
||||
});
|
||||
|
||||
it("prepares release notes from conventional commits since the previous tag", async () => {
|
||||
const cwd = await tempWorkspace();
|
||||
await writeJson(path.join(cwd, "package.json"), { version: "2.3.2" });
|
||||
await writeJson(path.join(cwd, "package-lock.json"), {
|
||||
version: "2.3.2",
|
||||
packages: { "": { version: "2.3.2" } },
|
||||
});
|
||||
await writeJson(path.join(cwd, "manifest.json"), { version: "2.3.2", minAppVersion: "1.12.0" });
|
||||
await writeJson(path.join(cwd, "versions.json"), { "2.3.2": "1.12.0" });
|
||||
runGit(["init"], cwd);
|
||||
runGit(["config", "user.name", "Codex Panel Tests"], cwd);
|
||||
runGit(["config", "user.email", "tests@example.com"], cwd);
|
||||
runGit(["add", "."], cwd);
|
||||
runGit(["commit", "-m", "chore: establish release baseline"], cwd);
|
||||
runGit(["tag", "2.3.2"], cwd);
|
||||
await writeFile(path.join(cwd, "change.txt"), "side chats\n");
|
||||
runGit(["add", "change.txt"], cwd);
|
||||
runGit(["commit", "-m", "feat(chat): add side chat support"], cwd);
|
||||
|
||||
const result = runNodeScript("scripts/release/prepare.mjs", ["2.4.0"], cwd);
|
||||
|
||||
expect(result.status).toBe(0);
|
||||
await expect(readFile(path.join(cwd, ".github", "release-notes", "2.4.0.md"), "utf8")).resolves.toBe(
|
||||
"## Changes\n\n- Add side chat support.\n",
|
||||
);
|
||||
await expect(readJson(path.join(cwd, "package.json"))).resolves.toMatchObject({ version: "2.4.0" });
|
||||
});
|
||||
|
||||
it("fails release prepare before changing version files when release notes already exist", async () => {
|
||||
const cwd = await tempWorkspace();
|
||||
await mkdir(path.join(cwd, ".github", "release-notes"), { recursive: true });
|
||||
|
|
@ -236,6 +274,20 @@ function runNodeScript(script: string, args: string[] = [], cwd = repoRoot, env:
|
|||
});
|
||||
}
|
||||
|
||||
function runCommitlint(message: string): number | null {
|
||||
return spawnSync(process.execPath, [path.join(repoRoot, "node_modules", "@commitlint", "cli", "cli.js")], {
|
||||
cwd: repoRoot,
|
||||
encoding: "utf8",
|
||||
input: `${message}\n`,
|
||||
shell: false,
|
||||
}).status;
|
||||
}
|
||||
|
||||
function runGit(args: string[], cwd: string): void {
|
||||
const result = spawnSync("git", args, { cwd, encoding: "utf8", shell: false });
|
||||
if (result.status !== 0) throw new Error(`git ${args.join(" ")} failed: ${result.stderr}`);
|
||||
}
|
||||
|
||||
async function writeJson(file: string, value: unknown): Promise<void> {
|
||||
await writeFile(file, `${JSON.stringify(value, null, 2)}\n`);
|
||||
}
|
||||
|
|
|
|||
45
tests/scripts/release-notes.test.ts
Normal file
45
tests/scripts/release-notes.test.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import path from "node:path";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
const { releaseNoteForCommit, renderReleaseNotes } = (await import(
|
||||
pathToFileURL(path.join(process.cwd(), "scripts", "release", "notes.mjs")).href
|
||||
)) as {
|
||||
releaseNoteForCommit(message: string): string | null;
|
||||
renderReleaseNotes(messages: string[]): string;
|
||||
};
|
||||
|
||||
describe("release notes", () => {
|
||||
it("renders user-facing conventional commits and breaking changes", () => {
|
||||
expect(
|
||||
renderReleaseNotes([
|
||||
"feat(chat): add side chat support",
|
||||
"fix: prevent stale titles",
|
||||
"perf(stream): reduce rendering work",
|
||||
"refactor!: remove the legacy settings format",
|
||||
"docs: explain side chats",
|
||||
"chore(deps): update development dependencies",
|
||||
]),
|
||||
).toBe(
|
||||
[
|
||||
"## Changes",
|
||||
"",
|
||||
"- Add side chat support.",
|
||||
"- Prevent stale titles.",
|
||||
"- Reduce rendering work.",
|
||||
"- Remove the legacy settings format.",
|
||||
"",
|
||||
].join("\n"),
|
||||
);
|
||||
});
|
||||
|
||||
it("uses a breaking footer to include an otherwise hidden type", () => {
|
||||
expect(releaseNoteForCommit("refactor: replace settings storage\n\nBREAKING-CHANGE: existing settings are reset")).toBe(
|
||||
"Replace settings storage.",
|
||||
);
|
||||
});
|
||||
|
||||
it("leaves an editable placeholder when no commits belong in the notes", () => {
|
||||
expect(renderReleaseNotes(["test: cover release generation", "ci: validate commit messages"])).toBe("## Changes\n\n- \n");
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue