@capgo/cli
Version:
A CLI to upload to capgo servers
102 lines (101 loc) • 4.85 kB
TypeScript
import type { PackageManagerType } from '@capgo/find-package-manager';
/**
* Set on the re-exec'd child so the freshly-launched (already-updated) process
* never re-prompts. Without this, a brief npm-registry propagation lag — where
* the new version isn't yet visible to the child's own check — could cause an
* infinite update → relaunch → update loop.
*/
export declare const SKIP_UPDATE_ENV = "CAPGO_SKIP_UPDATE_PROMPT";
type DependencySection = 'dependencies' | 'devDependencies' | 'optionalDependencies';
export interface CliDependencyDeclaration {
packageJsonPath: string;
section: DependencySection;
range: string;
}
/**
* Walk up from `startDir` (inclusive) to `rootDir` (inclusive) and return the
* first package.json that declares @capgo/cli, with its section + range.
*
* In a monorepo this finds the app sub-package's declaration when present,
* otherwise the workspace root's. Returns null when nothing on that path
* declares the CLI — i.e. it was launched ephemerally (npx/bunx/dlx), so there
* is no on-disk dependency to update.
*/
export declare function findCliDeclaration(startDir: string, rootDir: string): CliDependencyDeclaration | null;
/**
* Resolve the on-disk entry script of the installed @capgo/cli by walking up
* node_modules from `startDir` (hoisting-aware, so it finds the workspace-root
* install in a monorepo). Returns the absolute path to the package's bin entry,
* or null when the CLI isn't installed anywhere up the tree.
*/
export declare function resolveInstalledCliEntry(startDir: string): string | null;
/**
* Bump a semver range to `latest` while preserving the caret/tilde prefix.
* Dist-tag ranges ("latest"/"next"/"*"), workspace protocols, and anything
* without a digit are returned unchanged — reinstalling already re-resolves
* those, and we must not clobber an intentional tag with a pinned version.
*/
export declare function bumpRange(oldRange: string, latest: string): string;
/**
* Pure transform: set @capgo/cli in `section` to the bumped range within the
* given package.json text. Preserves 2-space indentation and the trailing
* newline. Returns null when nothing changed (already at target / a tag range).
*/
export declare function applyCliBump(packageJsonText: string, section: DependencySection, latest: string): string | null;
export interface SpawnCommand {
cmd: string;
args: string[];
}
/**
* Ephemeral re-exec (Path B): fetch + run the latest CLI through the project's
* package-manager runner. npx needs `-y` to skip its "Ok to proceed?" install
* prompt (which would deadlock an automated re-exec); bunx/pnpm dlx/yarn dlx
* install non-interactively. The flag must precede the package spec so the
* runner consumes it instead of forwarding it to `capgo`.
*/
export declare function buildEphemeralReexec(pm: PackageManagerType, forwardArgs: string[]): SpawnCommand;
/** `<pm> install`, run at the workspace root for Path A (reconciles the
* lockfile after the package.json bump for npm/yarn/pnpm/bun workspaces). */
export declare function buildInstallCommand(pm: PackageManagerType): SpawnCommand;
export type UpdateStrategy = {
kind: 'project';
declaration: CliDependencyDeclaration;
installRoot: string;
entry: string;
} | {
kind: 'ephemeral';
};
/**
* Decide how to update based on how the running process resolved. Path A
* (project) requires BOTH a declared dependency AND a resolvable local entry,
* so we can re-exec the exact installed binary after `<pm> install`. Anything
* else — including "declared but not installed" — falls back to Path B.
*/
export declare function classifyUpdateStrategy(opts: {
installRoot: string;
declaration: CliDependencyDeclaration | null;
entry: string | null;
}): UpdateStrategy;
/**
* Check whether a newer @capgo/cli is published, capped by a timeout so a slow
* registry can't stall the wizard. Returns the version pair when an update is
* available, or null when up to date / timed out / re-exec'd (the SKIP env is
* set on the relaunched child to avoid an update→relaunch loop).
*
* The decision UI lives in the Ink wizard (ui/update-prompt.tsx) — this only
* resolves the data the prompt needs. The install + re-exec is
* runUpdateAndReexec, run AFTER Ink tears down.
*/
export declare function checkForCliUpdate(): Promise<{
currentVersion: string;
latestVersion: string;
} | null>;
export declare function runUpdateAndReexec(latest: string): void;
/**
* Runner-aware "update manually" hint (e.g. `npx -y @capgo/cli@latest build
* init`, `pnpm dlx @capgo/cli@latest build init`) for the fallback shown when
* an accepted auto-update fails — so the suggested command matches the user's
* package manager rather than hardcoding npx.
*/
export declare function manualUpdateHint(): string;
export {};