@mutmutco/installer-face 0.2.1 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +57 -16
- package/dist/conformance.d.ts +8 -0
- package/dist/face.d.ts +40 -6
- package/dist/index.d.ts +10 -1
- package/dist/index.js +688 -71
- package/dist/maintenance.d.ts +52 -0
- package/dist/outcome.d.ts +6 -0
- package/dist/payload.d.ts +7 -0
- package/dist/products.d.ts +6 -0
- package/dist/run.d.ts +86 -0
- package/dist/spinner.d.ts +9 -12
- package/dist/transcript.d.ts +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type InstallerRun } from './run.js';
|
|
2
|
+
/** Facts produced by a product's convergence engine. No terminal labels or layout. */
|
|
3
|
+
export interface MaintenanceArm {
|
|
4
|
+
surface: string;
|
|
5
|
+
from: string | null;
|
|
6
|
+
to: string;
|
|
7
|
+
verdict: 'ok' | 'skip' | 'defer' | 'fail';
|
|
8
|
+
detail: string;
|
|
9
|
+
repeatFailure?: boolean;
|
|
10
|
+
launchStaged?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface MaintenanceSummary {
|
|
13
|
+
target: string | null;
|
|
14
|
+
surfaces: {
|
|
15
|
+
id: string;
|
|
16
|
+
present: boolean;
|
|
17
|
+
action: string;
|
|
18
|
+
}[];
|
|
19
|
+
exit: number;
|
|
20
|
+
detail?: string;
|
|
21
|
+
deferred?: boolean;
|
|
22
|
+
reexec: {
|
|
23
|
+
dist: string;
|
|
24
|
+
target: string;
|
|
25
|
+
from: string | null;
|
|
26
|
+
} | null;
|
|
27
|
+
}
|
|
28
|
+
/** One install/update lifecycle, including scheduler ordering and self-update continuation. */
|
|
29
|
+
export declare function runMaintenance<S extends MaintenanceSummary>(product: unknown, args: string[], dependencies: {
|
|
30
|
+
engine: (options: {
|
|
31
|
+
dryRun: boolean;
|
|
32
|
+
shippedTarget?: string;
|
|
33
|
+
narrate?: (line: string) => void;
|
|
34
|
+
onTargetResolved?: (target: string, gate: string | null) => void;
|
|
35
|
+
onPhase?: (line: string) => void;
|
|
36
|
+
onArm?: (arm: MaintenanceArm) => void;
|
|
37
|
+
}) => Promise<S>;
|
|
38
|
+
counts: (summary: S) => {
|
|
39
|
+
total: number;
|
|
40
|
+
updated: number;
|
|
41
|
+
failed: number;
|
|
42
|
+
retry: number;
|
|
43
|
+
};
|
|
44
|
+
diagnose: (arm: MaintenanceArm) => string | undefined;
|
|
45
|
+
schedule: () => {
|
|
46
|
+
ok: boolean;
|
|
47
|
+
detail: string;
|
|
48
|
+
};
|
|
49
|
+
handOff: (next: NonNullable<S['reexec']>, args: string[], env: NodeJS.ProcessEnv) => number;
|
|
50
|
+
shippedTarget?: string;
|
|
51
|
+
run?: InstallerRun;
|
|
52
|
+
}): Promise<number>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { InstallerFinish } from './run.js';
|
|
2
|
+
export type InstallerOutcome = InstallerFinish;
|
|
3
|
+
/** Child facts cross a process boundary; unknown fields and inconsistent counts are errors. */
|
|
4
|
+
export declare function validateInstallerOutcome(value: unknown): InstallerOutcome;
|
|
5
|
+
export declare function writeInstallerOutcome(path: string, value: unknown): void;
|
|
6
|
+
export declare function readInstallerOutcome(path: string): InstallerOutcome | undefined;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Product declarations provide operations; this package owns the executable payload entry. */
|
|
2
|
+
export interface PayloadEntryOptions {
|
|
3
|
+
tarballs: string[];
|
|
4
|
+
converge: string[];
|
|
5
|
+
shippedFlag?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function renderPayloadEntry({ tarballs, converge, shippedFlag }: PayloadEntryOptions): string;
|
package/dist/products.d.ts
CHANGED
|
@@ -5,6 +5,12 @@ export interface ProductIdentity {
|
|
|
5
5
|
readonly accent: string;
|
|
6
6
|
/** The warm line under the welcome. Verbatim from the guidebook; never composed at a call site. */
|
|
7
7
|
readonly warm: string;
|
|
8
|
+
readonly installWarm: string;
|
|
9
|
+
/**
|
|
10
|
+
* The product's own health command, as the guidebook writes it. It is the ONE suggested command
|
|
11
|
+
* the receipt closes with, so it is data here rather than a string each surface retypes (#6895).
|
|
12
|
+
*/
|
|
13
|
+
readonly doctor: string;
|
|
8
14
|
}
|
|
9
15
|
export declare const PRODUCTS: Readonly<Record<string, ProductIdentity>>;
|
|
10
16
|
/** The identity for a product key. An unknown key is a caller bug, and failing here is cheaper than
|
package/dist/run.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { type StepKind, type StepMeasure } from './face.js';
|
|
2
|
+
export interface InstallerProduct {
|
|
3
|
+
product: string;
|
|
4
|
+
gate: string;
|
|
5
|
+
doctor: string;
|
|
6
|
+
surfaces: {
|
|
7
|
+
id: string;
|
|
8
|
+
npm?: string;
|
|
9
|
+
bin?: string;
|
|
10
|
+
kind?: string;
|
|
11
|
+
activation?: string;
|
|
12
|
+
}[];
|
|
13
|
+
}
|
|
14
|
+
export declare function validateInstallerProduct(value: unknown): InstallerProduct;
|
|
15
|
+
declare const PHASES: {
|
|
16
|
+
readonly preflight: readonly ["Checking prerequisites", "Checked prerequisites"];
|
|
17
|
+
readonly resolve: readonly ["Resolving the release", "Resolved the release"];
|
|
18
|
+
readonly download: readonly ["Downloading the payload", "Downloaded the payload"];
|
|
19
|
+
readonly 'sign-in': readonly ["Signing in", "Signed in"];
|
|
20
|
+
readonly check: readonly ["Checking surfaces", "Checked surfaces"];
|
|
21
|
+
readonly arm: readonly ["Scheduling updates", "Armed hourly updates"];
|
|
22
|
+
readonly 'verify-release': readonly ["Checking the release version", "Verified the release version"];
|
|
23
|
+
readonly verify: readonly ["Verifying the payload", "Verified the payload"];
|
|
24
|
+
readonly install: readonly ["Installing the product", "Installed the product"];
|
|
25
|
+
readonly activate: readonly ["Activating surfaces", "Activated surfaces"];
|
|
26
|
+
readonly doctor: readonly ["Checking health", "Checked health"];
|
|
27
|
+
};
|
|
28
|
+
export type InstallerPhase = keyof typeof PHASES;
|
|
29
|
+
export type InstallerChannel = 'stdout' | 'stderr' | 'spinner';
|
|
30
|
+
export interface InstallerRunOptions {
|
|
31
|
+
operation?: 'install' | 'update';
|
|
32
|
+
tty?: boolean;
|
|
33
|
+
dryRun?: boolean;
|
|
34
|
+
color?: boolean;
|
|
35
|
+
columns?: number;
|
|
36
|
+
env?: Readonly<NodeJS.ProcessEnv>;
|
|
37
|
+
animate?: boolean;
|
|
38
|
+
write?: (text: string, channel: InstallerChannel) => void;
|
|
39
|
+
}
|
|
40
|
+
export interface InstallerFinish {
|
|
41
|
+
version?: string;
|
|
42
|
+
total: number;
|
|
43
|
+
updated: number;
|
|
44
|
+
failed: number;
|
|
45
|
+
retry?: string;
|
|
46
|
+
dryRun?: boolean;
|
|
47
|
+
installed?: boolean;
|
|
48
|
+
detail?: string;
|
|
49
|
+
deferred?: boolean;
|
|
50
|
+
operationFailed?: boolean;
|
|
51
|
+
}
|
|
52
|
+
export interface InstallerPhaseFacts {
|
|
53
|
+
state?: 'running' | StepKind;
|
|
54
|
+
seconds?: number;
|
|
55
|
+
measure?: StepMeasure;
|
|
56
|
+
detail?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface InstallerSurfaceFacts {
|
|
59
|
+
id: string;
|
|
60
|
+
from?: string | null;
|
|
61
|
+
to?: string | null;
|
|
62
|
+
state: 'updated' | 'current' | 'failed' | 'skipped' | 'retry' | 'pending' | 'kept';
|
|
63
|
+
seconds?: number;
|
|
64
|
+
detail?: string;
|
|
65
|
+
}
|
|
66
|
+
/** One owner for the entire run. Callers supply measured facts, never terminal prose. */
|
|
67
|
+
export declare function createInstallerRun(value: unknown, options?: InstallerRunOptions): {
|
|
68
|
+
start: () => void;
|
|
69
|
+
phase(id: InstallerPhase, facts?: InstallerPhaseFacts): void;
|
|
70
|
+
surface(facts: InstallerSurfaceFacts): void;
|
|
71
|
+
milestone({ step, state, ms }: {
|
|
72
|
+
step: string;
|
|
73
|
+
state: StepKind;
|
|
74
|
+
ms?: number;
|
|
75
|
+
}): void;
|
|
76
|
+
signIn({ url, code }: {
|
|
77
|
+
url: string;
|
|
78
|
+
code: string;
|
|
79
|
+
}): void;
|
|
80
|
+
relay(text: string, channel?: InstallerChannel, record?: boolean): void;
|
|
81
|
+
finish(facts: InstallerFinish): void;
|
|
82
|
+
stop(): void;
|
|
83
|
+
};
|
|
84
|
+
export type InstallerRun = ReturnType<typeof createInstallerRun>;
|
|
85
|
+
export declare function runInstaller(value: unknown, operation: (run: InstallerRun) => Promise<InstallerFinish>, options?: InstallerRunOptions): Promise<InstallerFinish>;
|
|
86
|
+
export {};
|
package/dist/spinner.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { Face } from './face.js';
|
|
1
|
+
import type { Face, StepMeasure } from './face.js';
|
|
2
2
|
export interface Spinner {
|
|
3
|
-
/** Begin animating against this title
|
|
4
|
-
start(text: string): void;
|
|
5
|
-
/** Change the title without restarting the animation. */
|
|
6
|
-
say(text: string): void;
|
|
3
|
+
/** Begin animating against this title, optionally carrying the right-column measure. */
|
|
4
|
+
start(text: string, measure?: StepMeasure): void;
|
|
5
|
+
/** Change the title, and the measure, without restarting the animation. */
|
|
6
|
+
say(text: string, measure?: StepMeasure): void;
|
|
7
7
|
/** Stop and CLEAR the line. Always call before writing the durable step line. */
|
|
8
8
|
stop(): void;
|
|
9
9
|
}
|
|
@@ -14,13 +14,10 @@ export interface SpinnerOptions {
|
|
|
14
14
|
stream?: NodeJS.WritableStream;
|
|
15
15
|
/** Frame interval in ms. */
|
|
16
16
|
intervalMs?: number;
|
|
17
|
+
/** Default stderr lane records worker frames here without involving the main event loop. */
|
|
18
|
+
transcriptPath?: string;
|
|
17
19
|
}
|
|
18
|
-
/**
|
|
19
|
-
|
|
20
|
-
* at the same place — one left edge, not two. It renders through `face.step(text, null, 'note')`
|
|
21
|
-
* rather than composing a line of its own, which means it inherits TITLE_COLUMN and cannot drift
|
|
22
|
-
* from it when the face changes.
|
|
23
|
-
*/
|
|
24
|
-
export declare function createSpinner(face: Face, { animate, stream, intervalMs }: SpinnerOptions): Spinner;
|
|
20
|
+
/** Shared formatting, with a worker for stderr and a timer for injected streams. */
|
|
21
|
+
export declare function createSpinner(face: Face, { animate, stream, intervalMs, transcriptPath }: SpinnerOptions): Spinner;
|
|
25
22
|
/** The frames, exported so a conformance check can recognise transient output. */
|
|
26
23
|
export declare const SPINNER_FRAMES: readonly string[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mutmutco/installer-face",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "The MM Terminal Line installer face: one renderer, the canonical product table, shell/PowerShell fragments for served one-liners, and the drift guard every surface runs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|