import type { EnvironmentName } from '../config/environments.js'; /** Which published line a build came from: a prerelease was installed from `@bitmagic/cli@dev`. */ export type UpdateTag = 'latest' | 'dev'; /** * The npm dist-tag a running version was installed from. * * The publish script derives the tag from the version with exactly this rule * (.github/scripts/publish-npm-package.sh), so a prerelease is on `dev` by construction and the * two ends cannot drift. Asking `latest` on behalf of a dev build would report the production * release as "newer" for half a patch cycle and never mention the dev build that fixes things. */ export declare function updateTagFor(version: string): UpdateTag; /** * How to install the line a build is already on, from scratch, with npm. * * Now only for the cases that genuinely mean a FIRST install — the README, the portal's /pro page, * and `reset-account`'s "start over where a new creator starts" — where there is no bitmagic on * the machine to run anything. Everything that updates an EXISTING install names * `SELF_UPDATE_COMMAND` instead, for the reason spelled out there. */ export declare function installCommandFor(tag: UpdateTag): string; /** * What every update nudge names, and the one command that reliably lands. * * A printed `npm i -g` is run by whatever `npm` the reading shell resolves, which on a machine * using nvm is routinely not the one that owns this install: a coding agent's non-interactive * shell sources no profile, nvm never loads, and the install goes to a prefix nobody's PATH points * at while npm reports success. `bitmagic self-update` resolves its own install from * `process.execPath` and asks the shell nothing (see update/self-install.ts). * * Naming a bitmagic command in a message printed BY bitmagic is safe by construction: the binary * is on that shell's PATH, because it just ran there. That is exactly the guarantee the npm line * never had. */ export declare const SELF_UPDATE_COMMAND = "bitmagic self-update"; /** * The same command when it has to cross lines. * * `self-update` reads a project's pin itself, so inside a project the bare form already does the * right thing — but the mismatch notice is also printed outside one, and it is the single message * whose whole subject is which line you should be on. Saying it out loud costs nothing and leaves * nothing to infer. */ export declare function crossLineUpdateCommand(tag: UpdateTag): string; /** * What to call a line in a sentence. * * The dev line says "prerelease" out loud because the only place this is used asks someone to * install it, and portal/src/cli-install.ts is right that putting an untested build on the machine * of someone who never opted into testing is the worse failure. Being asked to cross lines is * legitimate — the project's environment is what wants it — but nobody should cross without knowing * which side they are landing on. */ export declare function describeUpdateTag(tag: UpdateTag): string; /** * Which line a PROJECT's CLI should come from — the one answer to "dev or prod?" for anyone * standing in a project directory, and the reason nobody should ever be asked. * * The project decides because the project is where the mismatch bites: new `/api/cli/v1` endpoints * reach the dev api-server before production, so a prerelease run against `prod` calls endpoints * that are not there yet, and a release run against `dev` is behind the engine that environment * serves. `local` sits with `dev` — a localhost api-server is built from the same `main` a * prerelease is cut from, so it is ahead of the release by construction. * * Note this is NOT `updateTagFor` applied to something else: that reads a version string and * answers "which line is this build ON", which is a fact about the install. This answers "which * line SHOULD it be on here", which is a fact about the project. The two disagreeing is exactly * what `cliLineMismatchNotice` reports. */ export declare function updateTagForEnvironment(environment: EnvironmentName): UpdateTag; /** * How stale a cached npm answer may be before it is refreshed. * * The check never blocks a command: the notice is printed from the cache, and a stale cache is * refreshed in the background for next time. So this is only "how far behind the notice can be", * not "how long a command waits". */ export declare const RELEASE_UPDATE_CHECK_INTERVAL_MS: number; /** * The same allowance for the dev line, which is shorter because the line moves faster. * * The dev line is cut from every merge to `main` and can move several times an hour, so an answer * that old is often about a build two or three versions back — precisely the version someone * testing dev needs to be told about soonest. Fifteen minutes keeps the nudge close to the line * while still collapsing a burst of commands into a single background registry read. */ export declare const DEV_UPDATE_CHECK_INTERVAL_MS: number; /** How long an answer about `tag` stays good. */ export declare function updateCheckIntervalFor(tag: UpdateTag): number; /** What is remembered between runs, so no command pays for the network. */ export interface UpdateCheckCache { /** The newest version npm reported for `tag`, or null if the last check could not reach it. */ latest: string | null; /** * The dist-tag that answer is about. * * Required rather than optional-with-a-default: a cache written by a CLI from before the dev * line existed then fails the shape guard, reads as absent and is refreshed — self-healing at * the cost of one quiet day, with no "unknown tag" branch for anyone to reason about. */ tag: UpdateTag; /** Epoch ms of that check. */ checkedAt: number; } /** * The interval comes from the cache's OWN tag, not from the running build's. * * They agree wherever this decides anything: `refreshUpdateCacheInBackground` refreshes a * cross-line cache unconditionally, so by the time staleness is asked about, the cache is about the * line the build is on. */ export declare function isCacheStale(cache: UpdateCheckCache | null, now: number): boolean; /** * The line to print, or null to stay quiet. * * Quiet for everything except a confirmed newer release: an unreachable npm, an unparseable * version on either side, and a CLI somehow ahead of the registry all produce nothing. * * `latestVersion` must be the newest version of the line `currentVersion` is ON — the caller is * responsible for having asked the right dist-tag. Comparing across lines would tell a tester on * 0.1.46-dev.3 to "update" to the older 0.1.45 release. */ export declare function cliUpdateNotice(currentVersion: string, latestVersion: string | null | undefined): string | null; /** * The line to say when the CLI running inside a project came from the other one. * * This is the one place the two lines are deliberately crossed, and it needs no version comparison * to do it: whatever the numbers say, a project pinned to `dev` wants the dev line and a project * pinned to `prod` wants the release. Version-driven nudges structurally cannot report this — a * prerelease sitting in a `prod` project is *ahead* of the release tag, so `cliUpdateNotice` is * correctly silent about a CLI that is on the wrong line entirely. * * `projectEnvironment` must be a project's committed pin, never a resolved environment: a one-off * `--env` is a statement about this command, not about which CLI belongs in this directory. */ export declare function cliLineMismatchNotice(currentVersion: string, projectEnvironment: EnvironmentName): string | null;