import type { PublishStepKind, PublishStepStatus } from './index.js'; /** * How to name a step at each point in its life, so its wording lives in one * place instead of being spread across the providers that emit it and the views * that render it. */ type StepLabels = { /** The step before it starts, phrased so it does not read as already happening, e.g. 'Provision database(s)'. */ idle: string; /** The step while it runs, e.g. 'Provisioning database(s)'. */ active: string; /** What the step has done, e.g. 'Provisioned database(s)'. */ done: string; /** The step as a thing another step waits for, e.g. 'database provisioning'. */ dependency: string; }; /** * A step reads as an action: its plain, not-yet-running name (`idle`) while it * waits, its active phrasing while it runs, and its past tense once done. The * policy step is named after the policies it checks rather than an action, so * its idle and done names are the same and only its running name gains a verb. */ const STEP_LABELS: Record = { build: { active: 'Building application', dependency: 'the application build', done: 'Built application', idle: 'Build application' }, database_migration: { active: 'Applying schema migrations to database(s)', dependency: 'schema migrations', done: 'Applied schema migrations to database(s)', idle: 'Apply schema migrations to database(s)' }, database_provisioning: { active: 'Provisioning database(s)', dependency: 'database provisioning', done: 'Provisioned database(s)', idle: 'Provision database(s)' }, policy_gates: { active: 'Running Pre-Publish Policies', dependency: 'Pre-Publish Policies', done: 'Pre-Publish Policies', idle: 'Pre-Publish Policies' }, publish: { active: 'Publishing', dependency: 'publishing', done: 'Published', idle: 'Publish' } }; /** The table typed loosely, for the lookups that have to survive an unknown kind. */ const STEP_LABELS_BY_KIND: Partial> = STEP_LABELS; /** * A publish plan crosses the wire, so a newer server can name a step kind this * build has never heard of. Show that kind as-is rather than leaving the row * nameless or throwing on the way to rendering it. */ function labelsFor(kind: PublishStepKind): StepLabels { return STEP_LABELS_BY_KIND[kind] ?? { active: kind, dependency: kind, done: kind, idle: kind }; } /** * The label to show for a step, phrased for where that step currently is. An * optional note (such as how many data tags the step covers) sits with the * phrase, ahead of the marker for a running or failed step. */ export function publishStepDisplayName(kind: PublishStepKind, status: PublishStepStatus, note?: string): string { const labels = labelsFor(kind); // Advisory means the step finished and left a note behind, so it reads as done. // Only a running step uses the active phrasing; a failed or not-yet-started // step uses the plain name so it never reads as if it is still happening. const phrase = status === 'passed' || status === 'advisory' ? labels.done : status === 'in_progress' ? labels.active : labels.idle; const labeled = note === undefined ? phrase : `${phrase} (${note})`; switch (status) { case 'in_progress': return `${labeled}…`; case 'failed': return `${labeled} failed`; // Skipped never ran, and the rest are all waiting on something. A status // added later lands here too, so a step can never render without a name. default: return labeled; } } /** * How to refer to a step that another step is waiting for. The action phrasing * does not fit here: 'Waiting on database provisioning' reads as a sentence, * 'Waiting on Provisioning database(s)' does not. */ export function publishStepDependencyName(kind: PublishStepKind): string { return labelsFor(kind).dependency; }