refactor(ui/alerts): derive option lists + form-state types from schema.d.ts
Closes item 5 on the Plan 03 cleanup triage. The option arrays
("METRICS", "COMPARATORS", KIND_OPTIONS, SEVERITY_OPTIONS, FIRE_MODES)
scattered across RouteMetricForm / JvmMetricForm / ExchangeMatchForm /
ConditionStep / ScopeStep were hand-typed string literals. They drifted
silently — P95_LATENCY_MS appeared in a dropdown without a backend
counterpart (caught at runtime in bcde6678); JvmMetric.LATEST and
Comparator.EQ existed on the backend but were missing from the UI all
along.
Fix: new `ui/src/api/alerting-enums.ts` derives every enum from
schema.d.ts and pairs each with a `Record<T, string>` label map.
TypeScript enforces exhaustiveness — adding or removing a backend
value fails the build of this file until the label map is updated.
Every consumer imports the generated `*_OPTIONS` array.
Covered (schema-derived):
- ConditionKind → CONDITION_KIND_OPTIONS
- Severity → SEVERITY_OPTIONS
- RouteMetric → ROUTE_METRIC_OPTIONS
- Comparator → COMPARATOR_OPTIONS (adds EQ that was missing)
- JvmAggregation → JVM_AGGREGATION_OPTIONS (adds LATEST that was missing)
- ExchangeMatch.fireMode → EXCHANGE_FIRE_MODE_OPTIONS
- AlertRuleTarget.kind → TARGET_KIND_OPTIONS
form-state.ts: `severity: 'CRITICAL' | 'WARNING' | 'INFO'` and
`kind: 'USER' | 'GROUP' | 'ROLE'` literal unions swapped for the
derived `Severity` / `TargetKind` aliases.
Not covered, backend types them as `String` (no `@Schema(allowableValues)`
annotation yet):
- AgentStateCondition.state
- DeploymentStateCondition.states
- LogPatternCondition.level
- ExchangeFilter.status
- JvmMetricCondition.metric
These stay hand-typed with a pointer-comment. Follow-up: add
`@Schema(allowableValues = …)` to the Java record components so the
enums land in schema.d.ts; then fold them into alerting-enums.ts.
Plus: gitnexus index-stats refresh in AGENTS.md/CLAUDE.md from the
post-deploy reindex.
Verified: ui build green, 49/49 vitest pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import type {
|
||||
ConditionKind,
|
||||
AlertCondition,
|
||||
} from '../../../api/queries/alertRules';
|
||||
import type { Severity, TargetKind } from '../../../api/alerting-enums';
|
||||
|
||||
export type WizardStep = 'scope' | 'condition' | 'trigger' | 'notify' | 'review';
|
||||
export const WIZARD_STEPS: WizardStep[] = ['scope', 'condition', 'trigger', 'notify', 'review'];
|
||||
@@ -11,7 +12,7 @@ export const WIZARD_STEPS: WizardStep[] = ['scope', 'condition', 'trigger', 'not
|
||||
export interface FormState {
|
||||
name: string;
|
||||
description: string;
|
||||
severity: 'CRITICAL' | 'WARNING' | 'INFO';
|
||||
severity: Severity;
|
||||
enabled: boolean;
|
||||
|
||||
// Scope (radio: env-wide | app | route | agent)
|
||||
@@ -36,7 +37,7 @@ export interface FormState {
|
||||
headerOverrides: Array<{ key: string; value: string }>;
|
||||
}>;
|
||||
|
||||
targets: Array<{ kind: 'USER' | 'GROUP' | 'ROLE'; targetId: string }>;
|
||||
targets: Array<{ kind: TargetKind; targetId: string }>;
|
||||
}
|
||||
|
||||
export function initialForm(existing?: AlertRuleResponse): FormState {
|
||||
@@ -102,7 +103,7 @@ export function initialForm(existing?: AlertRuleResponse): FormState {
|
||||
.map(([key, value]) => ({ key, value })),
|
||||
})),
|
||||
targets: (existing.targets ?? []).map((t) => ({
|
||||
kind: (t.kind ?? 'USER') as 'USER' | 'GROUP' | 'ROLE',
|
||||
kind: (t.kind ?? 'USER') as TargetKind,
|
||||
targetId: t.targetId ?? '',
|
||||
})),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user