From 2e21cf715442f425a524b8dd47d8f05cb1414e0e Mon Sep 17 00:00:00 2001 From: Mirek Rusin Date: Sat, 29 Aug 2026 21:17:14 +0200 Subject: [PATCH] Rename packages to @mirek/throwscript-*; add CI and changesets publishing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - @throwscript/core → @mirek/throwscript-core, throwscript → @mirek/throwscript-cli (the bin is still `throwscript`); manifests gain repository/homepage/bugs, keywords, engines and publishConfig - CLI reads its version from package.json so changeset bumps propagate - .github/workflows/ci.yml: changeset-required job on PRs, verify matrix on Node 20/22/24 (build, lint, test, pack check), aggregate CI job - .github/workflows/publish.yml: changesets/action opens the version PR while changesets are pending, otherwise verifies and publishes via OIDC trusted publishing with provenance - .changeset/: config (both packages released in lockstep), README, and the changeset for this change - scripts/pack-check.mjs: packs both packages, installs the tarballs into a throwaway consumer and exercises the bin and the core API - root scripts: pack:check, verify, changeset, version-packages, release:publish Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01QswtWoNc2nD627xnAp7ZsV --- .changeset/README.md | 45 ++ .changeset/config.json | 15 + .changeset/rename-and-ci.md | 6 + .github/workflows/ci.yml | 95 ++++ .github/workflows/publish.yml | 79 ++++ README.md | 11 +- package.json | 8 +- packages/cli/package.json | 33 +- packages/cli/src/main.ts | 5 +- packages/core/package.json | 31 +- pnpm-lock.yaml | 795 +++++++++++++++++++++++++++++++++- scripts/pack-check.mjs | 98 +++++ 12 files changed, 1205 insertions(+), 16 deletions(-) create mode 100644 .changeset/README.md create mode 100644 .changeset/config.json create mode 100644 .changeset/rename-and-ci.md create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/publish.yml create mode 100644 scripts/pack-check.mjs diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 0000000..04b3e80 --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,45 @@ +# Changesets + +Every pull request adds one markdown file here instead of editing package versions — +uniquely named files never conflict between concurrent pull requests. Format: + +```md +--- +"@mirek/throwscript-core": minor +"@mirek/throwscript-cli": minor +--- + +One-line summary of the change. +``` + +The two packages are released in lockstep (`fixed` in `config.json`): naming either one +bumps both to the same version. Pick the bump the change needs: + +- `patch` — fixes and documentation; +- `minor` — new features; +- `major` — breaking changes. + +A pull request that changes nothing publishable (CI, scripts, repository docs) still needs a +file, so that nothing is ever forgotten: run `pnpm changeset --empty`. + +## How a release happens + +1. Merged changesets accumulate on `main`. The **Publish** workflow + (`.github/workflows/publish.yml`) opens or updates the `chore(release): version packages` + pull request (branch `changeset-release/main`), which runs `pnpm version-packages`: + `changeset version` bumps the packages, prepends their `CHANGELOG.md` entries, and deletes + the consumed files. +2. Merging that pull request leaves `main` with no pending changesets, so the same workflow + runs `pnpm verify` and then `pnpm release:publish` (`changeset publish`): every package + whose version is not yet on npm is published with provenance and tagged + `@`. Packages already on npm are skipped, so a failed run is simply + re-run. + +npm authentication is OIDC trusted publishing: each `@mirek/throwscript-*` package lists this +repository and the workflow file name `publish.yml` as its trusted publisher on npmjs.com, so +do not rename the workflow file. A brand-new package cannot use trusted publishing for its +first release — publish it once from a maintainer machine (`npm login`, then +`pnpm build && pnpm release:publish`), add the trusted publisher on npmjs.com, and re-run the +workflow. + +Do not run `npm version` or `pnpm publish` in individual packages by hand. diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 0000000..8cdf59d --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@3.1.4/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [["@mirek/throwscript-core", "@mirek/throwscript-cli"]], + "linked": [], + "access": "public", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "ignore": [], + "privatePackages": { + "version": false, + "tag": false + } +} diff --git a/.changeset/rename-and-ci.md b/.changeset/rename-and-ci.md new file mode 100644 index 0000000..17a525a --- /dev/null +++ b/.changeset/rename-and-ci.md @@ -0,0 +1,6 @@ +--- +"@mirek/throwscript-core": minor +"@mirek/throwscript-cli": minor +--- + +Rename packages to `@mirek/throwscript-core` and `@mirek/throwscript-cli` (the bin is still `throwscript`); the CLI reports the version from its package manifest. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..97ec8e8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,95 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + # Every PR must add a changeset (see .changeset/README.md). The automated + # version packages PR is the one exception: it consumes changesets. + changeset: + name: Changeset + if: github.event_name == 'pull_request' && !startsWith(github.head_ref, 'changeset-release/') + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Require a changeset + run: | + added="$(git diff --name-only --diff-filter=A "origin/${{ github.base_ref }}...HEAD" -- '.changeset/*.md' | grep -v '^\.changeset/README\.md$' || true)" + if [ -z "$added" ]; then + echo "::error::This PR adds no changeset. Run \`pnpm changeset\` (or \`pnpm changeset --empty\` for a change that publishes nothing) and commit the file under .changeset/." + exit 1 + fi + echo "changesets added:" + echo "$added" + + verify: + name: Verify (Node ${{ matrix.node }}) + runs-on: ubuntu-latest + timeout-minutes: 15 + defaults: + run: + # GitHub's default shell runs `bash -e` without pipefail, so + # `pnpm X | tee X.log` would report success whatever X did. + shell: bash + strategy: + fail-fast: false + matrix: + node: + - 20 + - 22 + - 24 + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + cache: pnpm + + - run: pnpm install --frozen-lockfile + - name: Build + run: pnpm build 2>&1 | tee build.log + - name: Lint + run: pnpm lint 2>&1 | tee lint.log + - name: Test + run: pnpm -r test 2>&1 | tee test.log + - name: Validate tarballs + run: pnpm pack:check 2>&1 | tee pack-check.log + + - name: Upload failure diagnostics + if: failure() + uses: actions/upload-artifact@v4 + with: + name: diagnostics-node-${{ matrix.node }} + path: '*.log' + retention-days: 1 + + ci: + name: CI + if: always() + needs: + - changeset + - verify + runs-on: ubuntu-latest + steps: + - name: Require all verification jobs + # The changeset job is skipped on pushes to main and on the version packages PR. + run: | + test "${{ needs.verify.result }}" = success + case "${{ needs.changeset.result }}" in success|skipped) ;; *) exit 1 ;; esac diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..7449210 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,79 @@ +name: Publish + +# Changesets release automation. On every push to main: +# - pending .changeset/*.md files → opens/updates the +# `chore(release): version packages` PR (branch changeset-release/main); +# - no pending changesets → runs the full verification gate, then +# `changeset publish`, which publishes every package whose version is not +# on npm yet (pnpm publish, so `workspace:*` ranges are rewritten) and +# tags it @. A no-op when everything is published. +# +# npm auth is OIDC trusted publishing (id-token: write) — no npm token. +# Each @mirek/throwscript-* package must have this repo + THIS WORKFLOW +# FILENAME (publish.yml) configured as a trusted publisher on npmjs.com, so do +# not rename this file. A brand-new package cannot use trusted publishing for +# its first release — see .changeset/README.md. + +on: + push: + branches: + - main + +permissions: + contents: write # push the changeset-release branch and the @ tags + pull-requests: write # open/update the version packages PR + id-token: write # npm OIDC trusted publishing + +concurrency: + group: publish-main + cancel-in-progress: false # never cancel a run that may be mid-publish + +jobs: + release: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: pnpm/action-setup@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 24 + registry-url: https://registry.npmjs.org + package-manager-cache: false # never use caching in release builds + + - run: pnpm install --frozen-lockfile + + - name: Detect pending changesets + id: pending + run: | + if git ls-files '.changeset/*.md' | grep -v '^\.changeset/README\.md$' | grep -q .; then + echo "changesets=true" >> "$GITHUB_OUTPUT" + else + echo "changesets=false" >> "$GITHUB_OUTPUT" + fi + + # Publishing ships the exact checked-out commit, so it runs the complete + # verification and installed-tarball gate first, whatever CI said elsewhere. + - name: Verify before publishing + if: steps.pending.outputs.changesets == 'false' + run: pnpm verify + + # Note: the version packages PR is opened with GITHUB_TOKEN, so CI does + # not run on it automatically (GitHub suppresses workflows for events + # created by the default token). Its diff is versions and changelogs + # only; CI runs on main after merge, and the publish path above verifies + # before anything ships. + - uses: changesets/action@v1 + with: + version: pnpm version-packages + publish: pnpm release:publish + commit: 'chore(release): version packages' + title: 'chore(release): version packages' + createGithubReleases: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_CONFIG_PROVENANCE: 'true' diff --git a/README.md b/README.md index fe17891..d77186d 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,11 @@ export async function fetchUser(id: string): Promise { ## Usage +```sh +pnpm add -D @mirek/throwscript-cli # installs the `throwscript` bin +# or run without installing: npx @mirek/throwscript-cli +``` + ```sh # check every file in the tsconfig.json project in the current directory throwscript @@ -200,8 +205,8 @@ subclasses. | Package | Description | | --- | --- | -| [`@throwscript/core`](packages/core) | The analyzer: walks a `ts.Program` and returns structured diagnostics | -| [`throwscript`](packages/cli) | The CLI wrapper | +| [`@mirek/throwscript-core`](packages/core) | The analyzer: walks a `ts.Program` and returns structured diagnostics | +| [`@mirek/throwscript-cli`](packages/cli) | The `throwscript` command-line tool | ## Development @@ -221,7 +226,7 @@ import { analyzeProject, formatDiagnostic, formatReport, -} from "@throwscript/core"; +} from "@mirek/throwscript-core"; const diagnostics = analyzeProject("tsconfig.json", { ignoreExternal: true, diff --git a/package.json b/package.json index eca14f3..4a58e72 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,12 @@ "build": "tsc -b packages/core packages/cli", "lint": "oxlint .", "test": "pnpm run build && pnpm -r run test", - "check": "pnpm run build && pnpm run lint && pnpm run test" + "pack:check": "node scripts/pack-check.mjs", + "check": "pnpm run build && pnpm run lint && pnpm run test", + "verify": "pnpm run check && pnpm run pack:check", + "changeset": "changeset", + "version-packages": "changeset version", + "release:publish": "changeset publish" }, "packageManager": "pnpm@10.33.0", "pnpm": { @@ -18,6 +23,7 @@ "node": ">=20" }, "devDependencies": { + "@changesets/cli": "^2.29.0", "oxlint": "^1.72.0", "typescript": "^5.9.3" } diff --git a/packages/cli/package.json b/packages/cli/package.json index cfd7087..765d229 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,9 +1,19 @@ { - "name": "throwscript", + "name": "@mirek/throwscript-cli", "version": "0.4.0", - "description": "Linter-like checker: every function that can throw must document it with JSDoc @throws", - "type": "module", + "description": "Linter-like CLI: every function that can throw must document it with JSDoc @throws.", + "keywords": [ + "throwscript", + "throws", + "jsdoc", + "typescript", + "linter", + "exceptions", + "errors" + ], + "author": "Mirek Rusin (https://github.com/mirek)", "license": "MIT", + "type": "module", "bin": { "throwscript": "./dist/main.js" }, @@ -16,7 +26,7 @@ "test": "node --import tsx --test test/*.test.ts" }, "dependencies": { - "@throwscript/core": "workspace:*" + "@mirek/throwscript-core": "workspace:*" }, "peerDependencies": { "typescript": ">=5.5.0 <7" @@ -25,5 +35,18 @@ "@types/node": "^22.0.0", "tsx": "^4.19.0", "typescript": "^5.9.3" - } + }, + "engines": { + "node": ">=20" + }, + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/mirek/throwscript.git", + "directory": "packages/cli" + }, + "homepage": "https://github.com/mirek/throwscript/tree/main/packages/cli#readme", + "bugs": "https://github.com/mirek/throwscript/issues" } diff --git a/packages/cli/src/main.ts b/packages/cli/src/main.ts index 8e32a45..1c1a27a 100644 --- a/packages/cli/src/main.ts +++ b/packages/cli/src/main.ts @@ -1,5 +1,6 @@ #!/usr/bin/env node import { existsSync, writeFileSync } from "node:fs"; +import { createRequire } from "node:module"; import path from "node:path"; import process from "node:process"; import { @@ -10,9 +11,9 @@ import { formatReport, type AnalyzeOptions, type ThrowsDiagnostic, -} from "@throwscript/core"; +} from "@mirek/throwscript-core"; -const VERSION = "0.4.0"; +const VERSION = (createRequire(import.meta.url)("../package.json") as { version: string }).version; const HELP = `throwscript — assert every function that can throw has a JSDoc @throws tag diff --git a/packages/core/package.json b/packages/core/package.json index d5c880c..625c9d0 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,9 +1,19 @@ { - "name": "@throwscript/core", + "name": "@mirek/throwscript-core", "version": "0.4.0", - "description": "Checker that asserts every function that can throw documents it with a JSDoc @throws tag", - "type": "module", + "description": "Analyzer asserting every TypeScript function that can throw documents it with a JSDoc @throws tag.", + "keywords": [ + "throwscript", + "throws", + "jsdoc", + "typescript", + "linter", + "exceptions", + "errors" + ], + "author": "Mirek Rusin (https://github.com/mirek)", "license": "MIT", + "type": "module", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { @@ -26,5 +36,18 @@ "@types/node": "^22.0.0", "tsx": "^4.19.0", "typescript": "^5.9.3" - } + }, + "engines": { + "node": ">=20" + }, + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/mirek/throwscript.git", + "directory": "packages/core" + }, + "homepage": "https://github.com/mirek/throwscript/tree/main/packages/core#readme", + "bugs": "https://github.com/mirek/throwscript/issues" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2d0cbe3..81e1a80 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: devDependencies: + '@changesets/cli': + specifier: ^2.29.0 + version: 2.31.1(@types/node@22.20.0) oxlint: specifier: ^1.72.0 version: 1.72.0 @@ -17,7 +20,7 @@ importers: packages/cli: dependencies: - '@throwscript/core': + '@mirek/throwscript-core': specifier: workspace:* version: link:../core devDependencies: @@ -45,6 +48,65 @@ importers: packages: + '@babel/runtime@7.29.7': + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} + engines: {node: '>=6.9.0'} + + '@changesets/apply-release-plan@7.1.1': + resolution: {integrity: sha512-9qPCm/rLx/xoOFXIHGB229+4GOL76S4MC+7tyOuTsR6+1jYlfFDQORdvwR5hDA6y4FL2BPt3qpbcQIS+dW85LA==} + + '@changesets/assemble-release-plan@6.0.10': + resolution: {integrity: sha512-rSDcqdJ9KbVyjpBIuCidhvZNIiVt1XaIYp73ycVQRIA5n/j6wQaEk0ChRLMUQ1vkxZe51PTQ9OIhbg6HQMW45A==} + + '@changesets/changelog-git@0.2.1': + resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} + + '@changesets/cli@2.31.1': + resolution: {integrity: sha512-uO05WTcRBwuVOJVSW8Cmpqw6q0WDL53ajGCMyszutvOe5toOnunbpM4jZzf+qxBOz7i0AzopZ8diBuewjmF40w==} + hasBin: true + + '@changesets/config@3.1.4': + resolution: {integrity: sha512-pf0bvD/v6WI2cRlZ6hzpjtZdSlXDXMAJ+Iz7xfFzV4ZxJ8OGGAON+1qYc99ZPrijnt4xp3VGG7eNvAOGS24V1Q==} + + '@changesets/errors@0.2.0': + resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} + + '@changesets/get-dependents-graph@2.1.4': + resolution: {integrity: sha512-ZsS00x6WvmHq3sQv8oCMwL0f/z3wbXCVuSVTJwCnnmbC/iBdNJGFx1EcbMG4PC6sXRyH69liM4A2WKXzn/kRPg==} + + '@changesets/get-release-plan@4.0.16': + resolution: {integrity: sha512-2K5Om6CrMPm45rtvckfzWo7e9jOVCKLCnXia5eUPaURH7/LWzri7pK1TycdzAuAtehLkW7VPbWLCSExTHmiI6g==} + + '@changesets/get-version-range-type@0.4.0': + resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} + + '@changesets/git@3.0.4': + resolution: {integrity: sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==} + + '@changesets/logger@0.1.1': + resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} + + '@changesets/parse@0.4.3': + resolution: {integrity: sha512-ZDmNc53+dXdWEv7fqIUSgRQOLYoUom5Z40gmLgmATmYR9NbL6FJJHwakcCpzaeCy+1D0m0n7mT4jj2B/MQPl7A==} + + '@changesets/pre@2.0.2': + resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==} + + '@changesets/read@0.6.7': + resolution: {integrity: sha512-D1G4AUYGrBEk8vj8MGwf75k9GpN6XL3wg8i42P2jZZwFLXnlr2Pn7r9yuQNbaMCarP7ZQWNJbV6XLeysAIMhTA==} + + '@changesets/should-skip-package@0.1.2': + resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==} + + '@changesets/types@4.1.0': + resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} + + '@changesets/types@6.1.0': + resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==} + + '@changesets/write@0.4.0': + resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} + '@esbuild/aix-ppc64@0.28.1': resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} engines: {node: '>=18'} @@ -201,6 +263,33 @@ packages: cpu: [x64] os: [win32] + '@inquirer/external-editor@1.0.3': + resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@manypkg/find-root@1.1.0': + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + + '@manypkg/get-packages@1.1.3': + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + '@oxlint/binding-android-arm-eabi@1.72.0': resolution: {integrity: sha512-zhCmvn+1Mj3UchAc/90i99S0t7jJUsHmFVSPg4UWrjO8b8eaSGwscgO6QAUtvHBstkjQwBttQNswEnAF1mIQdA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -323,19 +412,177 @@ packages: cpu: [x64] os: [win32] + '@types/node@12.20.55': + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + '@types/node@22.20.0': resolution: {integrity: sha512-QWlFW2wf3nTjC13/DqRnBpR4ZO36VJH/JVBkA/vcnmbTBNQIlnObqyqZE1tUR7+Ni23Lda8R1BxMfbXRpCUx5g==} + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + better-path-resolve@1.0.0: + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} + engines: {node: '>=4'} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + chardet@2.2.0: + resolution: {integrity: sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + esbuild@0.28.1: resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} engines: {node: '>=18'} hasBin: true + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + extendable-error@0.1.7: + resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fastq@1.20.3: + resolution: {integrity: sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + human-id@4.2.1: + resolution: {integrity: sha512-zPGsiS+dWoTZtZ4AtpA9Y+BdSFSNWvnouNlWNoUFyAM6xHOHmdCvqO3k8AIbdamCOv4gUFUVNPf6rJFfc4UiJw==} + hasBin: true + + iconv-lite@0.7.3: + resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} + engines: {node: '>=0.10.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-subdir@1.2.0: + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} + engines: {node: '>=4'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + js-yaml@3.15.2: + resolution: {integrity: sha512-6EuL879VkRA+1Cz578mKMiKvjPNEuk6+r1JaFzoSWejZmtf7xWbIyw1e3KkxlkzTIt9Taw6JBhEppG7utc1P+w==} + hasBin: true + + js-yaml@4.3.2: + resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} + hasBin: true + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + + outdent@0.5.0: + resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + oxlint@1.72.0: resolution: {integrity: sha512-1rhdZIP/EvoI91ABIwNU5Q8+bWf8mjrS5UzIOZld4d4bXxJvtlUhlQvaoTogIGin/qdErMOrwaIJvCSIAKTLhA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -349,6 +596,124 @@ packages: vite-plus: optional: true + p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-manager-detector@0.2.11: + resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + quansync@0.2.11: + resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + read-yaml-file@1.1.0: + resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} + engines: {node: '>=6'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + spawndamnit@3.0.1: + resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + term-size@2.2.1: + resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} + engines: {node: '>=8'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + tsx@4.23.0: resolution: {integrity: sha512-eUdUIaCr963q2h5u3+QwvYp0+eqPvn+egeqZUm0hwERCqqx1E3kK5ehbGCvqSE5MQAULr67ww0cA3jKc3YkM1w==} engines: {node: '>=18.0.0'} @@ -362,8 +727,162 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + snapshots: + '@babel/runtime@7.29.7': {} + + '@changesets/apply-release-plan@7.1.1': + dependencies: + '@changesets/config': 3.1.4 + '@changesets/get-version-range-type': 0.4.0 + '@changesets/git': 3.0.4 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + detect-indent: 6.1.0 + fs-extra: 7.0.1 + lodash.startcase: 4.4.0 + outdent: 0.5.0 + prettier: 2.8.8 + resolve-from: 5.0.0 + semver: 7.8.5 + + '@changesets/assemble-release-plan@6.0.10': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.4 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + semver: 7.8.5 + + '@changesets/changelog-git@0.2.1': + dependencies: + '@changesets/types': 6.1.0 + + '@changesets/cli@2.31.1(@types/node@22.20.0)': + dependencies: + '@changesets/apply-release-plan': 7.1.1 + '@changesets/assemble-release-plan': 6.0.10 + '@changesets/changelog-git': 0.2.1 + '@changesets/config': 3.1.4 + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.4 + '@changesets/get-release-plan': 4.0.16 + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.7 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@changesets/write': 0.4.0 + '@inquirer/external-editor': 1.0.3(@types/node@22.20.0) + '@manypkg/get-packages': 1.1.3 + ansi-colors: 4.1.3 + enquirer: 2.4.1 + fs-extra: 7.0.1 + mri: 1.2.0 + package-manager-detector: 0.2.11 + picocolors: 1.1.1 + resolve-from: 5.0.0 + semver: 7.8.5 + spawndamnit: 3.0.1 + term-size: 2.2.1 + transitivePeerDependencies: + - '@types/node' + + '@changesets/config@3.1.4': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.4 + '@changesets/logger': 0.1.1 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + micromatch: 4.0.8 + + '@changesets/errors@0.2.0': + dependencies: + extendable-error: 0.1.7 + + '@changesets/get-dependents-graph@2.1.4': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + picocolors: 1.1.1 + semver: 7.8.5 + + '@changesets/get-release-plan@4.0.16': + dependencies: + '@changesets/assemble-release-plan': 6.0.10 + '@changesets/config': 3.1.4 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.7 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/get-version-range-type@0.4.0': {} + + '@changesets/git@3.0.4': + dependencies: + '@changesets/errors': 0.2.0 + '@manypkg/get-packages': 1.1.3 + is-subdir: 1.2.0 + micromatch: 4.0.8 + spawndamnit: 3.0.1 + + '@changesets/logger@0.1.1': + dependencies: + picocolors: 1.1.1 + + '@changesets/parse@0.4.3': + dependencies: + '@changesets/types': 6.1.0 + js-yaml: 4.3.2 + + '@changesets/pre@2.0.2': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + + '@changesets/read@0.6.7': + dependencies: + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/parse': 0.4.3 + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + p-filter: 2.1.0 + picocolors: 1.1.1 + + '@changesets/should-skip-package@0.1.2': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/types@4.1.0': {} + + '@changesets/types@6.1.0': {} + + '@changesets/write@0.4.0': + dependencies: + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + human-id: 4.2.1 + prettier: 2.8.8 + '@esbuild/aix-ppc64@0.28.1': optional: true @@ -442,6 +961,41 @@ snapshots: '@esbuild/win32-x64@0.28.1': optional: true + '@inquirer/external-editor@1.0.3(@types/node@22.20.0)': + dependencies: + chardet: 2.2.0 + iconv-lite: 0.7.3 + optionalDependencies: + '@types/node': 22.20.0 + + '@manypkg/find-root@1.1.0': + dependencies: + '@babel/runtime': 7.29.7 + '@types/node': 12.20.55 + find-up: 4.1.0 + fs-extra: 8.1.0 + + '@manypkg/get-packages@1.1.3': + dependencies: + '@babel/runtime': 7.29.7 + '@changesets/types': 4.1.0 + '@manypkg/find-root': 1.1.0 + fs-extra: 8.1.0 + globby: 11.1.0 + read-yaml-file: 1.1.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.3 + '@oxlint/binding-android-arm-eabi@1.72.0': optional: true @@ -499,10 +1053,51 @@ snapshots: '@oxlint/binding-win32-x64-msvc@1.72.0': optional: true + '@types/node@12.20.55': {} + '@types/node@22.20.0': dependencies: undici-types: 6.21.0 + ansi-colors@4.1.3: {} + + ansi-regex@5.0.1: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + array-union@2.1.0: {} + + better-path-resolve@1.0.0: + dependencies: + is-windows: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + chardet@2.2.0: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + detect-indent@6.1.0: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + esbuild@0.28.1: optionalDependencies: '@esbuild/aix-ppc64': 0.28.1 @@ -532,9 +1127,115 @@ snapshots: '@esbuild/win32-ia32': 0.28.1 '@esbuild/win32-x64': 0.28.1 + esprima@4.0.1: {} + + extendable-error@0.1.7: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fastq@1.20.3: + dependencies: + reusify: 1.1.0 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + fsevents@2.3.3: optional: true + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + graceful-fs@4.2.11: {} + + human-id@4.2.1: {} + + iconv-lite@0.7.3: + dependencies: + safer-buffer: 2.1.2 + + ignore@5.3.2: {} + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-subdir@1.2.0: + dependencies: + better-path-resolve: 1.0.0 + + is-windows@1.0.2: {} + + isexe@2.0.0: {} + + js-yaml@3.15.2: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.3.2: + dependencies: + argparse: 2.0.1 + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + lodash.startcase@4.4.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + + mri@1.2.0: {} + + outdent@0.5.0: {} + oxlint@1.72.0: optionalDependencies: '@oxlint/binding-android-arm-eabi': 1.72.0 @@ -557,6 +1258,92 @@ snapshots: '@oxlint/binding-win32-ia32-msvc': 1.72.0 '@oxlint/binding-win32-x64-msvc': 1.72.0 + p-filter@2.1.0: + dependencies: + p-map: 2.1.0 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-map@2.1.0: {} + + p-try@2.2.0: {} + + package-manager-detector@0.2.11: + dependencies: + quansync: 0.2.11 + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-type@4.0.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.2: {} + + pify@4.0.1: {} + + prettier@2.8.8: {} + + quansync@0.2.11: {} + + queue-microtask@1.2.3: {} + + read-yaml-file@1.1.0: + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.15.2 + pify: 4.0.1 + strip-bom: 3.0.0 + + resolve-from@5.0.0: {} + + reusify@1.1.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safer-buffer@2.1.2: {} + + semver@7.8.5: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@4.1.0: {} + + slash@3.0.0: {} + + spawndamnit@3.0.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + sprintf-js@1.0.3: {} + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-bom@3.0.0: {} + + term-size@2.2.1: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + tsx@4.23.0: dependencies: esbuild: 0.28.1 @@ -566,3 +1353,9 @@ snapshots: typescript@5.9.3: {} undici-types@6.21.0: {} + + universalify@0.1.2: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 diff --git a/scripts/pack-check.mjs b/scripts/pack-check.mjs new file mode 100644 index 0000000..8686c1d --- /dev/null +++ b/scripts/pack-check.mjs @@ -0,0 +1,98 @@ +// Packs every workspace package and installs the tarballs into a throwaway +// consumer project, then checks what a user would actually get: no +// `workspace:` ranges leaked into the manifests, no source/test files in the +// tarball, the `throwscript` bin runs, and the core package imports. +import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { spawnSync } from 'node:child_process' +import { fileURLToPath } from 'node:url' +import path from 'node:path' + +const pnpmCli = process.env.npm_execpath +if (!pnpmCli) throw new Error('pack-check must be run through pnpm') + +const root = fileURLToPath(new URL('..', import.meta.url)) +const packageDirectories = ['packages/core', 'packages/cli'].map(p => path.join(root, p)) + +function run(command, args, options = {}) { + const result = spawnSync(command, args, { encoding: 'utf8', ...options }) + if (result.error) throw result.error + if (result.status !== 0) { + process.stdout.write(result.stdout ?? '') + process.stderr.write(result.stderr ?? '') + throw new Error(`${command} ${args.join(' ')} failed with status ${result.status}`) + } + return result +} + +const pnpm = (args, cwd) => run(process.execPath, [pnpmCli, ...args], { cwd }) + +const temporaryDirectory = mkdtempSync(path.join(tmpdir(), 'throwscript-pack-check-')) +const consumer = path.join(temporaryDirectory, 'consumer') + +try { + const tarballs = new Map() + for (const directory of packageDirectories) { + const manifest = JSON.parse(readFileSync(path.join(directory, 'package.json'), 'utf8')) + console.log(`pack-check ${manifest.name}`) + const destination = path.join(temporaryDirectory, path.basename(directory)) + const report = JSON.parse(pnpm(['pack', '--pack-destination', destination, '--json'], directory).stdout) + const packed = Array.isArray(report) ? report[0] : report + const files = packed.files.map(f => (typeof f === 'string' ? f : f.path).replace(/^package\//, '')) + const tarball = path.join(destination, path.basename(packed.filename)) + + const forbidden = files.filter(f => /^(src|test)\//.test(f) || /tsconfig.*\.json$/.test(f)) + if (forbidden.length > 0) { + throw new Error(`${manifest.name} packs development-only files:\n${forbidden.join('\n')}`) + } + if (!files.includes('dist/index.js') && !files.includes('dist/main.js')) { + throw new Error(`${manifest.name} packs no built entry point`) + } + const packedManifest = JSON.parse(run('tar', ['-xOf', tarball, 'package/package.json']).stdout) + for (const field of ['dependencies', 'peerDependencies', 'optionalDependencies']) { + for (const [name, range] of Object.entries(packedManifest[field] ?? {})) { + if (String(range).startsWith('workspace:')) { + throw new Error(`${manifest.name} retains ${field}.${name}=${range} in its tarball`) + } + } + } + tarballs.set(manifest.name, tarball) + } + + const dependencies = Object.fromEntries( + [...tarballs].map(([name, tarball]) => [name, `file:${path.relative(consumer, tarball)}`]) + ) + run('mkdir', ['-p', consumer]) + writeFileSync(path.join(consumer, 'package.json'), JSON.stringify({ + name: 'throwscript-consumer', + private: true, + type: 'module', + dependencies: { ...dependencies, typescript: '^5.9.3' } + }, null, 2)) + // Route the CLI's dependency on core to the local tarball as well. + writeFileSync( + path.join(consumer, 'pnpm-workspace.yaml'), + `overrides:\n${Object.entries(dependencies).map(([n, t]) => ` '${n}': '${t}'\n`).join('')}` + ) + pnpm(['install', '--ignore-scripts', '--no-frozen-lockfile'], consumer) + + writeFileSync(path.join(consumer, 'sample.ts'), 'export function boom(): void {\n throw new Error("x");\n}\n') + const version = pnpm(['exec', 'throwscript', '--version'], consumer).stdout.trim() + if (!/^throwscript \d+\.\d+\.\d+/.test(version)) throw new Error(`unexpected --version output: ${version}`) + + const check = spawnSync(process.execPath, [pnpmCli, 'exec', 'throwscript', 'sample.ts'], { cwd: consumer, encoding: 'utf8' }) + if (check.status !== 1 || !/'boom' can throw \{Error\}/.test(check.stdout)) { + throw new Error(`throwscript did not report the sample throw (status ${check.status}):\n${check.stdout}${check.stderr}`) + } + + writeFileSync( + path.join(consumer, 'api.mjs'), + 'import { analyzeFiles, formatReport } from "@mirek/throwscript-core";\n' + + 'const d = analyzeFiles(["sample.ts"]);\n' + + 'if (d.length !== 1 || !formatReport(d).includes("boom")) throw new Error("core API check failed");\n' + ) + run(process.execPath, ['api.mjs'], { cwd: consumer }) + console.log('pack-check ok') +} finally { + rmSync(temporaryDirectory, { recursive: true, force: true }) +}