ktx/packages/cli/src/update-check/channel.ts
Andrey Avtomonov 698efdcef8
feat(cli): add channel-aware update notifier (#265)
* feat(cli): show cached update notices after commands

* docs(cli): describe update notices

* fix(cli): type update check environment

* fix(cli): decouple update notice display from refresh and harden suppression

Display a cached "update available" notice based solely on the lastNoticeAt
24h throttle, independent of checkedAt refresh freshness, matching the design's
independent display/refresh decisions. Suppress the check unconditionally under
--json, CI, and non-TTY before consulting output-mode preferences, so a
KTX_OUTPUT=pretty override can no longer make CI/non-TTY contexts phone npm.
2026-06-06 10:42:10 +02:00

43 lines
1.1 KiB
TypeScript

import semver from 'semver';
export type UpdateChannel = 'latest' | 'next';
export type UpdateDecision =
| { status: 'skip' }
| { status: 'upToDate'; channel: UpdateChannel; target: string }
| { status: 'available'; channel: UpdateChannel; target: string };
/** @internal */
export function inferUpdateChannel(installed: string): UpdateChannel | null {
const parsed = semver.parse(installed);
if (!parsed || installed === '0.0.0') {
return null;
}
const [prereleaseId] = parsed.prerelease;
if (prereleaseId === undefined) {
return 'latest';
}
if (prereleaseId === 'rc') {
return 'next';
}
return null;
}
export function decideUpdate(installed: string, distTags: Record<string, string>): UpdateDecision {
const channel = inferUpdateChannel(installed);
if (!channel || !semver.valid(installed)) {
return { status: 'skip' };
}
const target = distTags[channel];
if (!target || !semver.valid(target)) {
return { status: 'skip' };
}
if (semver.gt(target, installed)) {
return { status: 'available', channel, target };
}
return { status: 'upToDate', channel, target };
}