diff --git a/.github/workflows/feature-pr.yml b/.github/workflows/feature-pr.yml index 417b839..fcee49e 100644 --- a/.github/workflows/feature-pr.yml +++ b/.github/workflows/feature-pr.yml @@ -1,44 +1,35 @@ -# @Project: @cldmv/fix-headers -# @Filename: /.github/workflows/feature-pr.yml -# @Date: 2026-07-18 18:03:25 -07:00 (1784423005) -# @Author: Nate Corcoran -# @Email: -# ----- -# @Last modified by: Shinrai (Shinrai@users.noreply.github.com) -# @Last modified time: 2026-07-18 18:06:48 -07:00 (1784423208) -# ----- -# @Copyright: Copyright (c) 2026-2026 Catalyzed Motivation Inc. All rights reserved. +# +# @Project: @cldmv/.github +# @Filename: /examples/individual-repo-workflows/release-flow-v4/feature-pr.yml +# @Author: Nate Corcoran +# @Email: +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# # Individual repo: .github/workflows/feature-pr.yml # -# v4 ergonomics: auto-opens (and refreshes) a PR from a code-side branch to -# the right integration branch on every push. +# v4 ergonomics: auto-opens (and refreshes) a PR from a code-side branch to the +# right integration branch on every push. # # Mapping (matches CLDMV/.github docs/conventions/branch-naming.md): # feat/*, feature/*, fix/*, release/*, chore/*, refactor/*, # docs/*, ci/*, perf/*, test/*, style/* β†’ next # hotfix/* β†’ hotfixes # -# Reserved branches NOT auto-PR'd: dependabot/* and copilot/* (they manage -# their own PRs); badges, gh-pages (bot-only); master/main (the target). +# Reserved branches NOT auto-PR'd: dependabot/* and copilot/* (they manage their +# own PRs); badges, gh-pages (bot-only); master/main (the target). # -# On first push: creates the PR with a categorized changelog body (same -# format the v4 release-PR machinery generates). On subsequent pushes: -# refreshes the existing PR's body with the latest categorized commits. -# Uses the shared get-commit-range + generate-comprehensive-changelog -# actions for the format, so consumer PRs look identical to release PRs -# in structure (Breaking Changes / Features / Bug Fixes / Other Changes / -# Contributors). -# -# Skipped automatically: bot pushes (your bot App's login / github-actions[bot]) -# and any push whose head commit starts with 'chore: bump version'. +# Thin caller: all job logic (target detection, changelog body, PR create/ +# refresh) lives in the reusable, pinned at @v4. Bumping the pin carries fixes +# without editing this file. The `push` trigger and its branch-prefix list stay +# here (GitHub requires the trigger local, and the list is per-repo config). name: πŸ”€ Feature PR (v4) on: push: branches: # CUSTOMIZE: prune this list to whichever branch prefixes your - # repo uses. Must align with the `case` statement below. + # repo uses. Must align with the `case` statement in the reusable. - 'feat/**' - 'feature/**' - 'fix/**' @@ -52,215 +43,17 @@ on: - 'style/**' - 'hotfix/**' -permissions: - contents: read - pull-requests: write - -# Serialize per-branch so a flurry of pushes doesn't race the -# "does a PR already exist?" check. concurrency: group: feature-pr-${{ github.repository }}-${{ github.ref }} cancel-in-progress: false jobs: open-pr: - # Loop guard: replace 'cldmv-bot[bot]' with your bot App's login. - if: | - github.actor != 'cldmv-bot[bot]' && - github.actor != 'github-actions[bot]' && - !startsWith(github.event.head_commit.message, 'chore: bump version') - runs-on: ubuntu-latest - steps: - - name: Determine target branch - id: target - shell: bash - run: | - branch="${GITHUB_REF#refs/heads/}" - echo "branch=$branch" >> "$GITHUB_OUTPUT" - # CUSTOMIZE: adjust the case arms to match your branch - # conventions. Anything not matched is silently skipped - # (so master/main, badges, gh-pages, dependabot/*, etc. - # are safe regardless of what fires the workflow). - # The flow_label sorts first in the PR's label list - # (the leading `!` precedes every letter alphabetically) - # so a glance at any PR's badges reveals which lane it's in. - # Lane (target) AND declared type both come from the branch - # prefix β€” the v4 convention requires a typed prefix, so a - # `docs/*` branch is a docs change, `fix/*` a fix, etc. The flow - # label is `! β†’ ` so it reflects what the PR actually - # is, not a blanket "feature". (Previously every next-lane branch - # got `! feature β†’ next`, mislabelling docs/fix/chore PRs.) - case "$branch" in - hotfix/*) target="hotfixes"; type="hotfix" ;; - feat/*|feature/*) target="next"; type="feature" ;; - fix/*) target="next"; type="fix" ;; - docs/*) target="next"; type="docs" ;; - chore/*) target="next"; type="chore" ;; - refactor/*) target="next"; type="refactor" ;; - ci/*) target="next"; type="ci" ;; - perf/*) target="next"; type="perf" ;; - test/*) target="next"; type="test" ;; - style/*) target="next"; type="style" ;; - release/*) target="next"; type="release" ;; - *) - target=""; type=""; flow_label="" - echo "::notice::Branch '$branch' does not match any auto-PR pattern; skipping." - ;; - esac - # Leading `!` sorts the flow label first in the PR's badge list, - # so a glance reveals both the change type and its lane. - if [ -n "$target" ]; then - flow_label="! ${type} β†’ ${target}" - fi - echo "target=$target" >> "$GITHUB_OUTPUT" - echo "flow_label=$flow_label" >> "$GITHUB_OUTPUT" - - - name: Create App token - id: app-token - if: steps.target.outputs.target != '' - uses: CLDMV/.github/.github/actions/github/steps/create-app-token@v4 - with: - client_id: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - private_key: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - env: - BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - - - name: Check for existing PR - id: existing - if: steps.target.outputs.target != '' - shell: bash - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - run: | - pr=$(gh pr list --repo "$GITHUB_REPOSITORY" \ - --head "${{ steps.target.outputs.branch }}" \ - --base "${{ steps.target.outputs.target }}" \ - --state open \ - --json number --jq '.[0].number // ""') - echo "number=$pr" >> "$GITHUB_OUTPUT" - if [ -n "$pr" ]; then - echo "::notice::Existing PR #$pr will be refreshed." - fi - - - name: Checkout (full history for git log) - if: steps.target.outputs.target != '' - uses: CLDMV/.github/.github/actions/common/steps/checkout-code@v4 - with: - fetch-depth: 0 - - - name: Fetch target branch ref - if: steps.target.outputs.target != '' - shell: bash - run: | - git fetch --quiet origin "${{ steps.target.outputs.target }}" - - - name: Get categorized commits (base..head) - id: commits - if: steps.target.outputs.target != '' - uses: CLDMV/.github/.github/actions/git/steps/get-commit-range@v4 - with: - base-ref: origin/${{ steps.target.outputs.target }} - head-ref: HEAD - - - name: Detect feature commits in range - id: feat - if: steps.target.outputs.target != '' - shell: bash - env: - COMMITS: ${{ steps.commits.outputs.commits }} - run: | - # `type: feature` is applied when the range contains a feature, - # mirroring the changelog's own "Features" section: get-commit- - # range tags `feat:` (and content-categorized add/new) commits - # as category "feature". Reuses the already-computed commits. - has_feature=false - if printf '%s' "$COMMITS" | jq -e 'any(.[]; .category == "feature")' >/dev/null 2>&1; then - has_feature=true - fi - echo "has_feature=$has_feature" >> "$GITHUB_OUTPUT" - echo "πŸ“Š feature detected in range: $has_feature" - - - name: Generate categorized changelog body - id: changelog - if: steps.target.outputs.target != '' - uses: CLDMV/.github/.github/actions/git/steps/generate-comprehensive-changelog@v4 - with: - commits: ${{ steps.commits.outputs.commits }} - commit-range: ${{ steps.commits.outputs.commit-range }} - env: - GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} - - - name: Save body to file - if: steps.target.outputs.target != '' - shell: bash - env: - BODY: ${{ steps.changelog.outputs.changelog-content }} - run: | - printf '%s' "$BODY" > /tmp/pr-body.md - - - name: Create PR (first push) - if: steps.target.outputs.target != '' && steps.existing.outputs.number == '' - shell: bash - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - HEAD_COMMIT_MSG: ${{ github.event.head_commit.message }} - HEAD_BRANCH: ${{ steps.target.outputs.branch }} - BASE_BRANCH: ${{ steps.target.outputs.target }} - run: | - # Title = head commit's first line β€” preserves the - # conventional-commit prefix the release-PR title-normalizer - # and commit-type aggregator expect. - title=$(printf '%s\n' "$HEAD_COMMIT_MSG" | head -1) - pr_url=$(gh pr create \ - --repo "$GITHUB_REPOSITORY" \ - --base "$BASE_BRANCH" \ - --head "$HEAD_BRANCH" \ - --title "$title" \ - --body-file /tmp/pr-body.md) - echo "::notice::Opened $pr_url" - # Apply the flow label (sorts first in the PR's badge list). - # `|| true` so a missing label in the repo (catalog not yet - # synced) doesn't fail the workflow. - if [ -n "${{ steps.target.outputs.flow_label }}" ]; then - gh pr edit "$pr_url" --add-label "${{ steps.target.outputs.flow_label }}" || true - fi - # Apply `type: feature` when the range implements a feature. - if [ "${{ steps.feat.outputs.has_feature }}" = "true" ]; then - gh pr edit "$pr_url" --add-label "type: feature" || true - fi - { - echo "### πŸ”€ Auto-opened PR" - echo "" - echo "$pr_url" - } >> "$GITHUB_STEP_SUMMARY" - - - name: Refresh existing PR body - if: steps.target.outputs.target != '' && steps.existing.outputs.number != '' - shell: bash - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - PR_NUMBER: ${{ steps.existing.outputs.number }} - run: | - gh pr edit "$PR_NUMBER" \ - --repo "$GITHUB_REPOSITORY" \ - --body-file /tmp/pr-body.md - # Re-apply the flow label so a manual removal doesn't - # strand the PR without its lane indicator. - if [ -n "${{ steps.target.outputs.flow_label }}" ]; then - gh pr edit "$PR_NUMBER" \ - --repo "$GITHUB_REPOSITORY" \ - --add-label "${{ steps.target.outputs.flow_label }}" || true - fi - # Apply `type: feature` when the range implements a feature. - if [ "${{ steps.feat.outputs.has_feature }}" = "true" ]; then - gh pr edit "$PR_NUMBER" \ - --repo "$GITHUB_REPOSITORY" \ - --add-label "type: feature" || true - fi - echo "::notice::Refreshed PR #${PR_NUMBER} body" - { - echo "### πŸ”€ Refreshed PR body" - echo "" - echo "PR #${PR_NUMBER}" - } >> "$GITHUB_STEP_SUMMARY" + permissions: + contents: read + pull-requests: write + uses: CLDMV/.github/.github/workflows/workflow-feature-pr.yml@v4 + secrets: + # Map your repo/org secrets to the expected names. + BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} + BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} diff --git a/.github/workflows/hotfix-redirector.yml b/.github/workflows/hotfix-redirector.yml index 1584650..830cad6 100644 --- a/.github/workflows/hotfix-redirector.yml +++ b/.github/workflows/hotfix-redirector.yml @@ -1,13 +1,11 @@ -# @Project: @cldmv/fix-headers -# @Filename: /.github/workflows/hotfix-redirector.yml -# @Date: 2026-05-22 00:00:00 -07:00 (1779778800) -# @Author: Nate Corcoran -# @Email: -# ----- -# @Last modified by: Shinrai (Shinrai@users.noreply.github.com) -# @Last modified time: 2026-07-18 18:06:48 -07:00 (1784423208) -# ----- -# @Copyright: Copyright (c) 2026-2026 Catalyzed Motivation Inc. All rights reserved. +# +# @Project: @cldmv/.github +# @Filename: /examples/individual-repo-workflows/release-flow-v4/hotfix-redirector.yml +# @Date: 2026-05-22 00:00:00 -07:00 (1779778800) +# @Author: Nate Corcoran +# @Email: +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# # Individual repo: .github/workflows/hotfix-redirector.yml # @@ -15,55 +13,39 @@ # # Two paths trigger a redirect (CLDMV/.github docs/conventions/release-flow-v4.md Β§5.2, Β§6.5): # 1. Head branch matches `hotfix/*` or `security/*` (human-driven hotfix flow). -# 2. Author is `dependabot[bot]` AND the PR body references a GHSA security -# advisory (Dependabot's security-update PRs flow into the hotfix lane; -# routine version bumps stay on `next`). +# 2. Author is `dependabot[bot]` AND its base isn't Dependabot's routine +# target-branch (default "next") β€” GitHub always overrides dependabot.yml's +# target-branch for security updates, so a base landing on the default +# branch instead of "next" is itself the signal. Routine version bumps stay +# on "next". # -# The redirect-hotfix-pr action owns all detection logic β€” it skips non-matching -# bot PRs, non-matching heads, and PRs already on `hotfixes`, and posts a -# one-time explanatory comment with the appropriate reason. +# Thin caller: all job logic (token, checkout, git identity, redirect action) +# lives in the reusable, pinned at @v4. Bumping the pin carries new requirements +# (e.g. the checkout + git identity the cherry-pick path needs) without editing +# this file. name: πŸ”€ Hotfix PR Redirector (v4) -# SECURITY NOTE: pull_request_target runs in the BASE repo's context with -# WRITE permissions + secrets. SAFE here because it is API-only β€” the -# redirect-hotfix-pr action never checks out or executes PR content. -# DO NOT add a checkout step. +# SECURITY NOTE: pull_request_target runs in the BASE repo's context with WRITE +# permissions + secrets. The reusable checks out `hotfixes` (a trusted base-repo +# branch, NOT the PR head/fork) and only cherry-picks/pushes against it. # -# `opened` only (NOT `edited`): if a maintainer manually re-targets the PR, -# we must not fight them by redirecting again. +# `opened` only (NOT `edited`): if a maintainer manually re-targets the PR, we +# must not fight them by redirecting again. on: pull_request_target: types: [opened] -permissions: - contents: read - pull-requests: write - concurrency: group: hotfix-redirector-${{ github.event.pull_request.number }} cancel-in-progress: true jobs: redirect: - name: "πŸ”€ Redirect to hotfixes" - runs-on: ubuntu-latest - steps: - - name: Create App token - id: app-token - uses: CLDMV/.github/.github/actions/github/steps/create-app-token@v4 - with: - client_id: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - private_key: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - env: - BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - - - name: Redirect hotfix/security PR to hotfixes - uses: CLDMV/.github/.github/actions/github/steps/redirect-hotfix-pr@v4 - with: - pr-number: ${{ github.event.pull_request.number }} - github-token: ${{ steps.app-token.outputs.token }} - head-ref: ${{ github.event.pull_request.head.ref }} - base-ref: ${{ github.event.pull_request.base.ref }} - user-type: ${{ github.event.pull_request.user.type }} - target-base: hotfixes + permissions: + contents: write + pull-requests: write + uses: CLDMV/.github/.github/workflows/workflow-hotfix-redirector.yml@v4 + secrets: + # Map your repo/org secrets to the expected names. + BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} + BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} diff --git a/.github/workflows/hotfixes-release.yml b/.github/workflows/hotfixes-release.yml index ac3ef17..bcf19a8 100644 --- a/.github/workflows/hotfixes-release.yml +++ b/.github/workflows/hotfixes-release.yml @@ -1,26 +1,25 @@ -# @Project: @cldmv/fix-headers -# @Filename: /.github/workflows/hotfixes-release.yml -# @Date: 2026-05-22 00:00:00 -07:00 (1779778800) -# @Author: Nate Corcoran -# @Email: -# ----- -# @Last modified by: Shinrai (Shinrai@users.noreply.github.com) -# @Last modified time: 2026-07-18 18:06:48 -07:00 (1784423208) -# ----- -# @Copyright: Copyright (c) 2026-2026 Catalyzed Motivation Inc. All rights reserved. +# +# @Project: @cldmv/.github +# @Filename: /examples/individual-repo-workflows/release-flow-v4/hotfixes-release.yml +# @Date: 2026-05-22 00:00:00 -07:00 (1779778800) +# @Author: Nate Corcoran +# @Email: +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# # Individual repo: .github/workflows/hotfixes-release.yml # # v4 hotfix lane: maintain the ONE persistent `hotfixes β†’ master` release PR. # # Mirror of next-release.yml but for the `hotfixes` integration branch -# (CLDMV/.github docs/conventions/release-flow-v4.md Β§5.4, Β§6.2). Fires on -# every push to `hotfixes` (hotfix/security PR squash-merges land here), and -# resolves-or-creates the persistent `hotfixes β†’ master` release PR. Patches -# the current release independently of whatever is pending on `next`. +# (CLDMV/.github docs/conventions/release-flow-v4.md Β§5.4, Β§6.2). Fires on every +# push to `hotfixes` (hotfix/security PR squash-merges land here), and +# resolves-or-creates the persistent `hotfixes β†’ master` release PR. # -# Same model as the next lane: the version bump rides on `hotfixes` as a -# `chore: bump version` commit, carried to master through the squash (Β§8.1). +# Thin caller: all job logic (plan / create / refresh) lives in the reusable, +# pinned at @v4. Bumping the pin carries fixes without editing this file. +# CUSTOMIZE `package_name` / `build_command` to match your package (same values +# as your next-release.yml). name: πŸš‘ Hotfixes Release (v4) on: @@ -28,144 +27,29 @@ on: branches: [hotfixes] workflow_dispatch: # manual kick β€” e.g. to open/refresh the PR for content already on `hotfixes` -permissions: - contents: write - pull-requests: write - concurrency: group: hotfixes-release-${{ github.repository }} cancel-in-progress: false jobs: - plan: - # Loop guard: skip only the release machinery's own `chore: bump version` - # push (create/update-release-pr writes it back to `hotfixes`). Do NOT gate - # on github.actor β€” dependabot security PRs are auto-merged into `hotfixes` - # BY the bot, so gating the bot out meant the hotfixesβ†’master release PR - # was never created (every push here is a bot merge). Reset force-pushes are - # harmless: the detect step below no-ops when in sync with master. - # workflow_dispatch bypasses the guard (event_name != 'push'). - if: | - github.event_name != 'push' || - !startsWith(github.event.head_commit.message, 'chore: bump version') - name: "πŸ” Plan (detect changes + resolve PR)" - runs-on: ubuntu-latest - outputs: - has-changes: ${{ steps.detect.outputs.has-changes }} - pr-number: ${{ steps.resolve.outputs.pr-number }} - steps: - - name: Create App token - id: app-token - uses: CLDMV/.github/.github/actions/github/steps/create-app-token@v4 - with: - client_id: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - private_key: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - env: - BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - - - name: Checkout hotfixes - uses: CLDMV/.github/.github/actions/common/steps/checkout-code@v4 - with: - ref: hotfixes - fetch-depth: 0 - - - name: Detect master..hotfixes changes - id: detect - shell: bash - run: | - git fetch origin master --quiet - count=$(git rev-list --count origin/master..HEAD) - echo "πŸ“Š commits on hotfixes not yet on master: $count" - if [ "$count" -gt 0 ]; then - echo "has-changes=true" >> "$GITHUB_OUTPUT" - else - echo "has-changes=false" >> "$GITHUB_OUTPUT" - echo "ℹ️ hotfixes is in sync with master β€” nothing to release." - fi - - - name: Resolve persistent hotfixesβ†’master PR - id: resolve - if: steps.detect.outputs.has-changes == 'true' - shell: bash - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - run: | - pr=$(gh pr list --repo "$GITHUB_REPOSITORY" --head hotfixes --base master \ - --state open --json number --jq '.[0].number // ""') - echo "pr-number=$pr" >> "$GITHUB_OUTPUT" - if [ -n "$pr" ]; then - echo "πŸ” existing hotfix release PR: #$pr β€” will refresh" - else - echo "πŸ†• no hotfix release PR yet β€” will create" - fi - - create: - name: "πŸ†• Create hotfix release PR" - needs: plan - if: needs.plan.outputs.has-changes == 'true' && needs.plan.outputs.pr-number == '' - runs-on: ubuntu-latest - steps: - - name: Create App token - id: app-token - uses: CLDMV/.github/.github/actions/github/steps/create-app-token@v4 - with: - client_id: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - private_key: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - env: - BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - - # Customize `package-name` + `build-command` to match this repo β€” - # see notes in next-release.yml. - - name: Create release PR - uses: CLDMV/.github/.github/actions/github/jobs/create-release-pr@v4 - with: - package-name: "@cldmv/fix-headers" - build-command: "npm run build:ci" - github-token: ${{ steps.app-token.outputs.token }} - - refresh: - name: "πŸ” Refresh hotfix release PR #${{ needs.plan.outputs.pr-number }}" - needs: plan - if: needs.plan.outputs.has-changes == 'true' && needs.plan.outputs.pr-number != '' - runs-on: ubuntu-latest - steps: - - name: Create App token - id: app-token - uses: CLDMV/.github/.github/actions/github/steps/create-app-token@v4 - with: - client_id: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - private_key: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - env: - BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - - - name: Refresh release PR - id: refresh - uses: CLDMV/.github/.github/actions/github/jobs/update-release-pr@v4 - with: - head-ref: hotfixes - pr-number: ${{ needs.plan.outputs.pr-number }} - package-name: "@cldmv/fix-headers" - build-command: "npm run build:ci" - github-token: ${{ steps.app-token.outputs.token }} - - # Optional: release-PR notifier. See next-release.yml for the - # rationale. Delete the step to opt out entirely; leave a webhook - # secret unset to opt out of that one channel. - - name: Notify on release-PR version bump - if: steps.refresh.outputs.version-changed == 'true' - uses: CLDMV/.github/.github/actions/community/jobs/release-notifier@v4 - with: - event_kind: release_pr - pr_number: ${{ needs.plan.outputs.pr-number }} - version: ${{ steps.refresh.outputs.new-version }} - github_token: ${{ steps.app-token.outputs.token }} - env: - DISCORD_RELEASE_PR_PUBLIC_WEBHOOK: ${{ secrets.DISCORD_RELEASE_PR_PUBLIC_WEBHOOK }} - DISCORD_RELEASE_PR_PRIVATE_WEBHOOK: ${{ secrets.DISCORD_RELEASE_PR_PRIVATE_WEBHOOK }} - SLACK_RELEASE_PR_PUBLIC_WEBHOOK: ${{ secrets.SLACK_RELEASE_PR_PUBLIC_WEBHOOK }} - SLACK_RELEASE_PR_PRIVATE_WEBHOOK: ${{ secrets.SLACK_RELEASE_PR_PRIVATE_WEBHOOK }} - GENERIC_RELEASE_PR_PUBLIC_WEBHOOK: ${{ secrets.GENERIC_RELEASE_PR_PUBLIC_WEBHOOK }} - GENERIC_RELEASE_PR_PRIVATE_WEBHOOK: ${{ secrets.GENERIC_RELEASE_PR_PRIVATE_WEBHOOK }} + release: + permissions: + contents: write + pull-requests: write + uses: CLDMV/.github/.github/workflows/workflow-hotfixes-release.yml@v4 + with: + package_name: "@cldmv/fix-headers" + build_command: "npm run build:ci" + secrets: + # Map your repo/org secrets to the expected names. + BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} + BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} + # Optional release-PR notifier webhooks β€” each is independently + # opt-in: leave one unset and that channel is silently skipped. + # Delete the lines you don't use. + DISCORD_RELEASE_PR_PUBLIC_WEBHOOK: ${{ secrets.DISCORD_RELEASE_PR_PUBLIC_WEBHOOK }} + DISCORD_RELEASE_PR_PRIVATE_WEBHOOK: ${{ secrets.DISCORD_RELEASE_PR_PRIVATE_WEBHOOK }} + SLACK_RELEASE_PR_PUBLIC_WEBHOOK: ${{ secrets.SLACK_RELEASE_PR_PUBLIC_WEBHOOK }} + SLACK_RELEASE_PR_PRIVATE_WEBHOOK: ${{ secrets.SLACK_RELEASE_PR_PRIVATE_WEBHOOK }} + GENERIC_RELEASE_PR_PUBLIC_WEBHOOK: ${{ secrets.GENERIC_RELEASE_PR_PUBLIC_WEBHOOK }} + GENERIC_RELEASE_PR_PRIVATE_WEBHOOK: ${{ secrets.GENERIC_RELEASE_PR_PRIVATE_WEBHOOK }} diff --git a/.github/workflows/next-release.yml b/.github/workflows/next-release.yml index 6204245..ee64351 100644 --- a/.github/workflows/next-release.yml +++ b/.github/workflows/next-release.yml @@ -1,13 +1,11 @@ -# @Project: @cldmv/fix-headers -# @Filename: /.github/workflows/next-release.yml -# @Date: 2026-05-22 00:00:00 -07:00 (1779778800) -# @Author: Nate Corcoran -# @Email: -# ----- -# @Last modified by: Shinrai (Shinrai@users.noreply.github.com) -# @Last modified time: 2026-07-18 18:06:49 -07:00 (1784423209) -# ----- -# @Copyright: Copyright (c) 2026-2026 Catalyzed Motivation Inc. All rights reserved. +# +# @Project: @cldmv/.github +# @Filename: /examples/individual-repo-workflows/release-flow-v4/next-release.yml +# @Date: 2026-05-22 00:00:00 -07:00 (1779778800) +# @Author: Nate Corcoran +# @Email: +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# # Individual repo: .github/workflows/next-release.yml # @@ -19,10 +17,13 @@ # feature commits into a single release β€” that batching is v4's whole point # (see CLDMV/.github docs/conventions/release-flow-v4.md Β§5.3, Β§6.1). # -# The version bump rides on `next` as a `chore: bump version` commit pushed -# by the release-PR machinery; it's carried to master through the squash -# (Β§8.1 β€” master accepts changes only via PR squash, and the publish flow -# reads package.json as-is). +# Thin caller: all job logic (plan / create / refresh) lives in the reusable, +# pinned at @v4. Bumping the pin carries fixes without editing this file. +# CUSTOMIZE: +# - `package_name` β†’ your npm package (or any unique identifier) +# - `build_command` β†’ your build script, or a stub like +# `echo 'βœ“ no build step'` for a meta package (optional; +# defaults to `npm run build:ci`) name: πŸš€ Next Release (v4) on: @@ -30,10 +31,6 @@ on: branches: [next] workflow_dispatch: # manual kick β€” e.g. to open/refresh the PR for content already on `next` -permissions: - contents: write - pull-requests: write - # Serialize: each run re-resolves the current PR state, so queueing (not # cancelling) avoids a create/refresh race when pushes land back-to-back. concurrency: @@ -41,143 +38,24 @@ concurrency: cancel-in-progress: false jobs: - plan: - # Loop guard: skip only the release machinery's own `chore: bump version` - # push (create/update-release-pr writes it back to `next`). Do NOT gate on - # github.actor β€” dependabot security PRs are auto-merged BY the bot, and - # excluding the bot actor meant bot-merged PRs never refreshed the release - # PR (fatal on `hotfixes`, where every merge is a bot auto-merge). Reset - # force-pushes are harmless: the detect step below no-ops when in sync with - # master. workflow_dispatch bypasses the guard (event_name != 'push'). - if: | - github.event_name != 'push' || - !startsWith(github.event.head_commit.message, 'chore: bump version') - name: "πŸ” Plan (detect changes + resolve PR)" - runs-on: ubuntu-latest - outputs: - has-changes: ${{ steps.detect.outputs.has-changes }} - pr-number: ${{ steps.resolve.outputs.pr-number }} - steps: - - name: Create App token - id: app-token - uses: CLDMV/.github/.github/actions/github/steps/create-app-token@v4 - with: - client_id: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - private_key: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - env: - BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - - - name: Checkout next - uses: CLDMV/.github/.github/actions/common/steps/checkout-code@v4 - with: - ref: next - fetch-depth: 0 - - - name: Detect master..next changes - id: detect - shell: bash - run: | - git fetch origin master --quiet - count=$(git rev-list --count origin/master..HEAD) - echo "πŸ“Š commits on next not yet on master: $count" - if [ "$count" -gt 0 ]; then - echo "has-changes=true" >> "$GITHUB_OUTPUT" - else - echo "has-changes=false" >> "$GITHUB_OUTPUT" - echo "ℹ️ next is in sync with master β€” nothing to release." - fi - - - name: Resolve persistent nextβ†’master PR - id: resolve - if: steps.detect.outputs.has-changes == 'true' - shell: bash - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - run: | - # The persistent release PR is the open PR with head=next, - # base=master. There is at most one (concurrency-serialized). - pr=$(gh pr list --repo "$GITHUB_REPOSITORY" --head next --base master \ - --state open --json number --jq '.[0].number // ""') - echo "pr-number=$pr" >> "$GITHUB_OUTPUT" - if [ -n "$pr" ]; then - echo "πŸ” existing release PR: #$pr β€” will refresh" - else - echo "πŸ†• no release PR yet β€” will create" - fi - - create: - name: "πŸ†• Create release PR" - needs: plan - if: needs.plan.outputs.has-changes == 'true' && needs.plan.outputs.pr-number == '' - runs-on: ubuntu-latest - steps: - - name: Create App token - id: app-token - uses: CLDMV/.github/.github/actions/github/steps/create-app-token@v4 - with: - client_id: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - private_key: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - env: - BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - - # Runs on the `next` ref β†’ create-release-pr opens next β†’ master and - # pushes the chore-bump commit to next. Customize: - # - `package-name` β†’ your npm package (or any unique identifier) - # - `build-command` β†’ your build script, or a stub like - # `echo 'βœ“ no build step'` for a meta package - - name: Create release PR - uses: CLDMV/.github/.github/actions/github/jobs/create-release-pr@v4 - with: - package-name: "@cldmv/fix-headers" - build-command: "npm run build:ci" - github-token: ${{ steps.app-token.outputs.token }} - - refresh: - name: "πŸ” Refresh release PR #${{ needs.plan.outputs.pr-number }}" - needs: plan - if: needs.plan.outputs.has-changes == 'true' && needs.plan.outputs.pr-number != '' - runs-on: ubuntu-latest - steps: - - name: Create App token - id: app-token - uses: CLDMV/.github/.github/actions/github/steps/create-app-token@v4 - with: - client_id: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - private_key: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - env: - BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - - - name: Refresh release PR - id: refresh - uses: CLDMV/.github/.github/actions/github/jobs/update-release-pr@v4 - with: - head-ref: next - pr-number: ${{ needs.plan.outputs.pr-number }} - package-name: "@cldmv/fix-headers" - build-command: "npm run build:ci" - github-token: ${{ steps.app-token.outputs.token }} - - # Optional: release-PR notifier. Fires only when the target - # version actually changes (PR open or version-bump shift), not - # on the changelog-only refreshes that run on every push. Each - # secret is independently opt-in: leave a webhook unset and that - # channel is silently skipped. Delete this step to opt out - # entirely. - - name: Notify on release-PR version bump - if: steps.refresh.outputs.version-changed == 'true' - uses: CLDMV/.github/.github/actions/community/jobs/release-notifier@v4 - with: - event_kind: release_pr - pr_number: ${{ needs.plan.outputs.pr-number }} - version: ${{ steps.refresh.outputs.new-version }} - github_token: ${{ steps.app-token.outputs.token }} - env: - DISCORD_RELEASE_PR_PUBLIC_WEBHOOK: ${{ secrets.DISCORD_RELEASE_PR_PUBLIC_WEBHOOK }} - DISCORD_RELEASE_PR_PRIVATE_WEBHOOK: ${{ secrets.DISCORD_RELEASE_PR_PRIVATE_WEBHOOK }} - SLACK_RELEASE_PR_PUBLIC_WEBHOOK: ${{ secrets.SLACK_RELEASE_PR_PUBLIC_WEBHOOK }} - SLACK_RELEASE_PR_PRIVATE_WEBHOOK: ${{ secrets.SLACK_RELEASE_PR_PRIVATE_WEBHOOK }} - GENERIC_RELEASE_PR_PUBLIC_WEBHOOK: ${{ secrets.GENERIC_RELEASE_PR_PUBLIC_WEBHOOK }} - GENERIC_RELEASE_PR_PRIVATE_WEBHOOK: ${{ secrets.GENERIC_RELEASE_PR_PRIVATE_WEBHOOK }} + release: + permissions: + contents: write + pull-requests: write + uses: CLDMV/.github/.github/workflows/workflow-next-release.yml@v4 + with: + package_name: "@cldmv/fix-headers" + build_command: "npm run build:ci" + secrets: + # Map your repo/org secrets to the expected names. + BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} + BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} + # Optional release-PR notifier webhooks β€” each is independently + # opt-in: leave one unset and that channel is silently skipped. + # Delete the lines you don't use. + DISCORD_RELEASE_PR_PUBLIC_WEBHOOK: ${{ secrets.DISCORD_RELEASE_PR_PUBLIC_WEBHOOK }} + DISCORD_RELEASE_PR_PRIVATE_WEBHOOK: ${{ secrets.DISCORD_RELEASE_PR_PRIVATE_WEBHOOK }} + SLACK_RELEASE_PR_PUBLIC_WEBHOOK: ${{ secrets.SLACK_RELEASE_PR_PUBLIC_WEBHOOK }} + SLACK_RELEASE_PR_PRIVATE_WEBHOOK: ${{ secrets.SLACK_RELEASE_PR_PRIVATE_WEBHOOK }} + GENERIC_RELEASE_PR_PUBLIC_WEBHOOK: ${{ secrets.GENERIC_RELEASE_PR_PUBLIC_WEBHOOK }} + GENERIC_RELEASE_PR_PRIVATE_WEBHOOK: ${{ secrets.GENERIC_RELEASE_PR_PRIVATE_WEBHOOK }} diff --git a/.github/workflows/next-reset.yml b/.github/workflows/next-reset.yml index 16505c7..87ba088 100644 --- a/.github/workflows/next-reset.yml +++ b/.github/workflows/next-reset.yml @@ -1,13 +1,11 @@ -# @Project: @cldmv/fix-headers -# @Filename: /.github/workflows/next-reset.yml -# @Date: 2026-05-22 00:00:00 -07:00 (1779778800) -# @Author: Nate Corcoran -# @Email: -# ----- -# @Last modified by: Shinrai (Shinrai@users.noreply.github.com) -# @Last modified time: 2026-07-18 18:06:49 -07:00 (1784423209) -# ----- -# @Copyright: Copyright (c) 2026-2026 Catalyzed Motivation Inc. All rights reserved. +# +# @Project: @cldmv/.github +# @Filename: /examples/individual-repo-workflows/release-flow-v4/next-reset.yml +# @Date: 2026-05-22 00:00:00 -07:00 (1779778800) +# @Author: Nate Corcoran +# @Email: +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# # Individual repo: .github/workflows/next-reset.yml # @@ -18,184 +16,28 @@ # - `next` depends on which lane released: # * normal release (next β†’ master, or a v3-style feat β†’ master): # force-reset `next` to master HEAD (Β§7.1). -# * hotfix release (hotfixes β†’ master): MERGE master into `next` -# instead, so next's accumulated feature work is preserved (Β§7.2, -# option B). The merge is a no-op (204) when next has no extra work. -# -# The released lane is detected from the PR head ref behind the squash -# commit's trailing "(#N)". -# -# wait-for-tags gate: a release also fires update-major-version-tags, which -# rolls the major tags. Jobs resolve `uses: ...@vN` at job start, so without -# this gate the sync job can run the PREVIOUS release's action code. The gate -# polls the RELEASED major's tag β€” parsed from the `release: vX.Y.Z` commit -# β€” until it matches the release commit. +# * hotfix release (hotfixes β†’ master): MERGE master into `next` instead, +# so next's accumulated feature work is preserved (Β§7.2, option B). # -# Self-healing: no-ops pre-cutover (neither integration branch exists), but -# post-cutover it RECREATES a branch that went missing β€” e.g. branch-retention -# deleting `next` as a merged PR head. force-reset-branch creates the ref -# when it's absent. +# Thin caller: all job logic (the wait-for-tags gate + the branch sync) lives in +# the reusable, pinned at @v4. Bumping the pin carries fixes without editing +# this file. name: ♻️ Next/Hotfixes Reset (v4) on: push: branches: [master, main] -permissions: - contents: write - concurrency: group: next-reset-${{ github.repository }} cancel-in-progress: false jobs: - wait-for-tags: - # Only fire on a release commit (the squash-merge of a release PR). - if: startsWith(github.event.head_commit.message, 'release:') - name: "⏳ Wait for the released major tag to roll forward" - runs-on: ubuntu-latest - timeout-minutes: 5 - steps: - - name: Poll the released major tag until it matches the release commit - shell: bash - env: - TARGET_SHA: ${{ github.sha }} - REPO: ${{ github.repository }} - COMMIT_MSG: ${{ github.event.head_commit.message }} - run: | - echo "πŸ” Release commit: $TARGET_SHA" - # Parse the released MAJOR from the `release: vX.Y.Z` subject - # and poll THAT tag (e.g. @v4 for v4.x). update-major-version- - # tags rolls @v to the release commit; a hardcoded @v3 - # would never match on a major bump (which creates @v4). - major=$(printf '%s' "$COMMIT_MSG" | grep -oiE 'release:[^0-9]*v?[0-9]+' | grep -oE '[0-9]+$' | head -1) - if [ -z "$major" ]; then - echo "⚠️ Could not parse a major version from the commit subject β€” skipping the gate." - exit 0 - fi - tag="v${major}" - echo "⏳ Gating on @${tag}…" - max_attempts=24 # 24 * 5s = 120s - for attempt in $(seq 1 $max_attempts); do - sha=$(git ls-remote "https://github.com/${REPO}.git" "refs/tags/${tag}^{}" 2>/dev/null | awk '{print $1}') - [ -z "$sha" ] && sha=$(git ls-remote "https://github.com/${REPO}.git" "refs/tags/${tag}" 2>/dev/null | awk '{print $1}') - echo "Attempt $attempt/$max_attempts: @${tag} β†’ ${sha:-}" - if [ "$sha" = "$TARGET_SHA" ]; then - echo "βœ… @${tag} matches the release commit β€” safe to proceed" - exit 0 - fi - [ "$attempt" -lt "$max_attempts" ] && sleep 5 - done - echo "⚠️ Timed out waiting for @${tag} β€” proceeding anyway." - - sync-branches: - name: "♻️ Sync next + hotfixes to master" - needs: wait-for-tags - if: startsWith(github.event.head_commit.message, 'release:') - runs-on: ubuntu-latest - steps: - - name: Create App token - id: app-token - uses: CLDMV/.github/.github/actions/github/steps/create-app-token@v4 - with: - client_id: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - private_key: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - # Pushing/merging master's tree (which includes - # .github/workflows/**) requires contents + workflows write. - permission_contents: "true" - permission_workflows: "true" - env: - BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - - - name: Checkout master - uses: CLDMV/.github/.github/actions/common/steps/checkout-code@v4 - with: - fetch-depth: 0 - - - name: Determine released lane - id: lane - shell: bash - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - COMMIT_MSG: ${{ github.event.head_commit.message }} - run: | - # The squash commit ends with "(#N)" β€” the merged PR number. - prnum=$(printf '%s' "$COMMIT_MSG" | grep -oE '#[0-9]+' | tail -1 | tr -d '#') - head="" - if [ -n "$prnum" ]; then - head=$(gh pr view "$prnum" --repo "$GITHUB_REPOSITORY" \ - --json headRefName --jq '.headRefName' 2>/dev/null || echo "") - fi - echo "released PR #${prnum:-?} head ref: ${head:-}" - if [ "$head" = "hotfixes" ]; then - echo "lane=hotfix" >> "$GITHUB_OUTPUT" - else - echo "lane=other" >> "$GITHUB_OUTPUT" - fi - - - name: Guard β€” is this repo on v4? (do next/hotfixes exist?) - id: guard - shell: bash - run: | - next_exists=false; hotfixes_exists=false - if git ls-remote --exit-code --heads origin next >/dev/null 2>&1; then - next_exists=true - git fetch origin next:refs/remotes/origin/next --quiet || true - fi - if git ls-remote --exit-code --heads origin hotfixes >/dev/null 2>&1; then - hotfixes_exists=true - git fetch origin hotfixes:refs/remotes/origin/hotfixes --quiet || true - fi - # "v4 adopted" = at least one integration branch exists. Keeps - # the reset a no-op on pre-cutover repos (neither exists) while - # letting it RECREATE a branch that went missing post-cutover - # (e.g. one was deleted as a merged PR head). force-reset-branch - # creates if absent. - v4_adopted=false - { [ "$next_exists" = true ] || [ "$hotfixes_exists" = true ]; } && v4_adopted=true - { - echo "next-exists=$next_exists" - echo "hotfixes-exists=$hotfixes_exists" - echo "v4-adopted=$v4_adopted" - } >> "$GITHUB_OUTPUT" - echo "ℹ️ next=$next_exists hotfixes=$hotfixes_exists v4-adopted=$v4_adopted lane=${{ steps.lane.outputs.lane }}" - - # hotfixes always tracks master after a release β€” created if missing. - - name: Ensure hotfixes = master HEAD (reset; create if missing) - if: steps.guard.outputs.v4-adopted == 'true' - uses: CLDMV/.github/.github/actions/git/steps/force-reset-branch@v4 - with: - target-branch: hotfixes - source-ref: master - github-token: ${{ steps.app-token.outputs.token }} - - # Normal release β†’ next is force-reset (its work just shipped), and - # recreated if it was deleted on merge. - - name: Ensure next = master HEAD (normal release; create if missing) - if: steps.guard.outputs.v4-adopted == 'true' && steps.lane.outputs.lane != 'hotfix' - uses: CLDMV/.github/.github/actions/git/steps/force-reset-branch@v4 - with: - target-branch: next - source-ref: master - github-token: ${{ steps.app-token.outputs.token }} - - # Hotfix release + next still exists β†’ merge master into next to - # preserve its accumulated feature work (Β§7.2 option B). - - name: Merge master into next (hotfix release; next exists) - if: steps.guard.outputs.v4-adopted == 'true' && steps.lane.outputs.lane == 'hotfix' && steps.guard.outputs.next-exists == 'true' - uses: CLDMV/.github/.github/actions/github/steps/merge-master-into-branch@v4 - with: - target-branch: next - source-ref: master - github-token: ${{ steps.app-token.outputs.token }} - - # Hotfix release but next is MISSING (deleted) β†’ recreate it at master - # HEAD; there's no accumulated work to preserve. - - name: Recreate next at master HEAD (hotfix release; next missing) - if: steps.guard.outputs.v4-adopted == 'true' && steps.lane.outputs.lane == 'hotfix' && steps.guard.outputs.next-exists == 'false' - uses: CLDMV/.github/.github/actions/git/steps/force-reset-branch@v4 - with: - target-branch: next - source-ref: master - github-token: ${{ steps.app-token.outputs.token }} + sync: + permissions: + contents: write + uses: CLDMV/.github/.github/workflows/workflow-next-reset.yml@v4 + secrets: + # Map your repo/org secrets to the expected names. + BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} + BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} diff --git a/.github/workflows/pr-title-normalizer.yml b/.github/workflows/pr-title-normalizer.yml index d37944f..adba973 100644 --- a/.github/workflows/pr-title-normalizer.yml +++ b/.github/workflows/pr-title-normalizer.yml @@ -1,66 +1,45 @@ -# @Project: @cldmv/fix-headers -# @Filename: /.github/workflows/pr-title-normalizer.yml -# @Date: 2026-05-22 00:00:00 -07:00 (1779778800) -# @Author: Nate Corcoran -# @Email: -# ----- -# @Last modified by: Shinrai (Shinrai@users.noreply.github.com) -# @Last modified time: 2026-07-18 18:06:49 -07:00 (1784423209) -# ----- -# @Copyright: Copyright (c) 2026-2026 Catalyzed Motivation Inc. All rights reserved. +# +# @Project: @cldmv/.github +# @Filename: /examples/individual-repo-workflows/release-flow-v4/pr-title-normalizer.yml +# @Date: 2026-05-22 00:00:00 -07:00 (1779778800) +# @Author: Nate Corcoran +# @Email: +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# # Individual repo: .github/workflows/pr-title-normalizer.yml # -# Normalize contributor PR titles to Conventional Commits format, derived -# from the highest-priority commit in the PR. The release flow expects this -# shape, so a v4 repo wants this enabled. (Also backportable to v3 repos β€” -# it wires the normalize-pr-title action, shipped in v3.3.0; the action owns -# all skip logic: bot authors, the long-running release PRs, titles already -# starting with `release:`, and titles that already conform.) +# Normalize contributor PR titles to Conventional Commits format, derived from +# the highest-priority commit in the PR. The release flow expects this shape, so +# a v4 repo wants this enabled. (Also backportable to v3 repos β€” the underlying +# action shipped in v3.3.0; it owns all skip logic: bot authors, the +# long-running release PRs, titles already starting with `release:`, and titles +# that already conform.) +# +# Thin caller: all job logic lives in the reusable, pinned at @v4. Bumping the +# pin carries fixes without editing this file. name: 🏷️ PR Title Normalizer -# SECURITY NOTE: pull_request_target runs in the BASE repo's context with -# WRITE permissions and access to secrets. SAFE for THIS workflow because it -# is API-only β€” the normalize-pr-title action never checks out the PR head -# and never executes PR content. DO NOT add a checkout step. -# -# Triggers on opened + synchronize only (NOT edited): a maintainer hand- -# editing the title must not kick off a re-normalize loop. +# SECURITY NOTE: pull_request_target runs in the BASE repo's context with WRITE +# permissions and access to secrets. SAFE β€” the reusable's path is API-only (it +# never checks out or executes PR content). Triggers on opened + synchronize +# only (NOT edited): a maintainer hand-editing the title must not kick off a +# re-normalize loop. on: pull_request_target: types: [opened, synchronize] -permissions: - contents: read - pull-requests: write - -# Collapse a burst of pushes to one normalize run per PR; the newest push -# carries the authoritative commit set, so cancelling an in-flight run is fine. concurrency: group: pr-title-normalizer-${{ github.event.pull_request.number }} cancel-in-progress: true jobs: normalize: - name: "✏️ Normalize title" - runs-on: ubuntu-latest - steps: - - name: Create App token (falls back to GITHUB_TOKEN) - id: app-token - uses: CLDMV/.github/.github/actions/github/steps/create-app-token@v4 - with: - client_id: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - private_key: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - env: - BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - - - name: Normalize PR title - uses: CLDMV/.github/.github/actions/github/steps/normalize-pr-title@v4 - with: - pr-number: ${{ github.event.pull_request.number }} - github-token: ${{ steps.app-token.outputs.token }} - base-ref: ${{ github.event.pull_request.base.ref }} - head-ref: ${{ github.event.pull_request.head.ref }} - user-type: ${{ github.event.pull_request.user.type }} - user-login: ${{ github.event.pull_request.user.login }} + permissions: + contents: read + pull-requests: write + uses: CLDMV/.github/.github/workflows/workflow-pr-title-normalizer.yml@v4 + secrets: + # Map your repo/org secrets to the expected names. + BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} + BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} diff --git a/package-lock.json b/package-lock.json index e4eec97..c34c71e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@cldmv/fix-headers", - "version": "1.3.6", + "version": "1.3.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@cldmv/fix-headers", - "version": "1.3.6", + "version": "1.3.7", "license": "Apache-2.0", "dependencies": { "ignore": "^7.0.5" @@ -15,13 +15,17 @@ "fix-headers": "src/cli.mjs" }, "devDependencies": { - "@types/node": "^25.3.0", + "@types/node": "^26.1.1", "@vitest/coverage-v8": "^4.1.8", - "typescript": "^5.9.3", + "typescript": "^7.0.2", "vitest": "^4.1.8" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.19.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/shinrai" }, "peerDependencies": { "vitest": ">=1.0.0" @@ -88,35 +92,38 @@ } }, "node_modules/@emnapi/core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", - "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "version": "2.0.0-alpha.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-2.0.0-alpha.3.tgz", + "integrity": "sha512-AZypUeJ/yByuxyS7BlSNRDOMLMlROYtjYdIAuBmJssVz1UJDSeYxLrdizhXCFYhedC5bqd/ASy8EuNXbVVXp9g==", "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { - "@emnapi/wasi-threads": "1.2.1", + "@emnapi/wasi-threads": "2.0.1", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "version": "2.0.0-alpha.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-2.0.0-alpha.3.tgz", + "integrity": "sha512-hFPAhMUjJD9BSyCANEISPOogeXC9Zo9ZQl7L6vKnaVsMkCtzznaW/naYypeyl0Gv5rYfWYsZbpixTMpjDJzQeA==", "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "tslib": "^2.4.0" } }, "node_modules/@emnapi/wasi-threads": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", - "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-2.0.1.tgz", + "integrity": "sha512-9DsSk+o5NBX0CCJT8s0EROGSGxjR/tKu6aBTaVyq+SjAEQH4XcdcRxPBRzsBLizTTJ49MJjF+jgu3qnO9GLQcQ==", "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "tslib": "^2.4.0" } @@ -150,28 +157,31 @@ } }, "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", - "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.0.tgz", + "integrity": "sha512-kDoONqMa+VnZ4vvvu/ZUurpJ4gkZU57e7g69qpNgWhYcZFPUHZM2CEMKm+cG6ufDVALbjMvfmMjFVqaK7uEMnA==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@tybys/wasm-util": "^0.10.1" + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" }, "funding": { "type": "github", "url": "https://github.com/sponsors/Brooooooklyn" }, "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" + "@emnapi/core": "^2.0.0-alpha.3", + "@emnapi/runtime": "^2.0.0-alpha.3" } }, "node_modules/@oxc-project/types": { - "version": "0.133.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz", - "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==", + "version": "0.139.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz", + "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==", "dev": true, "license": "MIT", "funding": { @@ -179,9 +189,9 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz", - "integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz", + "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==", "cpu": [ "arm64" ], @@ -196,9 +206,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.3.tgz", - "integrity": "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz", + "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==", "cpu": [ "arm64" ], @@ -213,9 +223,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz", - "integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz", + "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==", "cpu": [ "x64" ], @@ -230,9 +240,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz", - "integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz", + "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==", "cpu": [ "x64" ], @@ -247,9 +257,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz", - "integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz", + "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==", "cpu": [ "arm" ], @@ -264,9 +274,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz", - "integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz", + "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==", "cpu": [ "arm64" ], @@ -284,9 +294,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz", - "integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz", + "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==", "cpu": [ "arm64" ], @@ -304,9 +314,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz", - "integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz", + "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==", "cpu": [ "ppc64" ], @@ -324,9 +334,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz", - "integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz", + "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==", "cpu": [ "s390x" ], @@ -344,9 +354,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz", - "integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz", + "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==", "cpu": [ "x64" ], @@ -364,9 +374,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz", - "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz", + "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==", "cpu": [ "x64" ], @@ -384,9 +394,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz", - "integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz", + "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==", "cpu": [ "arm64" ], @@ -401,9 +411,9 @@ } }, "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz", - "integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz", + "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==", "cpu": [ "wasm32" ], @@ -411,18 +421,52 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "1.10.0", - "@emnapi/runtime": "1.10.0", - "@napi-rs/wasm-runtime": "^1.1.4" + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1", + "@napi-rs/wasm-runtime": "^1.1.6" }, "engines": { "node": "^20.19.0 || >=22.12.0" } }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz", - "integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz", + "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==", "cpu": [ "arm64" ], @@ -437,9 +481,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz", - "integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz", + "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==", "cpu": [ "x64" ], @@ -468,9 +512,9 @@ "license": "MIT" }, "node_modules/@tybys/wasm-util": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", - "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", "dev": true, "license": "MIT", "optional": true, @@ -504,24 +548,364 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.3.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.3.tgz", - "integrity": "sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==", + "version": "26.1.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz", + "integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~7.18.0" + "undici-types": "~8.3.0" + } + }, + "node_modules/@typescript/typescript-aix-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", + "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-darwin-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", + "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-darwin-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", + "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-freebsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", + "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-freebsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", + "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-arm": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", + "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", + "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-loong64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", + "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-mips64el": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", + "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", + "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-riscv64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", + "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-s390x": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", + "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", + "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-netbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", + "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-netbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", + "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-openbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", + "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-openbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", + "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-sunos-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", + "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-win32-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", + "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-win32-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", + "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" } }, "node_modules/@vitest/coverage-v8": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.8.tgz", - "integrity": "sha512-lt3kovsyHwYe00wq4D1ti0Z974fWj4NLp6siqiyEufUpyFwK9Yhi7rBhac9JL5aA0zoMrJqc4vYPZRUnI7l7nw==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.10.tgz", + "integrity": "sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^1.0.2", - "@vitest/utils": "4.1.8", + "@vitest/utils": "4.1.10", "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", @@ -535,8 +919,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "4.1.8", - "vitest": "4.1.8" + "@vitest/browser": "4.1.10", + "vitest": "4.1.10" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -545,16 +929,16 @@ } }, "node_modules/@vitest/expect": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.8.tgz", - "integrity": "sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", + "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.8", - "@vitest/utils": "4.1.8", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" }, @@ -563,13 +947,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.8.tgz", - "integrity": "sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz", + "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.1.8", + "@vitest/spy": "4.1.10", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -590,9 +974,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.8.tgz", - "integrity": "sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", + "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", "dev": true, "license": "MIT", "dependencies": { @@ -603,13 +987,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.8.tgz", - "integrity": "sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", + "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.1.8", + "@vitest/utils": "4.1.10", "pathe": "^2.0.3" }, "funding": { @@ -617,14 +1001,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.8.tgz", - "integrity": "sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", + "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.8", - "@vitest/utils": "4.1.8", + "@vitest/pretty-format": "4.1.10", + "@vitest/utils": "4.1.10", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -633,9 +1017,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.8.tgz", - "integrity": "sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", + "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", "dev": true, "license": "MIT", "funding": { @@ -643,13 +1027,13 @@ } }, "node_modules/@vitest/utils": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.8.tgz", - "integrity": "sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", + "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.8", + "@vitest/pretty-format": "4.1.10", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" }, @@ -784,9 +1168,9 @@ "license": "MIT" }, "node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", "license": "MIT", "engines": { "node": ">= 4" @@ -839,9 +1223,9 @@ "license": "MIT" }, "node_modules/lightningcss": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", "dev": true, "license": "MPL-2.0", "dependencies": { @@ -855,23 +1239,23 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-android-arm64": "1.32.0", - "lightningcss-darwin-arm64": "1.32.0", - "lightningcss-darwin-x64": "1.32.0", - "lightningcss-freebsd-x64": "1.32.0", - "lightningcss-linux-arm-gnueabihf": "1.32.0", - "lightningcss-linux-arm64-gnu": "1.32.0", - "lightningcss-linux-arm64-musl": "1.32.0", - "lightningcss-linux-x64-gnu": "1.32.0", - "lightningcss-linux-x64-musl": "1.32.0", - "lightningcss-win32-arm64-msvc": "1.32.0", - "lightningcss-win32-x64-msvc": "1.32.0" + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" } }, "node_modules/lightningcss-android-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", - "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", "cpu": [ "arm64" ], @@ -890,9 +1274,9 @@ } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", - "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", "cpu": [ "arm64" ], @@ -911,9 +1295,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", - "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", "cpu": [ "x64" ], @@ -932,9 +1316,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", - "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", "cpu": [ "x64" ], @@ -953,9 +1337,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", - "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", "cpu": [ "arm" ], @@ -974,9 +1358,9 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", - "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", "cpu": [ "arm64" ], @@ -998,9 +1382,9 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", - "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", "cpu": [ "arm64" ], @@ -1022,9 +1406,9 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", "cpu": [ "x64" ], @@ -1046,9 +1430,9 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", "cpu": [ "x64" ], @@ -1070,9 +1454,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", - "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", "cpu": [ "arm64" ], @@ -1091,9 +1475,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", - "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", "cpu": [ "x64" ], @@ -1150,9 +1534,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "version": "3.3.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", "dev": true, "funding": [ { @@ -1197,9 +1581,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, "license": "MIT", "engines": { @@ -1210,9 +1594,9 @@ } }, "node_modules/postcss": { - "version": "8.5.15", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", - "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "version": "8.5.25", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz", + "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==", "dev": true, "funding": [ { @@ -1230,7 +1614,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.12", + "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -1239,13 +1623,13 @@ } }, "node_modules/rolldown": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz", - "integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz", + "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.133.0", + "@oxc-project/types": "=0.139.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -1255,21 +1639,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.3", - "@rolldown/binding-darwin-arm64": "1.0.3", - "@rolldown/binding-darwin-x64": "1.0.3", - "@rolldown/binding-freebsd-x64": "1.0.3", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", - "@rolldown/binding-linux-arm64-gnu": "1.0.3", - "@rolldown/binding-linux-arm64-musl": "1.0.3", - "@rolldown/binding-linux-ppc64-gnu": "1.0.3", - "@rolldown/binding-linux-s390x-gnu": "1.0.3", - "@rolldown/binding-linux-x64-gnu": "1.0.3", - "@rolldown/binding-linux-x64-musl": "1.0.3", - "@rolldown/binding-openharmony-arm64": "1.0.3", - "@rolldown/binding-wasm32-wasi": "1.0.3", - "@rolldown/binding-win32-arm64-msvc": "1.0.3", - "@rolldown/binding-win32-x64-msvc": "1.0.3" + "@rolldown/binding-android-arm64": "1.1.5", + "@rolldown/binding-darwin-arm64": "1.1.5", + "@rolldown/binding-darwin-x64": "1.1.5", + "@rolldown/binding-freebsd-x64": "1.1.5", + "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", + "@rolldown/binding-linux-arm64-gnu": "1.1.5", + "@rolldown/binding-linux-arm64-musl": "1.1.5", + "@rolldown/binding-linux-ppc64-gnu": "1.1.5", + "@rolldown/binding-linux-s390x-gnu": "1.1.5", + "@rolldown/binding-linux-x64-gnu": "1.1.5", + "@rolldown/binding-linux-x64-musl": "1.1.5", + "@rolldown/binding-openharmony-arm64": "1.1.5", + "@rolldown/binding-wasm32-wasi": "1.1.5", + "@rolldown/binding-win32-arm64-msvc": "1.1.5", + "@rolldown/binding-win32-x64-msvc": "1.1.5" } }, "node_modules/semver": { @@ -1382,37 +1766,58 @@ "optional": true }, "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", + "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", "dev": true, "license": "Apache-2.0", "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "tsc": "bin/tsc" }, "engines": { - "node": ">=14.17" + "node": ">=16.20.0" + }, + "optionalDependencies": { + "@typescript/typescript-aix-ppc64": "7.0.2", + "@typescript/typescript-darwin-arm64": "7.0.2", + "@typescript/typescript-darwin-x64": "7.0.2", + "@typescript/typescript-freebsd-arm64": "7.0.2", + "@typescript/typescript-freebsd-x64": "7.0.2", + "@typescript/typescript-linux-arm": "7.0.2", + "@typescript/typescript-linux-arm64": "7.0.2", + "@typescript/typescript-linux-loong64": "7.0.2", + "@typescript/typescript-linux-mips64el": "7.0.2", + "@typescript/typescript-linux-ppc64": "7.0.2", + "@typescript/typescript-linux-riscv64": "7.0.2", + "@typescript/typescript-linux-s390x": "7.0.2", + "@typescript/typescript-linux-x64": "7.0.2", + "@typescript/typescript-netbsd-arm64": "7.0.2", + "@typescript/typescript-netbsd-x64": "7.0.2", + "@typescript/typescript-openbsd-arm64": "7.0.2", + "@typescript/typescript-openbsd-x64": "7.0.2", + "@typescript/typescript-sunos-x64": "7.0.2", + "@typescript/typescript-win32-arm64": "7.0.2", + "@typescript/typescript-win32-x64": "7.0.2" } }, "node_modules/undici-types": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", - "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", "dev": true, "license": "MIT" }, "node_modules/vite": { - "version": "8.0.16", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz", - "integrity": "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==", + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz", + "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", - "picomatch": "^4.0.4", - "postcss": "^8.5.15", - "rolldown": "1.0.3", + "picomatch": "^4.0.5", + "postcss": "^8.5.17", + "rolldown": "~1.1.5", "tinyglobby": "^0.2.17" }, "bin": { @@ -1429,7 +1834,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.1.18", + "@vitejs/devtools": "^0.3.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", @@ -1481,19 +1886,19 @@ } }, "node_modules/vitest": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.8.tgz", - "integrity": "sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", + "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.1.8", - "@vitest/mocker": "4.1.8", - "@vitest/pretty-format": "4.1.8", - "@vitest/runner": "4.1.8", - "@vitest/snapshot": "4.1.8", - "@vitest/spy": "4.1.8", - "@vitest/utils": "4.1.8", + "@vitest/expect": "4.1.10", + "@vitest/mocker": "4.1.10", + "@vitest/pretty-format": "4.1.10", + "@vitest/runner": "4.1.10", + "@vitest/snapshot": "4.1.10", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", @@ -1521,12 +1926,12 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.8", - "@vitest/browser-preview": "4.1.8", - "@vitest/browser-webdriverio": "4.1.8", - "@vitest/coverage-istanbul": "4.1.8", - "@vitest/coverage-v8": "4.1.8", - "@vitest/ui": "4.1.8", + "@vitest/browser-playwright": "4.1.10", + "@vitest/browser-preview": "4.1.10", + "@vitest/browser-webdriverio": "4.1.10", + "@vitest/coverage-istanbul": "4.1.10", + "@vitest/coverage-v8": "4.1.10", + "@vitest/ui": "4.1.10", "happy-dom": "*", "jsdom": "*", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" diff --git a/package.json b/package.json index 298a6d7..a46ab05 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cldmv/fix-headers", - "version": "1.3.6", + "version": "1.3.7", "description": "Multi-language project header normalizer with auto-detection and override support.", "type": "module", "main": "./index.cjs", @@ -31,7 +31,8 @@ "types:build": "tsc -p .configs/tsconfig.json --noCheck", "types:check": "tsc -p .configs/tsconfig.json --noEmit", "test:coverage": "vitest run --config .configs/vitest.config.mjs --coverage", - "cli": "node ./src/cli.mjs" + "cli": "node ./src/cli.mjs", + "build": "echo 'no build step - stopgap for CI coverage-badge; see tracking issue'" }, "keywords": [ "headers", @@ -75,9 +76,9 @@ "license": "Apache-2.0", "sideEffects": false, "devDependencies": { - "@types/node": "^25.3.0", + "@types/node": "^26.1.1", "@vitest/coverage-v8": "^4.1.8", - "typescript": "^5.9.3", + "typescript": "^7.0.2", "vitest": "^4.1.8" }, "dependencies": { diff --git a/src/constants.mjs b/src/constants.mjs index 632e4b3..0f21257 100644 --- a/src/constants.mjs +++ b/src/constants.mjs @@ -21,8 +21,10 @@ export { DETECTOR_PROFILES, getAllowedExtensions, getEnabledDetectors } from "./ /** @type {string} */ export const DEFAULT_COMPANY_NAME = "Catalyzed Motivation Inc."; -/** @type {number} */ -export const DEFAULT_MAX_HEADER_SCAN_LINES = 40; +/** Header must sit near the top of the file, but a metadata block can legitimately + * run long; cap the scan generously so a long block's closing `*​/` is still seen. + * @type {number} */ +export const DEFAULT_MAX_HEADER_SCAN_LINES = 200; /** * Folders skipped at ANY depth β€” vendored / VCS directories that are never source and can diff --git a/src/detectors/index.mjs b/src/detectors/index.mjs index 32d9cc9..94191bc 100644 --- a/src/detectors/index.mjs +++ b/src/detectors/index.mjs @@ -140,7 +140,7 @@ export function getDetectorById(id) { /** * Resolves comment syntax for a file path using detector-specific templates. * @param {string} filePath - File path. - * @param {{ language?: string, enabledDetectors?: string[], disabledDetectors?: string[], detectors?: object[], detectorSyntaxOverrides?: Record }} [options={}] - Runtime options. `detectors` overrides the enabled-detector set (matching {@link detectProjectFromMarkers}). + * @param {{ language?: string, enabledDetectors?: string[], disabledDetectors?: string[], detectors?: DetectorProfile[], detectorSyntaxOverrides?: Record }} [options={}] - Runtime options. `detectors` overrides the enabled-detector set (matching {@link detectProjectFromMarkers}). * @returns {{kind: "block" | "line" | "html", linePrefix?: string, lineSeparator?: string, blockStart?: string, blockLinePrefix?: string, blockEnd?: string}} Syntax descriptor. */ export function getCommentSyntaxForFile(filePath, options = {}) { diff --git a/tests/constants.test.vitest.mjs b/tests/constants.test.vitest.mjs index 2fc4bc4..65d1e40 100644 --- a/tests/constants.test.vitest.mjs +++ b/tests/constants.test.vitest.mjs @@ -17,7 +17,7 @@ import { DEFAULT_COMPANY_NAME, DEFAULT_IGNORE_FOLDERS, DEFAULT_MAX_HEADER_SCAN_L describe("constants", () => { it("exports expected defaults", () => { expect(DEFAULT_COMPANY_NAME).toBe("Catalyzed Motivation Inc."); - expect(DEFAULT_MAX_HEADER_SCAN_LINES).toBe(40); + expect(DEFAULT_MAX_HEADER_SCAN_LINES).toBe(200); expect(DEFAULT_IGNORE_FOLDERS.has("node_modules")).toBe(true); expect(DETECTOR_PROFILES.some((profile) => profile.id === "node")).toBe(true); expect(DETECTOR_PROFILES.some((profile) => profile.id === "json")).toBe(true); diff --git a/tests/header.test.vitest.mjs b/tests/header.test.vitest.mjs index 0da048b..f3a9358 100644 --- a/tests/header.test.vitest.mjs +++ b/tests/header.test.vitest.mjs @@ -141,6 +141,17 @@ describe("header/template + parser", () => { }); }); + it("replaces a header block longer than the old 40-line scan cap without duplicating it", () => { + const oldFields = Array.from({ length: 45 }, (_, i) => ` *\t@Field${i}: value${i}`).join("\n"); + const content = `/**\n *\t@Project: old\n${oldFields}\n */\n\nexport const value = 1;\n`; + const { nextContent } = replaceOrInsertHeader(content, "/**\\n *\\t@Project: new\\n */", "/repo/src/a.mjs"); + + expect(nextContent.match(/@Project:/g)).toHaveLength(1); + expect(nextContent).toContain("@Project: new"); + expect(nextContent).not.toContain("@Project: old"); + expect(nextContent).toContain("export const value = 1;"); + }); + it("inserts header after python shebang via detector", () => { const content = "#!/usr/bin/env python3\n\nprint('x')\n"; const replacement = replaceOrInsertHeader(content, "#\t@Project: x", "/repo/src/app.py");