From 2a80ba75e419c04f004ef06886e02efcbf0f8ec8 Mon Sep 17 00:00:00 2001 From: kyle Date: Thu, 12 Feb 2026 21:48:29 -0600 Subject: [PATCH] updates --- .github/.gitversion.yml | 22 + .github/workflows/pr.yml | 42 ++ .github/workflows/release.yml | 112 ++++ .gitignore | 2 + .nvmrc | 1 + .prettierignore | 10 + .prettierrc | 9 + action.sh | 83 +++ action.yml | 55 +- package.json | 22 + pnpm-lock.yaml | 874 ++++++++++++++++++++++++++ tests/format-value.bats | 60 ++ tests/full-run.bats | 75 +++ tests/print-section.bats | 33 + tests/snapshots/full-run.expected.txt | 53 ++ tests/test_helper/common-setup.bash | 12 + utility/cspell/cspell.config.json | 13 + utility/cspell/dictionary.txt | 2 + 18 files changed, 1434 insertions(+), 46 deletions(-) create mode 100644 .github/.gitversion.yml create mode 100644 .github/workflows/pr.yml create mode 100644 .github/workflows/release.yml create mode 100644 .nvmrc create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100755 action.sh create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 tests/format-value.bats create mode 100644 tests/full-run.bats create mode 100644 tests/print-section.bats create mode 100644 tests/snapshots/full-run.expected.txt create mode 100644 tests/test_helper/common-setup.bash create mode 100644 utility/cspell/cspell.config.json create mode 100644 utility/cspell/dictionary.txt diff --git a/.github/.gitversion.yml b/.github/.gitversion.yml new file mode 100644 index 0000000..457524f --- /dev/null +++ b/.github/.gitversion.yml @@ -0,0 +1,22 @@ +mode: ContinuousDeployment +tag-prefix: v +increment: None +commit-message-incrementing: Enabled +major-version-bump-message: '^(feat|fix|chore|ci|docs|test)(\(.+\))?\!:.*' +minor-version-bump-message: '^feat(\(.+\))?:.*' +patch-version-bump-message: '^(fix|ci)(\(.+\))?:.*' +branches: + main: + is-main-branch: true + increment: None + feature: + label: alpha + regex: ^(feat(ure)?|(bug)?fix)[\/-](?.+) + increment: None + release: + label: rc + regex: ^releases?[\/-](?.+) + increment: None +ignore: + sha: [] +merge-message-formats: {} diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 0000000..4cf74f0 --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,42 @@ +name: pr +on: + pull_request: + branches: + - main + +jobs: + validate: + name: validate + runs-on: ubuntu-latest + steps: + - uses: hwrok/print-workflow-data@v1 + + - name: checkout + uses: actions/checkout@v6 + + - name: pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + + - name: node + uses: actions/setup-node@v6.2.0 + with: + node-version-file: '.nvmrc' + cache: 'pnpm' + + - name: pnpm install + id: install-deps + run: pnpm install + + - name: check - tests + if: always() && steps.install-deps.outcome == 'success' + run: pnpm test + + - name: check - formatting + if: always() && steps.install-deps.outcome == 'success' + run: pnpm format + + - name: check - spelling + if: always() && steps.install-deps.outcome == 'success' + run: pnpm spellcheck diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..07f0270 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,112 @@ +name: release + +on: + workflow_dispatch: + workflow_call: + outputs: + version: + description: 'version' + value: ${{ jobs.release.outputs.version }} + tag: + description: 'version tag' + value: ${{ jobs.release.outputs.tag }} + +concurrency: + group: release + +jobs: + release: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.compute_version.outputs.semVer }} + tag: ${{ steps.check_tag.outputs.tag }} + permissions: + contents: write + + steps: + - uses: hwrok/print-workflow-data@v1 + + - name: checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: install gitversion + uses: gittools/actions/gitversion/setup@v4 + with: + versionSpec: '6.3.x' + preferLatestVersion: true + + - name: compute version + id: compute_version + uses: gittools/actions/gitversion/execute@v4 + with: + configFilePath: .github/.gitversion.yml + + - run: echo "version:${{ steps.compute_version.outputs.semVer }}" + + - name: check tag + id: check_tag + run: | + tag="v${{ steps.compute_version.outputs.semVer }}" + echo "tag=$tag" >> $GITHUB_OUTPUT + if git rev-parse "$tag" >/dev/null 2>&1; then + echo "::warning::Tag $tag already exists — skipping release." + else + echo "should_tag=true" >> $GITHUB_OUTPUT + fi + + - name: configure git + if: steps.check_tag.outputs.should_tag + run: | + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config user.name "github-actions[bot]" + + - name: create tag + if: steps.check_tag.outputs.should_tag + run: | + tag="${{ steps.check_tag.outputs.tag }}" + git tag "$tag" + git push origin "$tag" + + - name: changelog + if: steps.check_tag.outputs.should_tag + id: changelog + run: | + CURRENT_TAG="${{ steps.check_tag.outputs.tag }}" + PREV_TAG=$(git tag --sort=-version:refname | grep -v "$CURRENT_TAG" | head -n 1) + + if [ -z "$PREV_TAG" ]; then + PREV_TAG=$(git rev-list --max-parents=0 HEAD) + fi + + CHANGELOG=$(git log --pretty="- %s (%h)" "$PREV_TAG".."$CURRENT_TAG") + + DELIMITER=$(openssl rand -hex 16) + echo "CHANGELOG<<$DELIMITER" >> $GITHUB_ENV + echo "$CHANGELOG" >> $GITHUB_ENV + echo "$DELIMITER" >> $GITHUB_ENV + + - name: update tracking tag + if: steps.check_tag.outputs.should_tag + run: | + SEMVER="${{ steps.compute_version.outputs.semVer }}" + MAJOR_VERSION=$(echo $SEMVER | cut -d '.' -f 1) + TRACKING_TAG="v$MAJOR_VERSION" + + git tag -f $TRACKING_TAG + git push origin $TRACKING_TAG -f + + - name: create release + if: steps.check_tag.outputs.should_tag + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ steps.check_tag.outputs.tag }} + name: 'Release ${{ steps.check_tag.outputs.tag }}' + body: | + ## Release ${{ steps.check_tag.outputs.tag }} + + ### Changes + ${{ env.CHANGELOG }} + draft: false + prerelease: false diff --git a/.gitignore b/.gitignore index 485dee6..ac929d3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ +.claude .idea +node_modules diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..54c6511 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v24 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..5269977 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,10 @@ +# Package Managers +package-lock.json +pnpm-lock.yaml +yarn.lock +bun.lock +bun.lockb + +# Miscellaneous +/static/ +.terraform/ diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..e02fefa --- /dev/null +++ b/.prettierrc @@ -0,0 +1,9 @@ +{ + "useTabs": false, + "singleQuote": true, + "quoteProps": "consistent", + "trailingComma": "all", + "printWidth": 100, + "plugins": [], + "overrides": [] +} diff --git a/action.sh b/action.sh new file mode 100755 index 0000000..3bfb058 --- /dev/null +++ b/action.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +set +eo pipefail + +# formats a value for display +# json objects -> aligned key:value table +# other json -> pretty-printed +# non-json / n/a -> raw +format_value() { + local value="$1" + if [ "$value" = "n/a" ] || [ -z "$value" ]; then + echo "n/a" + return + fi + if ! command -v jq >/dev/null 2>&1; then + echo "$value" + return + fi + if echo "$value" | jq -e 'type == "object"' >/dev/null 2>&1; then + echo "$value" | jq -r ' + (keys | map(length) | max) as $w | + to_entries[] | + "\(.key + (" " * ($w - (.key | length)))) : \(.value | if type == "string" then . elif type == "null" then "" else tojson end)" + ' + return + fi + if echo "$value" | jq -e '.' >/dev/null 2>&1; then + echo "$value" | jq '.' + return + fi + echo "$value" +} + +# prints a labeled section with a colored box header +print_section() { + local title="$1" + local body="$2" + local color=92 # bright green + local bar_len=$(( ${#title} + 2 )) + local bar + bar="$(printf '─%.0s' $(seq 1 $bar_len))" + printf '\e[1;%sm┌%s┐\e[0m\n' "$color" "$bar" + printf '\e[1;%sm│ %s │\e[0m\n' "$color" "$title" + printf '\e[1;%sm└%s┘\e[0m\n' "$color" "$bar" + printf '%s\n' "$body" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + is_default_branch="false" + is_default_target="false" + [ "$GITHUB_REF_NAME" = "$DEFAULT_BRANCH" ] && is_default_branch="true" + [ "$GITHUB_BASE_REF" = "$DEFAULT_BRANCH" ] && is_default_target="true" + + github_context_body=$(cat <=20'} + + '@cspell/cspell-json-reporter@9.6.4': + resolution: {integrity: sha512-rGYSDnDWACrUyovfN8M/LM8CCFSKjYd2kehbNS7YMPk0Jk+rLk6sgt5WYu3ty45otXCkiO07bjUo/81wBLet7A==} + engines: {node: '>=20'} + + '@cspell/cspell-performance-monitor@9.6.4': + resolution: {integrity: sha512-exuqxV1IVfZkasg57ZjUbaHeZDd6Mdbsbe5FBT3+XaVnRij+wpY2oEW9+kIOL5MOQE3bgQKgu37iMtA1NlCrGA==} + engines: {node: '>=20.18'} + + '@cspell/cspell-pipe@9.6.4': + resolution: {integrity: sha512-vVxajTG9Ko01oHk8HPsMLajcLrd9AfkOk6vdgFI4FD7ZPq1CY0hfTmfmJ8bzZ4/QkqXglTvePdSgHQVJeltwWw==} + engines: {node: '>=20'} + + '@cspell/cspell-resolver@9.6.4': + resolution: {integrity: sha512-3xsgZEqqH9Uj8ZYLBnWbnsHz8wphgaeuWKcNDqgwoMjvwTMQLGoXjHht8Jx5yxd2e080lB7fJax8TaBdCzmFFA==} + engines: {node: '>=20'} + + '@cspell/cspell-service-bus@9.6.4': + resolution: {integrity: sha512-oGNEzP1gJ43rLklJQjOk5PsfX0mZkLjV19djGptb9xZQeC2qAUxnaAbZtWt5CE8ni2iiTaRmgNRbUqAhRCnjew==} + engines: {node: '>=20'} + + '@cspell/cspell-types@9.6.4': + resolution: {integrity: sha512-lf6d+BdMkJIFCxx2FpajLpqVGGyaGUNFU6jhEM6QUPeGuoA5et2kJXrL0NSY2uWLOVyYYc/FPjzlbe8trA9tBQ==} + engines: {node: '>=20'} + + '@cspell/cspell-worker@9.6.4': + resolution: {integrity: sha512-anacKDOZzDfPzuDeFOXGI2tFBYiRRCSnIZP/AOyJ9zTvEQcqq5p/ak18nJ5OQyDr2NG7ovJiCDT5YNiH2Vdg/g==} + engines: {node: '>=20.18'} + + '@cspell/dict-ada@4.1.1': + resolution: {integrity: sha512-E+0YW9RhZod/9Qy2gxfNZiHJjCYFlCdI69br1eviQQWB8yOTJX0JHXLs79kOYhSW0kINPVUdvddEBe6Lu6CjGQ==} + + '@cspell/dict-al@1.1.1': + resolution: {integrity: sha512-sD8GCaZetgQL4+MaJLXqbzWcRjfKVp8x+px3HuCaaiATAAtvjwUQ5/Iubiqwfd1boIh2Y1/3EgM3TLQ7Q8e0wQ==} + + '@cspell/dict-aws@4.0.17': + resolution: {integrity: sha512-ORcblTWcdlGjIbWrgKF+8CNEBQiLVKdUOFoTn0KPNkAYnFcdPP0muT4892h7H4Xafh3j72wqB4/loQ6Nti9E/w==} + + '@cspell/dict-bash@4.2.2': + resolution: {integrity: sha512-kyWbwtX3TsCf5l49gGQIZkRLaB/P8g73GDRm41Zu8Mv51kjl2H7Au0TsEvHv7jzcsRLS6aUYaZv6Zsvk1fOz+Q==} + + '@cspell/dict-companies@3.2.10': + resolution: {integrity: sha512-bJ1qnO1DkTn7JYGXvxp8FRQc4yq6tRXnrII+jbP8hHmq5TX5o1Wu+rdfpoUQaMWTl6balRvcMYiINDesnpR9Bw==} + + '@cspell/dict-cpp@7.0.2': + resolution: {integrity: sha512-dfbeERiVNeqmo/npivdR6rDiBCqZi3QtjH2Z0HFcXwpdj6i97dX1xaKyK2GUsO/p4u1TOv63Dmj5Vm48haDpuA==} + + '@cspell/dict-cryptocurrencies@5.0.5': + resolution: {integrity: sha512-R68hYYF/rtlE6T/dsObStzN5QZw+0aQBinAXuWCVqwdS7YZo0X33vGMfChkHaiCo3Z2+bkegqHlqxZF4TD3rUA==} + + '@cspell/dict-csharp@4.0.8': + resolution: {integrity: sha512-qmk45pKFHSxckl5mSlbHxmDitSsGMlk/XzFgt7emeTJWLNSTUK//MbYAkBNRtfzB4uD7pAFiKgpKgtJrTMRnrQ==} + + '@cspell/dict-css@4.0.19': + resolution: {integrity: sha512-VYHtPnZt/Zd/ATbW3rtexWpBnHUohUrQOHff/2JBhsVgxOrksAxJnLAO43Q1ayLJBJUUwNVo+RU0sx0aaysZfg==} + + '@cspell/dict-dart@2.3.2': + resolution: {integrity: sha512-sUiLW56t9gfZcu8iR/5EUg+KYyRD83Cjl3yjDEA2ApVuJvK1HhX+vn4e4k4YfjpUQMag8XO2AaRhARE09+/rqw==} + + '@cspell/dict-data-science@2.0.13': + resolution: {integrity: sha512-l1HMEhBJkPmw4I2YGVu2eBSKM89K9pVF+N6qIr5Uo5H3O979jVodtuwP8I7LyPrJnC6nz28oxeGRCLh9xC5CVA==} + + '@cspell/dict-django@4.1.6': + resolution: {integrity: sha512-SdbSFDGy9ulETqNz15oWv2+kpWLlk8DJYd573xhIkeRdcXOjskRuxjSZPKfW7O3NxN/KEf3gm3IevVOiNuFS+w==} + + '@cspell/dict-docker@1.1.17': + resolution: {integrity: sha512-OcnVTIpHIYYKhztNTyK8ShAnXTfnqs43hVH6p0py0wlcwRIXe5uj4f12n7zPf2CeBI7JAlPjEsV0Rlf4hbz/xQ==} + + '@cspell/dict-dotnet@5.0.12': + resolution: {integrity: sha512-FiV934kNieIjGTkiApu/WKvLYi/KBpvfWB2TSqpDQtmXZlt3uSa5blwblO1ZC8OvjH8RCq/31H5IdEYmTaZS7A==} + + '@cspell/dict-elixir@4.0.8': + resolution: {integrity: sha512-CyfphrbMyl4Ms55Vzuj+mNmd693HjBFr9hvU+B2YbFEZprE5AG+EXLYTMRWrXbpds4AuZcvN3deM2XVB80BN/Q==} + + '@cspell/dict-en-common-misspellings@2.1.12': + resolution: {integrity: sha512-14Eu6QGqyksqOd4fYPuRb58lK1Va7FQK9XxFsRKnZU8LhL3N+kj7YKDW+7aIaAN/0WGEqslGP6lGbQzNti8Akw==} + + '@cspell/dict-en-gb-mit@3.1.18': + resolution: {integrity: sha512-AXaMzbaxhSc32MSzKX0cpwT+Thv1vPfxQz1nTly1VHw3wQcwPqVFSqrLOYwa8VNqAPR45583nnhD6iqJ9YESoQ==} + + '@cspell/dict-en_us@4.4.29': + resolution: {integrity: sha512-G3B27++9ziRdgbrY/G/QZdFAnMzzx17u8nCb2Xyd4q6luLpzViRM/CW3jA+Mb/cGT5zR/9N+Yz9SrGu1s0bq7g==} + + '@cspell/dict-filetypes@3.0.15': + resolution: {integrity: sha512-uDMeqYlLlK476w/muEFQGBy9BdQWS0mQ7BJiy/iQv5XUWZxE2O54ZQd9nW8GyQMzAgoyg5SG4hf9l039Qt66oA==} + + '@cspell/dict-flutter@1.1.1': + resolution: {integrity: sha512-UlOzRcH2tNbFhZmHJN48Za/2/MEdRHl2BMkCWZBYs+30b91mWvBfzaN4IJQU7dUZtowKayVIF9FzvLZtZokc5A==} + + '@cspell/dict-fonts@4.0.5': + resolution: {integrity: sha512-BbpkX10DUX/xzHs6lb7yzDf/LPjwYIBJHJlUXSBXDtK/1HaeS+Wqol4Mlm2+NAgZ7ikIE5DQMViTgBUY3ezNoQ==} + + '@cspell/dict-fsharp@1.1.1': + resolution: {integrity: sha512-imhs0u87wEA4/cYjgzS0tAyaJpwG7vwtC8UyMFbwpmtw+/bgss+osNfyqhYRyS/ehVCWL17Ewx2UPkexjKyaBA==} + + '@cspell/dict-fullstack@3.2.8': + resolution: {integrity: sha512-J6EeoeThvx/DFrcA2rJiCA6vfqwJMbkG0IcXhlsmRZmasIpanmxgt90OEaUazbZahFiuJT8wrhgQ1QgD1MsqBw==} + + '@cspell/dict-gaming-terms@1.1.2': + resolution: {integrity: sha512-9XnOvaoTBscq0xuD6KTEIkk9hhdfBkkvJAIsvw3JMcnp1214OCGW8+kako5RqQ2vTZR3Tnf3pc57o7VgkM0q1Q==} + + '@cspell/dict-git@3.1.0': + resolution: {integrity: sha512-KEt9zGkxqGy2q1nwH4CbyqTSv5nadpn8BAlDnzlRcnL0Xb3LX9xTgSGShKvzb0bw35lHoYyLWN2ZKAqbC4pgGQ==} + + '@cspell/dict-golang@6.0.26': + resolution: {integrity: sha512-YKA7Xm5KeOd14v5SQ4ll6afe9VSy3a2DWM7L9uBq4u3lXToRBQ1W5PRa+/Q9udd+DTURyVVnQ+7b9cnOlNxaRg==} + + '@cspell/dict-google@1.0.9': + resolution: {integrity: sha512-biL65POqialY0i4g6crj7pR6JnBkbsPovB2WDYkj3H4TuC/QXv7Pu5pdPxeUJA6TSCHI7T5twsO4VSVyRxD9CA==} + + '@cspell/dict-haskell@4.0.6': + resolution: {integrity: sha512-ib8SA5qgftExpYNjWhpYIgvDsZ/0wvKKxSP+kuSkkak520iPvTJumEpIE+qPcmJQo4NzdKMN8nEfaeci4OcFAQ==} + + '@cspell/dict-html-symbol-entities@4.0.5': + resolution: {integrity: sha512-429alTD4cE0FIwpMucvSN35Ld87HCyuM8mF731KU5Rm4Je2SG6hmVx7nkBsLyrmH3sQukTcr1GaiZsiEg8svPA==} + + '@cspell/dict-html@4.0.14': + resolution: {integrity: sha512-2bf7n+kS92g+cMKV0wr9o/Oq9n8JzU7CcrB96gIh2GHgnF+0xDOqO2W/1KeFAqOfqosoOVE48t+4dnEMkkoJ2Q==} + + '@cspell/dict-java@5.0.12': + resolution: {integrity: sha512-qPSNhTcl7LGJ5Qp6VN71H8zqvRQK04S08T67knMq9hTA8U7G1sTKzLmBaDOFhq17vNX/+rT+rbRYp+B5Nwza1A==} + + '@cspell/dict-julia@1.1.1': + resolution: {integrity: sha512-WylJR9TQ2cgwd5BWEOfdO3zvDB+L7kYFm0I9u0s9jKHWQ6yKmfKeMjU9oXxTBxIufhCXm92SKwwVNAC7gjv+yA==} + + '@cspell/dict-k8s@1.0.12': + resolution: {integrity: sha512-2LcllTWgaTfYC7DmkMPOn9GsBWsA4DZdlun4po8s2ysTP7CPEnZc1ZfK6pZ2eI4TsZemlUQQ+NZxMe9/QutQxg==} + + '@cspell/dict-kotlin@1.1.1': + resolution: {integrity: sha512-J3NzzfgmxRvEeOe3qUXnSJQCd38i/dpF9/t3quuWh6gXM+krsAXP75dY1CzDmS8mrJAlBdVBeAW5eAZTD8g86Q==} + + '@cspell/dict-latex@5.0.0': + resolution: {integrity: sha512-HUrIqUVohM6P0+5b7BsdAdb0STIv0aaFBvguI7pLcreljlcX3FSPUxea7ticzNlCNeVrEaiEn/ws9m6rYUeuNw==} + + '@cspell/dict-lorem-ipsum@4.0.5': + resolution: {integrity: sha512-9a4TJYRcPWPBKkQAJ/whCu4uCAEgv/O2xAaZEI0n4y1/l18Yyx8pBKoIX5QuVXjjmKEkK7hi5SxyIsH7pFEK9Q==} + + '@cspell/dict-lua@4.0.8': + resolution: {integrity: sha512-N4PkgNDMu9JVsRu7JBS/3E/dvfItRgk9w5ga2dKq+JupP2Y3lojNaAVFhXISh4Y0a6qXDn2clA6nvnavQ/jjLA==} + + '@cspell/dict-makefile@1.0.5': + resolution: {integrity: sha512-4vrVt7bGiK8Rx98tfRbYo42Xo2IstJkAF4tLLDMNQLkQ86msDlYSKG1ZCk8Abg+EdNcFAjNhXIiNO+w4KflGAQ==} + + '@cspell/dict-markdown@2.0.14': + resolution: {integrity: sha512-uLKPNJsUcumMQTsZZgAK9RgDLyQhUz/uvbQTEkvF/Q4XfC1i/BnA8XrOrd0+Vp6+tPOKyA+omI5LRWfMu5K/Lw==} + peerDependencies: + '@cspell/dict-css': ^4.0.19 + '@cspell/dict-html': ^4.0.14 + '@cspell/dict-html-symbol-entities': ^4.0.5 + '@cspell/dict-typescript': ^3.2.3 + + '@cspell/dict-monkeyc@1.0.12': + resolution: {integrity: sha512-MN7Vs11TdP5mbdNFQP5x2Ac8zOBm97ARg6zM5Sb53YQt/eMvXOMvrep7+/+8NJXs0jkp70bBzjqU4APcqBFNAw==} + + '@cspell/dict-node@5.0.9': + resolution: {integrity: sha512-hO+ga+uYZ/WA4OtiMEyKt5rDUlUyu3nXMf8KVEeqq2msYvAPdldKBGH7lGONg6R/rPhv53Rb+0Y1SLdoK1+7wQ==} + + '@cspell/dict-npm@5.2.34': + resolution: {integrity: sha512-M2MtfmYeHIPBuC8esMU4JQXHKma7Xt7VyBWUk67B62KDu61sxebQ2HeizdqmN2sLEJsTkq3bZT5PGzHpZ0LEWQ==} + + '@cspell/dict-php@4.1.1': + resolution: {integrity: sha512-EXelI+4AftmdIGtA8HL8kr4WlUE11OqCSVlnIgZekmTkEGSZdYnkFdiJ5IANSALtlQ1mghKjz+OFqVs6yowgWA==} + + '@cspell/dict-powershell@5.0.15': + resolution: {integrity: sha512-l4S5PAcvCFcVDMJShrYD0X6Huv9dcsQPlsVsBGbH38wvuN7gS7+GxZFAjTNxDmTY1wrNi1cCatSg6Pu2BW4rgg==} + + '@cspell/dict-public-licenses@2.0.15': + resolution: {integrity: sha512-cJEOs901H13Pfy0fl4dCD1U+xpWIMaEPq8MeYU83FfDZvellAuSo4GqWCripfIqlhns/L6+UZEIJSOZnjgy7Wg==} + + '@cspell/dict-python@4.2.25': + resolution: {integrity: sha512-hDdN0YhKgpbtZVRjQ2c8jk+n0wQdidAKj1Fk8w7KEHb3YlY5uPJ0mAKJk7AJKPNLOlILoUmN+HAVJz+cfSbWYg==} + + '@cspell/dict-r@2.1.1': + resolution: {integrity: sha512-71Ka+yKfG4ZHEMEmDxc6+blFkeTTvgKbKAbwiwQAuKl3zpqs1Y0vUtwW2N4b3LgmSPhV3ODVY0y4m5ofqDuKMw==} + + '@cspell/dict-ruby@5.1.0': + resolution: {integrity: sha512-9PJQB3cfkBULrMLp5kSAcFPpzf8oz9vFN+QYZABhQwWkGbuzCIXSorHrmWSASlx4yejt3brjaWS57zZ/YL5ZQQ==} + + '@cspell/dict-rust@4.1.2': + resolution: {integrity: sha512-O1FHrumYcO+HZti3dHfBPUdnDFkI+nbYK3pxYmiM1sr+G0ebOd6qchmswS0Wsc6ZdEVNiPYJY/gZQR6jfW3uOg==} + + '@cspell/dict-scala@5.0.9': + resolution: {integrity: sha512-AjVcVAELgllybr1zk93CJ5wSUNu/Zb5kIubymR/GAYkMyBdYFCZ3Zbwn4Zz8GJlFFAbazABGOu0JPVbeY59vGg==} + + '@cspell/dict-shell@1.1.2': + resolution: {integrity: sha512-WqOUvnwcHK1X61wAfwyXq04cn7KYyskg90j4lLg3sGGKMW9Sq13hs91pqrjC44Q+lQLgCobrTkMDw9Wyl9nRFA==} + + '@cspell/dict-software-terms@5.1.21': + resolution: {integrity: sha512-3lAB4OXsf6rs5zbwe4/nKmwyAJAvjs5KTRrPckzHx7q9dYpviW+UxDyhevCCsRfmcu24OhYP7BVQWXxLvYk4xA==} + + '@cspell/dict-sql@2.2.1': + resolution: {integrity: sha512-qDHF8MpAYCf4pWU8NKbnVGzkoxMNrFqBHyG/dgrlic5EQiKANCLELYtGlX5auIMDLmTf1inA0eNtv74tyRJ/vg==} + + '@cspell/dict-svelte@1.0.7': + resolution: {integrity: sha512-hGZsGqP0WdzKkdpeVLBivRuSNzOTvN036EBmpOwxH+FTY2DuUH7ecW+cSaMwOgmq5JFSdTcbTNFlNC8HN8lhaQ==} + + '@cspell/dict-swift@2.0.6': + resolution: {integrity: sha512-PnpNbrIbex2aqU1kMgwEKvCzgbkHtj3dlFLPMqW1vSniop7YxaDTtvTUO4zA++ugYAEL+UK8vYrBwDPTjjvSnA==} + + '@cspell/dict-terraform@1.1.3': + resolution: {integrity: sha512-gr6wxCydwSFyyBKhBA2xkENXtVFToheqYYGFvlMZXWjviynXmh+NK/JTvTCk/VHk3+lzbO9EEQKee6VjrAUSbA==} + + '@cspell/dict-typescript@3.2.3': + resolution: {integrity: sha512-zXh1wYsNljQZfWWdSPYwQhpwiuW0KPW1dSd8idjMRvSD0aSvWWHoWlrMsmZeRl4qM4QCEAjua8+cjflm41cQBg==} + + '@cspell/dict-vue@3.0.5': + resolution: {integrity: sha512-Mqutb8jbM+kIcywuPQCCaK5qQHTdaByoEO2J9LKFy3sqAdiBogNkrplqUK0HyyRFgCfbJUgjz3N85iCMcWH0JA==} + + '@cspell/dict-zig@1.0.0': + resolution: {integrity: sha512-XibBIxBlVosU06+M6uHWkFeT0/pW5WajDRYdXG2CgHnq85b0TI/Ks0FuBJykmsgi2CAD3Qtx8UHFEtl/DSFnAQ==} + + '@cspell/dynamic-import@9.6.4': + resolution: {integrity: sha512-1VnL9ahT3s17DLWl4MeO1pYg7zcVT3X9cKynI2/U86zNK5xMGS5icvjp7X65tsCAVNcWOtkqVFfrxi7kWxn67g==} + engines: {node: '>=20'} + + '@cspell/filetypes@9.6.4': + resolution: {integrity: sha512-a1aZ/8vGnhTknxTukjzo3m8CISyHW2MWnbedywg5SDEl5RMJitmzX90QZiQdSvEcqzqmtoAgSEZNBT2LX2gIKg==} + engines: {node: '>=20'} + + '@cspell/rpc@9.6.4': + resolution: {integrity: sha512-vGI1788Rx5Yml9N1/pD4zGd8Vrchi2Y01ADf9NiiOaNVVdf4PU1GCssLCsiIzhYQneErpQ8pJi/mS2F/QMZbRA==} + engines: {node: '>=20.18'} + + '@cspell/strong-weak-map@9.6.4': + resolution: {integrity: sha512-AQrUbA0JUOEQgwItnfUQ6Ydk0hWY/uV3VhLwZWyrnT9eiQynmTnRTHtOCkkSl9+M4P0N4Raa2eGFRLcPAFksaw==} + engines: {node: '>=20'} + + '@cspell/url@9.6.4': + resolution: {integrity: sha512-h6VMlb7bDyGJfwLtipxxtHlT+ojzUXZz14AqZ/NEzY3LfOhfJTGpRcWLYFsgG/L0Ma4qjsYbPJt/Sj1C14j0VA==} + engines: {node: '>=20'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + array-timsort@1.0.3: + resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} + + bats-assert@2.2.4: + resolution: {integrity: sha512-EcaY4Z+Tbz1c7pnC1SrVSq0epr7tLwFpz6qt7KUW9K8uSw8V12DTfH9d2HxZWvBEATaCuMsZ7KoZMFiSQPRoXw==} + peerDependencies: + bats: 0.4 || ^1 + bats-support: ^0.3 + + bats-support@0.3.0: + resolution: {integrity: sha512-z+2WzXbI4OZgLnynydqH8GpI3+DcOtepO66PlK47SfEzTkiuV9hxn9eIQX+uLVFbt2Oqoc7Ky3TJ/N83lqD+cg==} + peerDependencies: + bats: 0.4 || ^1 + + bats@1.13.0: + resolution: {integrity: sha512-giSYKGTOcPZyJDbfbTtzAedLcNWdjCLbXYU3/MwPnjyvDXzu6Dgw8d2M+8jHhZXSmsCMSQqCp+YBsJ603UO4vQ==} + hasBin: true + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + chalk-template@1.1.2: + resolution: {integrity: sha512-2bxTP2yUH7AJj/VAXfcA+4IcWGdQ87HwBANLt5XxGTeomo8yG0y95N1um9i5StvhT/Bl0/2cARA5v1PpPXUxUA==} + engines: {node: '>=14.16'} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + clear-module@4.1.2: + resolution: {integrity: sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==} + engines: {node: '>=8'} + + commander@14.0.3: + resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} + engines: {node: '>=20'} + + comment-json@4.5.1: + resolution: {integrity: sha512-taEtr3ozUmOB7it68Jll7s0Pwm+aoiHyXKrEC8SEodL4rNpdfDLqa7PfBlrgFoCNNdR8ImL+muti5IGvktJAAg==} + engines: {node: '>= 6'} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cspell-config-lib@9.6.4: + resolution: {integrity: sha512-MecJNR9bIlcPBhyZFsXP6Q2n8qQ2IR9N9HiIz0yh0gBNVydp3LR5JITP5Ji8m7hexmZzVeoXms/dVN74XbS95g==} + engines: {node: '>=20'} + + cspell-dictionary@9.6.4: + resolution: {integrity: sha512-Ik9ZQVqV/fJfMt5X6IkC7yHGVH46/qjcqCNWwrMSwvROLM3SemNxxZoLvh0wi0GXz9WF1lHcxLJVdeKUk6QB8g==} + engines: {node: '>=20'} + + cspell-gitignore@9.6.4: + resolution: {integrity: sha512-a8asE9BsjJgJ506WUGh5VHrTdVEE8hWELjCJB2atPrW6iY5e4aCIugy0gkRC1ZH9/TseadlmMLrFzHUkJUjzsg==} + engines: {node: '>=20'} + hasBin: true + + cspell-glob@9.6.4: + resolution: {integrity: sha512-253VrjbR8QU15h8GtpDQLX5Ti9uNSuNod2T7f8YEElQOb9I/kUXoCj3Cq4P390IC99klqSHIDxHsxd77ex19lA==} + engines: {node: '>=20'} + + cspell-grammar@9.6.4: + resolution: {integrity: sha512-rvZyTB45/XSRWx7eAsrvTTAZvBTREr/2G2JWVMdqrptFyq1XReAKHhw/x1HJkNgWC9LKAK3bVQJpjLsNG37U9A==} + engines: {node: '>=20'} + hasBin: true + + cspell-io@9.6.4: + resolution: {integrity: sha512-bmvJ4yn5QK2FZWTkZA4sx2qJqIi8BrUUUV7W209drSwkYjhJtXqP0RyF6Qx4Xuu2D1s0UilEtO5Jd+E9UJkQ6w==} + engines: {node: '>=20'} + + cspell-lib@9.6.4: + resolution: {integrity: sha512-fUodKcIHTwvokuowB25XyFzBxlk73yj1QRw2por3BxDz9fAim1zAIohAPAnGuzj3LowYnTMjHLYE7RFDUSxy5A==} + engines: {node: '>=20'} + + cspell-trie-lib@9.6.4: + resolution: {integrity: sha512-JKwyRtyybbaTrixwI1OgU5Hvva2Z5zHVWl92WBa9U7KijAyiD/Ehp3T3DCYuBwGks7egw7MgWPySkXXnpme6mw==} + engines: {node: '>=20'} + peerDependencies: + '@cspell/cspell-types': 9.6.4 + + cspell@9.6.4: + resolution: {integrity: sha512-rZJmgcyBGKX3KcJ3KC9JYVHeKhDEVbmCheSp8eRGMYw6MCG9o7FHqQjGA/u4lEu4A0psr7ACP/5ym/QHyntRbA==} + engines: {node: '>=20.18'} + hasBin: true + + env-paths@4.0.0: + resolution: {integrity: sha512-pxP8eL2SwwaTRi/KHYwLYXinDs7gL3jxFcBYmEdYfZmZXbaVDvdppd0XBU8qVz03rDfKZMXg1omHCbsJjZrMsw==} + engines: {node: '>=20'} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + fast-equals@6.0.0: + resolution: {integrity: sha512-PFhhIGgdM79r5Uztdj9Zb6Tt1zKafqVfdMGwVca1z5z6fbX7DmsySSuJd8HiP6I1j505DCS83cLxo5rmSNeVEA==} + engines: {node: '>=6.0.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + gensequence@8.0.8: + resolution: {integrity: sha512-omMVniXEXpdx/vKxGnPRoO2394Otlze28TyxECbFVyoSpZ9H3EO7lemjcB12OpQJzRW4e5tt/dL1rOxry6aMHg==} + engines: {node: '>=20'} + + global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-meta-resolve@4.2.0: + resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} + + ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + is-safe-filename@0.1.1: + resolution: {integrity: sha512-4SrR7AdnY11LHfDKTZY1u6Ga3RuxZdl3YKWWShO5iyuG5h8QS4GD2tOb04peBJ5I7pXbR+CGBNEhTcwK+FzN3g==} + engines: {node: '>=20'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parent-module@2.0.0: + resolution: {integrity: sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==} + engines: {node: '>=8'} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + prettier@3.8.1: + resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==} + engines: {node: '>=14'} + hasBin: true + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + + smol-toml@1.6.0: + resolution: {integrity: sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==} + engines: {node: '>= 18'} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + vscode-languageserver-textdocument@1.0.12: + resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==} + + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + + xdg-basedir@5.1.0: + resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} + engines: {node: '>=12'} + + yaml@2.8.2: + resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} + engines: {node: '>= 14.6'} + hasBin: true + +snapshots: + + '@cspell/cspell-bundled-dicts@9.6.4': + dependencies: + '@cspell/dict-ada': 4.1.1 + '@cspell/dict-al': 1.1.1 + '@cspell/dict-aws': 4.0.17 + '@cspell/dict-bash': 4.2.2 + '@cspell/dict-companies': 3.2.10 + '@cspell/dict-cpp': 7.0.2 + '@cspell/dict-cryptocurrencies': 5.0.5 + '@cspell/dict-csharp': 4.0.8 + '@cspell/dict-css': 4.0.19 + '@cspell/dict-dart': 2.3.2 + '@cspell/dict-data-science': 2.0.13 + '@cspell/dict-django': 4.1.6 + '@cspell/dict-docker': 1.1.17 + '@cspell/dict-dotnet': 5.0.12 + '@cspell/dict-elixir': 4.0.8 + '@cspell/dict-en-common-misspellings': 2.1.12 + '@cspell/dict-en-gb-mit': 3.1.18 + '@cspell/dict-en_us': 4.4.29 + '@cspell/dict-filetypes': 3.0.15 + '@cspell/dict-flutter': 1.1.1 + '@cspell/dict-fonts': 4.0.5 + '@cspell/dict-fsharp': 1.1.1 + '@cspell/dict-fullstack': 3.2.8 + '@cspell/dict-gaming-terms': 1.1.2 + '@cspell/dict-git': 3.1.0 + '@cspell/dict-golang': 6.0.26 + '@cspell/dict-google': 1.0.9 + '@cspell/dict-haskell': 4.0.6 + '@cspell/dict-html': 4.0.14 + '@cspell/dict-html-symbol-entities': 4.0.5 + '@cspell/dict-java': 5.0.12 + '@cspell/dict-julia': 1.1.1 + '@cspell/dict-k8s': 1.0.12 + '@cspell/dict-kotlin': 1.1.1 + '@cspell/dict-latex': 5.0.0 + '@cspell/dict-lorem-ipsum': 4.0.5 + '@cspell/dict-lua': 4.0.8 + '@cspell/dict-makefile': 1.0.5 + '@cspell/dict-markdown': 2.0.14(@cspell/dict-css@4.0.19)(@cspell/dict-html-symbol-entities@4.0.5)(@cspell/dict-html@4.0.14)(@cspell/dict-typescript@3.2.3) + '@cspell/dict-monkeyc': 1.0.12 + '@cspell/dict-node': 5.0.9 + '@cspell/dict-npm': 5.2.34 + '@cspell/dict-php': 4.1.1 + '@cspell/dict-powershell': 5.0.15 + '@cspell/dict-public-licenses': 2.0.15 + '@cspell/dict-python': 4.2.25 + '@cspell/dict-r': 2.1.1 + '@cspell/dict-ruby': 5.1.0 + '@cspell/dict-rust': 4.1.2 + '@cspell/dict-scala': 5.0.9 + '@cspell/dict-shell': 1.1.2 + '@cspell/dict-software-terms': 5.1.21 + '@cspell/dict-sql': 2.2.1 + '@cspell/dict-svelte': 1.0.7 + '@cspell/dict-swift': 2.0.6 + '@cspell/dict-terraform': 1.1.3 + '@cspell/dict-typescript': 3.2.3 + '@cspell/dict-vue': 3.0.5 + '@cspell/dict-zig': 1.0.0 + + '@cspell/cspell-json-reporter@9.6.4': + dependencies: + '@cspell/cspell-types': 9.6.4 + + '@cspell/cspell-performance-monitor@9.6.4': {} + + '@cspell/cspell-pipe@9.6.4': {} + + '@cspell/cspell-resolver@9.6.4': + dependencies: + global-directory: 4.0.1 + + '@cspell/cspell-service-bus@9.6.4': {} + + '@cspell/cspell-types@9.6.4': {} + + '@cspell/cspell-worker@9.6.4': + dependencies: + cspell-lib: 9.6.4 + + '@cspell/dict-ada@4.1.1': {} + + '@cspell/dict-al@1.1.1': {} + + '@cspell/dict-aws@4.0.17': {} + + '@cspell/dict-bash@4.2.2': + dependencies: + '@cspell/dict-shell': 1.1.2 + + '@cspell/dict-companies@3.2.10': {} + + '@cspell/dict-cpp@7.0.2': {} + + '@cspell/dict-cryptocurrencies@5.0.5': {} + + '@cspell/dict-csharp@4.0.8': {} + + '@cspell/dict-css@4.0.19': {} + + '@cspell/dict-dart@2.3.2': {} + + '@cspell/dict-data-science@2.0.13': {} + + '@cspell/dict-django@4.1.6': {} + + '@cspell/dict-docker@1.1.17': {} + + '@cspell/dict-dotnet@5.0.12': {} + + '@cspell/dict-elixir@4.0.8': {} + + '@cspell/dict-en-common-misspellings@2.1.12': {} + + '@cspell/dict-en-gb-mit@3.1.18': {} + + '@cspell/dict-en_us@4.4.29': {} + + '@cspell/dict-filetypes@3.0.15': {} + + '@cspell/dict-flutter@1.1.1': {} + + '@cspell/dict-fonts@4.0.5': {} + + '@cspell/dict-fsharp@1.1.1': {} + + '@cspell/dict-fullstack@3.2.8': {} + + '@cspell/dict-gaming-terms@1.1.2': {} + + '@cspell/dict-git@3.1.0': {} + + '@cspell/dict-golang@6.0.26': {} + + '@cspell/dict-google@1.0.9': {} + + '@cspell/dict-haskell@4.0.6': {} + + '@cspell/dict-html-symbol-entities@4.0.5': {} + + '@cspell/dict-html@4.0.14': {} + + '@cspell/dict-java@5.0.12': {} + + '@cspell/dict-julia@1.1.1': {} + + '@cspell/dict-k8s@1.0.12': {} + + '@cspell/dict-kotlin@1.1.1': {} + + '@cspell/dict-latex@5.0.0': {} + + '@cspell/dict-lorem-ipsum@4.0.5': {} + + '@cspell/dict-lua@4.0.8': {} + + '@cspell/dict-makefile@1.0.5': {} + + '@cspell/dict-markdown@2.0.14(@cspell/dict-css@4.0.19)(@cspell/dict-html-symbol-entities@4.0.5)(@cspell/dict-html@4.0.14)(@cspell/dict-typescript@3.2.3)': + dependencies: + '@cspell/dict-css': 4.0.19 + '@cspell/dict-html': 4.0.14 + '@cspell/dict-html-symbol-entities': 4.0.5 + '@cspell/dict-typescript': 3.2.3 + + '@cspell/dict-monkeyc@1.0.12': {} + + '@cspell/dict-node@5.0.9': {} + + '@cspell/dict-npm@5.2.34': {} + + '@cspell/dict-php@4.1.1': {} + + '@cspell/dict-powershell@5.0.15': {} + + '@cspell/dict-public-licenses@2.0.15': {} + + '@cspell/dict-python@4.2.25': + dependencies: + '@cspell/dict-data-science': 2.0.13 + + '@cspell/dict-r@2.1.1': {} + + '@cspell/dict-ruby@5.1.0': {} + + '@cspell/dict-rust@4.1.2': {} + + '@cspell/dict-scala@5.0.9': {} + + '@cspell/dict-shell@1.1.2': {} + + '@cspell/dict-software-terms@5.1.21': {} + + '@cspell/dict-sql@2.2.1': {} + + '@cspell/dict-svelte@1.0.7': {} + + '@cspell/dict-swift@2.0.6': {} + + '@cspell/dict-terraform@1.1.3': {} + + '@cspell/dict-typescript@3.2.3': {} + + '@cspell/dict-vue@3.0.5': {} + + '@cspell/dict-zig@1.0.0': {} + + '@cspell/dynamic-import@9.6.4': + dependencies: + '@cspell/url': 9.6.4 + import-meta-resolve: 4.2.0 + + '@cspell/filetypes@9.6.4': {} + + '@cspell/rpc@9.6.4': {} + + '@cspell/strong-weak-map@9.6.4': {} + + '@cspell/url@9.6.4': {} + + ansi-regex@6.2.2: {} + + array-timsort@1.0.3: {} + + bats-assert@2.2.4(bats-support@0.3.0(bats@1.13.0))(bats@1.13.0): + dependencies: + bats: 1.13.0 + bats-support: 0.3.0(bats@1.13.0) + + bats-support@0.3.0(bats@1.13.0): + dependencies: + bats: 1.13.0 + + bats@1.13.0: {} + + callsites@3.1.0: {} + + chalk-template@1.1.2: + dependencies: + chalk: 5.6.2 + + chalk@5.6.2: {} + + clear-module@4.1.2: + dependencies: + parent-module: 2.0.0 + resolve-from: 5.0.0 + + commander@14.0.3: {} + + comment-json@4.5.1: + dependencies: + array-timsort: 1.0.3 + core-util-is: 1.0.3 + esprima: 4.0.1 + + core-util-is@1.0.3: {} + + cspell-config-lib@9.6.4: + dependencies: + '@cspell/cspell-types': 9.6.4 + comment-json: 4.5.1 + smol-toml: 1.6.0 + yaml: 2.8.2 + + cspell-dictionary@9.6.4: + dependencies: + '@cspell/cspell-performance-monitor': 9.6.4 + '@cspell/cspell-pipe': 9.6.4 + '@cspell/cspell-types': 9.6.4 + cspell-trie-lib: 9.6.4(@cspell/cspell-types@9.6.4) + fast-equals: 6.0.0 + + cspell-gitignore@9.6.4: + dependencies: + '@cspell/url': 9.6.4 + cspell-glob: 9.6.4 + cspell-io: 9.6.4 + + cspell-glob@9.6.4: + dependencies: + '@cspell/url': 9.6.4 + picomatch: 4.0.3 + + cspell-grammar@9.6.4: + dependencies: + '@cspell/cspell-pipe': 9.6.4 + '@cspell/cspell-types': 9.6.4 + + cspell-io@9.6.4: + dependencies: + '@cspell/cspell-service-bus': 9.6.4 + '@cspell/url': 9.6.4 + + cspell-lib@9.6.4: + dependencies: + '@cspell/cspell-bundled-dicts': 9.6.4 + '@cspell/cspell-performance-monitor': 9.6.4 + '@cspell/cspell-pipe': 9.6.4 + '@cspell/cspell-resolver': 9.6.4 + '@cspell/cspell-types': 9.6.4 + '@cspell/dynamic-import': 9.6.4 + '@cspell/filetypes': 9.6.4 + '@cspell/rpc': 9.6.4 + '@cspell/strong-weak-map': 9.6.4 + '@cspell/url': 9.6.4 + clear-module: 4.1.2 + cspell-config-lib: 9.6.4 + cspell-dictionary: 9.6.4 + cspell-glob: 9.6.4 + cspell-grammar: 9.6.4 + cspell-io: 9.6.4 + cspell-trie-lib: 9.6.4(@cspell/cspell-types@9.6.4) + env-paths: 4.0.0 + gensequence: 8.0.8 + import-fresh: 3.3.1 + resolve-from: 5.0.0 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.1.0 + xdg-basedir: 5.1.0 + + cspell-trie-lib@9.6.4(@cspell/cspell-types@9.6.4): + dependencies: + '@cspell/cspell-types': 9.6.4 + + cspell@9.6.4: + dependencies: + '@cspell/cspell-json-reporter': 9.6.4 + '@cspell/cspell-performance-monitor': 9.6.4 + '@cspell/cspell-pipe': 9.6.4 + '@cspell/cspell-types': 9.6.4 + '@cspell/cspell-worker': 9.6.4 + '@cspell/dynamic-import': 9.6.4 + '@cspell/url': 9.6.4 + ansi-regex: 6.2.2 + chalk: 5.6.2 + chalk-template: 1.1.2 + commander: 14.0.3 + cspell-config-lib: 9.6.4 + cspell-dictionary: 9.6.4 + cspell-gitignore: 9.6.4 + cspell-glob: 9.6.4 + cspell-io: 9.6.4 + cspell-lib: 9.6.4 + fast-json-stable-stringify: 2.1.0 + flatted: 3.3.3 + semver: 7.7.4 + tinyglobby: 0.2.15 + + env-paths@4.0.0: + dependencies: + is-safe-filename: 0.1.1 + + esprima@4.0.1: {} + + fast-equals@6.0.0: {} + + fast-json-stable-stringify@2.1.0: {} + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + flatted@3.3.3: {} + + gensequence@8.0.8: {} + + global-directory@4.0.1: + dependencies: + ini: 4.1.1 + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-meta-resolve@4.2.0: {} + + ini@4.1.1: {} + + is-safe-filename@0.1.1: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parent-module@2.0.0: + dependencies: + callsites: 3.1.0 + + picomatch@4.0.3: {} + + prettier@3.8.1: {} + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + semver@7.7.4: {} + + smol-toml@1.6.0: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + vscode-languageserver-textdocument@1.0.12: {} + + vscode-uri@3.1.0: {} + + xdg-basedir@5.1.0: {} + + yaml@2.8.2: {} diff --git a/tests/format-value.bats b/tests/format-value.bats new file mode 100644 index 0000000..de975f2 --- /dev/null +++ b/tests/format-value.bats @@ -0,0 +1,60 @@ +#!/usr/bin/env bats + +setup() { + load 'test_helper/common-setup' + _common_setup +} + +@test "n/a input returns n/a" { + run format_value "n/a" + assert_success + assert_output "n/a" +} + +@test "empty input returns n/a" { + run format_value "" + assert_success + assert_output "n/a" +} + +@test "flat json object renders as aligned key:value table" { + run format_value '{"status":"success","check_run_id":123}' + assert_success + assert_line --partial "check_run_id : 123" + assert_line --partial "status : success" +} + +@test "nested json object renders nested values as inline json" { + run format_value '{"name":"test","config":{"debug":true}}' + assert_success + assert_line --partial 'config : {"debug":true}' + assert_line --partial "name : test" +} + +@test "null json values render as empty string" { + run format_value '{"key":null}' + assert_success + assert_line --partial "key : " +} + +@test "json array pretty-prints" { + run format_value '["a","b","c"]' + assert_success + assert_line --partial '"a"' + assert_line --partial '"b"' + assert_line --partial '"c"' +} + +@test "non-json string passes through raw" { + run format_value "just a plain string" + assert_success + assert_output "just a plain string" +} + +@test "jq unavailable falls back to raw output" { + # hide jq from PATH + PATH="/usr/bin:/bin" + run format_value '{"key":"value"}' + assert_success + assert_output '{"key":"value"}' +} diff --git a/tests/full-run.bats b/tests/full-run.bats new file mode 100644 index 0000000..4c02b8a --- /dev/null +++ b/tests/full-run.bats @@ -0,0 +1,75 @@ +#!/usr/bin/env bats + +setup() { + load 'test_helper/common-setup' + _common_setup +} + +set_all_env_vars() { + export GITHUB_ACTOR="testuser" + export TRIGGERING_ACTOR="testuser" + export GITHUB_WORKFLOW="CI" + export GITHUB_WORKFLOW_REF="owner/repo/.github/workflows/ci.yml@refs/heads/main" + export GITHUB_RUN_ID="123456789" + export GITHUB_RUN_NUMBER="42" + export GITHUB_RUN_ATTEMPT="1" + export GITHUB_EVENT_NAME="push" + export EVENT_ACTION="" + export GITHUB_BASE_REF="" + export GITHUB_HEAD_REF="" + export DEFAULT_BRANCH="main" + export GITHUB_REF="refs/heads/main" + export GITHUB_REF_NAME="main" + export GITHUB_SHA="abc1234def5678" + export MATRIX_CONTEXT='{"os":"ubuntu-latest","node":"20"}' + export JOB_CONTEXT='{"status":"success","check_run_id":99999}' + export RUNNER_CONTEXT='{"os":"Linux","arch":"X64","name":"runner-1","environment":"github-hosted"}' + export CALLER_INPUTS='{"deploy":true,"env":"staging"}' + export CALLER_NEEDS='{"some_dep":{"result":"success"}}' + export CALLER_VARS='{"SOME_VAR":"the-value"}' + export EXTRAS='{"custom":"data"}' +} + +@test "exits 0 with all env vars set" { + set_all_env_vars + run "${PROJECT_ROOT}/action.sh" + assert_success +} + +@test "exits 0 with empty/missing env vars" { + unset GITHUB_ACTOR GITHUB_WORKFLOW GITHUB_SHA 2>/dev/null || true + export MATRIX_CONTEXT="" + export JOB_CONTEXT="" + export RUNNER_CONTEXT="" + export CALLER_INPUTS="" + export CALLER_NEEDS="" + export CALLER_VARS="" + export EXTRAS="" + run "${PROJECT_ROOT}/action.sh" + assert_success +} + +@test "exits 0 with garbage input" { + export MATRIX_CONTEXT="not json at all {{{" + export JOB_CONTEXT="nope" + export RUNNER_CONTEXT="12345" + export CALLER_INPUTS="🔥" + export CALLER_NEEDS="" + export CALLER_VARS="" + export EXTRAS="" + run "${PROJECT_ROOT}/action.sh" + assert_success +} + +@test "snapshot: full output matches expected" { + set_all_env_vars + run "${PROJECT_ROOT}/action.sh" + assert_success + + # normalize: strip ansi codes + trailing whitespace per line + local clean + clean="$(strip_ansi "$output" | sed 's/[[:space:]]*$//')" + local expected + expected="$(sed 's/[[:space:]]*$//' "${BATS_TEST_DIRNAME}/snapshots/full-run.expected.txt")" + assert_equal "$clean" "$expected" +} diff --git a/tests/print-section.bats b/tests/print-section.bats new file mode 100644 index 0000000..d4f112b --- /dev/null +++ b/tests/print-section.bats @@ -0,0 +1,33 @@ +#!/usr/bin/env bats + +setup() { + load 'test_helper/common-setup' + _common_setup +} + +@test "output contains title text" { + run print_section "test title" "body text" + assert_success + local clean + clean="$(strip_ansi "$output")" + [[ "$clean" == *"test title"* ]] +} + +@test "output contains box drawing characters" { + run print_section "header" "content" + assert_success + local clean + clean="$(strip_ansi "$output")" + [[ "$clean" == *"┌"* ]] + [[ "$clean" == *"┐"* ]] + [[ "$clean" == *"│"* ]] + [[ "$clean" == *"└"* ]] + [[ "$clean" == *"┘"* ]] + [[ "$clean" == *"─"* ]] +} + +@test "output contains body text" { + run print_section "header" "some body content" + assert_success + assert_output --partial "some body content" +} diff --git a/tests/snapshots/full-run.expected.txt b/tests/snapshots/full-run.expected.txt new file mode 100644 index 0000000..3339647 --- /dev/null +++ b/tests/snapshots/full-run.expected.txt @@ -0,0 +1,53 @@ +┌────────────────┐ +│ github context │ +└────────────────┘ +github.actor : testuser +github.triggering_actor : testuser +github.workflow : CI +github.workflow_ref : owner/repo/.github/workflows/ci.yml@refs/heads/main +github.run_id : 123456789 +github.run_number : 42 +github.run_attempt : 1 +github.event_name : push +github.event.action : +github.base_ref : +github.head_ref : +is_default_branch : true +is_default_target : false +github.ref : refs/heads/main +github.ref_name : main +github.sha : abc1234def5678 +┌────────────────┐ +│ matrix context │ +└────────────────┘ +os : ubuntu-latest +node : 20 +┌─────────────┐ +│ job context │ +└─────────────┘ +status : success +check_run_id : 99999 +┌────────────────┐ +│ runner context │ +└────────────────┘ +os : Linux +arch : X64 +name : runner-1 +environment : github-hosted +┌───────────────┐ +│ caller inputs │ +└───────────────┘ +deploy : true +env : staging +┌──────────────┐ +│ caller needs │ +└──────────────┘ +some_dep : {"result":"success"} +┌─────────────┐ +│ caller vars │ +└─────────────┘ +SOME_VAR : the_value +┌────────┐ +│ extras │ +└────────┘ +custom : data diff --git a/tests/test_helper/common-setup.bash b/tests/test_helper/common-setup.bash new file mode 100644 index 0000000..9c8cd45 --- /dev/null +++ b/tests/test_helper/common-setup.bash @@ -0,0 +1,12 @@ +_common_setup() { + PROJECT_ROOT="$(cd "${BATS_TEST_DIRNAME}/.." && pwd)" + + load "${PROJECT_ROOT}/node_modules/bats-support/load.bash" + load "${PROJECT_ROOT}/node_modules/bats-assert/load.bash" + + source "${PROJECT_ROOT}/action.sh" +} + +strip_ansi() { + perl -pe 's/\e\[[0-9;]*m//g' <<< "$1" +} diff --git a/utility/cspell/cspell.config.json b/utility/cspell/cspell.config.json new file mode 100644 index 0000000..2cfb731 --- /dev/null +++ b/utility/cspell/cspell.config.json @@ -0,0 +1,13 @@ +{ + "language": "en", + "dictionaryDefinitions": [ + { + "name": "dictionary", + "path": "./dictionary.txt" + } + ], + "dictionaries": ["dictionary"], + "words": [], + "allowCompoundWords": true, + "ignorePaths": ["**/pnpm-lock.yaml"] +} diff --git a/utility/cspell/dictionary.txt b/utility/cspell/dictionary.txt new file mode 100644 index 0000000..5d0ef31 --- /dev/null +++ b/utility/cspell/dictionary.txt @@ -0,0 +1,2 @@ +bats +hwrok