import { type Argv, type Arguments } from 'yargs'; /** * Side-effectful primitives used by the ctl orchestration. Extracted behind an * interface so the control flow can be unit-tested with fakes while the real * command wires in process spawning, git and the filesystem. */ export interface CtlDeps { /** * Starts `npm run dev` for a service, truncating logFile and piping output * to it. Returns the master pid, or 0 if the process failed to start. */ startService(dir: string, logFile: string): number; /** Runs `git pull` in the service directory; throws on failure. */ gitPull(dir: string): void; /** Runs `npm run stop` in the service directory (best-effort). */ stopService(dir: string): void; /** Signals a started process (and its group) by pid; defaults to SIGTERM. */ killGroup(pid: number, signal?: NodeJS.Signals): void; /** True if a process with the given pid is currently running. */ isAlive(pid: number): boolean; /** Reads a service log file, returning '' when it does not exist yet. */ readLog(logFile: string): string; /** Resolves after the given number of milliseconds. */ sleep(ms: number): Promise; /** Monotonic-ish millisecond clock (injected so tests stay deterministic). */ now(): number; /** Writes a status line for the user. */ log(msg: string): void; } /** Options controlling a ctl invocation. */ export interface CtlOptions { path: string; services?: string[]; update: boolean; calm: boolean; verbose: boolean; varHome?: string; } /** * Outcome of waiting for a service to become ready in calm mode. * - `ready` - the readiness marker appeared; * - `crashed` - the process exited during startup (dead pid); * - `errored` - an error was logged but the process is still alive; * - `timeout` - neither readiness nor an error within the attempt budget. */ export type ReadyState = 'ready' | 'crashed' | 'errored' | 'timeout'; interface PidEntry { svc: string; pid: number; } /** * Parses the `/.pids` file into `{ svc, pid }` records, ignoring blank or * malformed lines. Missing file yields an empty list. * * @param {string} varHome - runtime working directory * @return {PidEntry[]} */ export declare function readPids(varHome: string): PidEntry[]; /** * Serialises pid records back to the `/.pids` file (one `svc:pid` per * line). Writing an empty list removes the file's contents. * * @param {string} varHome - runtime working directory * @param {PidEntry[]} entries - records to persist */ export declare function writePids(varHome: string, entries: PidEntry[]): void; /** * Polls a service log file until it reports readiness, the process exits * (crashed during startup), or the attempt budget is exhausted. Used by calm * mode so services start one-at-a-time rather than all at once. Because the * log is truncated on start, the readiness scan only ever sees the current * run - it cannot be fooled by a marker left over from a previous run. * * @param {string} logFile - path to the service log * @param {number} pid - master pid of the started service * @param {CtlDeps} deps - injected primitives * @param {number} [maxAttempts] - number of one-second polls before timing out * @return {Promise} */ export declare function waitForReady(logFile: string, pid: number, deps: CtlDeps, maxAttempts?: number): Promise; /** * Starts the selected services, recording their master pids and (in calm * mode) waiting for each to become ready before starting the next. * * @param {CtlOptions} opts * @param {CtlDeps} deps * @return {Promise} */ export declare function startServices(opts: CtlOptions, deps: CtlDeps): Promise; /** * Stops the selected services: signals their recorded master processes, waits * for them to actually terminate (escalating SIGTERM -> SIGKILL), runs each * service's `stop` script, and prints a summary. Pids of services we could not * kill are kept in the pid file (with a warning) so `status` still reflects * reality and a later `start` won't spawn a duplicate. * * When run from a directory where no services can be discovered and no explicit * `-s` was given, it falls back to stopping every tracked pid, so `imq ctl stop` * works from anywhere rather than silently doing nothing. * * @param {CtlOptions} opts * @param {CtlDeps} deps * @return {Promise} */ export declare function stopServices(opts: CtlOptions, deps: CtlDeps): Promise; /** * Reports the recorded services and whether each is currently running, * distinguishing live pids from stale ones left by a crash or reboot. * * @param {CtlOptions} opts * @param {CtlDeps} deps * @return {void} */ export declare function statusServices(opts: CtlOptions, deps: CtlDeps): void; /** * Runs a ctl action (start | stop | restart | status) end-to-end, honoring * verbose timing. * * @param {'start'|'stop'|'restart'|'status'} action * @param {CtlOptions} opts * @param {CtlDeps} deps * @return {Promise} */ export declare function runCtl(action: 'start' | 'stop' | 'restart' | 'status', opts: CtlOptions, deps: CtlDeps): Promise; /** * Builds the production dependency set (real spawning, git and filesystem). * * @return {CtlDeps} */ export declare function defaultDeps(): CtlDeps; export declare const command: string, describe: string, builder: (yargs: Argv) => Argv<{ action: "restart" | "start" | "status" | "stop" | undefined; } & { p: string; } & { s: string | undefined; } & { u: boolean; } & { c: boolean; } & { v: boolean; }>, handler: (argv: Arguments) => Promise; export {};