mise.toml

  1# SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  2#
  3# SPDX-License-Identifier: CC0-1.0
  4
  5[tools]
  6node = "26"
  7
  8[tasks.fmt]
  9description = "Format all files with Biome"
 10run = "npm run fmt"
 11
 12[tasks.lint]
 13description = "Lint all files with Biome"
 14run = "npm run lint"
 15
 16[tasks.typecheck]
 17description = "Type-check all packages with TypeScript"
 18run = "npm run typecheck"
 19
 20[tasks.check]
 21description = "Format, lint, and type-check"
 22depends = ["fmt", "lint", "typecheck"]
 23
 24[tasks."release:bump"]
 25description = "Bump one or more package versions"
 26usage = '''
 27arg "<version>" help="SemVer increment or exact version"
 28arg "<packages>" help="Package selectors" var=#true var_min=1
 29flag "--preid <preid>" help="Prerelease identifier for pre* increments"
 30'''
 31shell = "bash -c"
 32run = '''
 33set -euo pipefail
 34
 35version=${usage_version:?}
 36preid=${usage_preid:-}
 37eval "packages=(${usage_packages:?})"
 38
 39exact_version_re='^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$'
 40is_exact_version=false
 41if [[ "$version" =~ $exact_version_re ]]; then
 42	is_exact_version=true
 43fi
 44
 45case "$version" in
 46	patch|minor|major|prepatch|preminor|premajor|prerelease) ;;
 47	*)
 48		if [[ "$is_exact_version" != true ]]; then
 49			echo "Error: unsupported version '$version'" >&2
 50			echo "Use patch, minor, major, prepatch, preminor, premajor, prerelease, or an exact SemVer." >&2
 51			exit 1
 52		fi
 53		;;
 54esac
 55
 56if [[ -n "$preid" ]]; then
 57	case "$version" in
 58		prepatch|preminor|premajor|prerelease) ;;
 59		*)
 60			echo "Error: --preid only applies to prepatch, preminor, premajor, or prerelease" >&2
 61			exit 1
 62			;;
 63	esac
 64fi
 65
 66resolved_dirs=$(bash scripts/resolve-release-packages.bash "${packages[@]}")
 67mapfile -t dirs <<< "$resolved_dirs"
 68
 69if [[ "$is_exact_version" == true && -n "${dirs[1]:-}" ]]; then
 70	echo "Error: exact versions may only be applied to one package at a time" >&2
 71	exit 1
 72fi
 73
 74for dir in "${dirs[@]}"; do
 75	args=(version "$version" --no-git-tag-version --workspace "$dir")
 76	if [[ -n "$preid" ]]; then
 77		args+=(--preid "$preid")
 78	fi
 79	echo "Bumping $dir"
 80	npm "${args[@]}"
 81done
 82'''
 83
 84[tasks."release:pack"]
 85description = "Check and dry-run npm package packing"
 86usage = '''
 87arg "<packages>" help="Package selectors" var=#true var_min=1
 88'''
 89shell = "bash -c"
 90run = '''
 91set -euo pipefail
 92
 93eval "packages=(${usage_packages:?})"
 94resolved_dirs=$(bash scripts/resolve-release-packages.bash "${packages[@]}")
 95mapfile -t dirs <<< "$resolved_dirs"
 96
 97mise run check
 98
 99for dir in "${dirs[@]}"; do
100	echo "Packing $dir (dry run)"
101	npm pack --dry-run "./$dir"
102done
103'''
104
105[tasks."release:publish"]
106description = "Check, dry-run, and publish npm packages"
107usage = '''
108arg "<packages>" help="Package selectors" var=#true var_min=1
109flag "--tag <tag>" help="npm dist-tag" default="latest"
110flag "--otp <otp>" help="One-time password for npm two-factor auth"
111'''
112shell = "bash -c"
113run = '''
114set -euo pipefail
115
116package_version() {
117	node -e 'const fs = require("node:fs"); const path = require("node:path"); const pkg = JSON.parse(fs.readFileSync(path.join(process.argv[1], "package.json"), "utf8")); console.log(pkg.version);' "$1"
118}
119
120eval "packages=(${usage_packages:?})"
121tag=${usage_tag:?}
122otp=${usage_otp:-}
123resolved_dirs=$(bash scripts/resolve-release-packages.bash "${packages[@]}")
124mapfile -t dirs <<< "$resolved_dirs"
125
126if [[ -n "$otp" && -n "${dirs[1]:-}" ]]; then
127	echo "Error: --otp may only be used with one package at a time" >&2
128	echo "Use an npm automation token for multi-package publishing, or publish each package separately with a fresh OTP." >&2
129	exit 1
130fi
131
132for dir in "${dirs[@]}"; do
133	version=$(package_version "$dir")
134	if [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+- && "$tag" == latest ]]; then
135		echo "Error: refusing to publish prerelease $dir@$version with tag latest" >&2
136		echo "Use --tag beta or another prerelease dist-tag." >&2
137		exit 1
138	fi
139done
140
141mise run check
142
143publish_args=(--access public --tag "$tag")
144if [[ -n "$otp" ]]; then
145	publish_args+=(--otp "$otp")
146fi
147
148for dir in "${dirs[@]}"; do
149	echo "Publishing $dir (dry run)"
150	npm publish --dry-run "${publish_args[@]}" "./$dir"
151done
152
153for dir in "${dirs[@]}"; do
154	echo "Publishing $dir"
155	npm publish "${publish_args[@]}" "./$dir"
156done
157'''