| |
| |
| |
| |
| |
| |
|
|
| import { db, capabilityLifecycleEvents } from "@workspace/db"; |
| import { newId } from "../ids.js"; |
|
|
| export type CapabilityLifecycleState = |
| | "created" |
| | "cold_start" |
| | "graduated" |
| | "live" |
| | "degraded"; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| const ALLOWED: Readonly<Record<CapabilityLifecycleState, ReadonlyArray<CapabilityLifecycleState>>> = { |
| created: ["cold_start"], |
| cold_start: ["graduated", "degraded"], |
| graduated: ["live", "degraded"], |
| live: ["degraded"], |
| degraded: ["cold_start", "live"], |
| }; |
|
|
| export class IllegalLifecycleTransitionError extends Error { |
| constructor( |
| public readonly from: CapabilityLifecycleState, |
| public readonly to: CapabilityLifecycleState, |
| ) { |
| super( |
| `capability/lifecycle: illegal transition ${from} → ${to} ` + |
| `(allowed from ${from}: [${ALLOWED[from].join(", ")}])`, |
| ); |
| this.name = "IllegalLifecycleTransitionError"; |
| } |
| } |
|
|
| export function isLegalTransition( |
| from: CapabilityLifecycleState, |
| to: CapabilityLifecycleState, |
| ): boolean { |
| if (from === to) return false; |
| return ALLOWED[from]?.includes(to) ?? false; |
| } |
|
|
| export function assertLegalTransition( |
| from: CapabilityLifecycleState, |
| to: CapabilityLifecycleState, |
| ): void { |
| if (!isLegalTransition(from, to)) { |
| throw new IllegalLifecycleTransitionError(from, to); |
| } |
| } |
|
|
| export interface TransitionToArgs { |
| capabilityId: string; |
| from: CapabilityLifecycleState; |
| to: CapabilityLifecycleState; |
| reason: string; |
| payload?: Record<string, unknown>; |
| } |
|
|
| export async function transitionTo(args: TransitionToArgs): Promise<{ eventId: string }> { |
| assertLegalTransition(args.from, args.to); |
| const eventId = newId("clcyev"); |
| await db.insert(capabilityLifecycleEvents).values({ |
| id: eventId, |
| capabilityId: args.capabilityId, |
| fromState: args.from, |
| toState: args.to, |
| reason: args.reason, |
| payload: args.payload ?? {}, |
| }); |
| return { eventId }; |
| } |
|
|
| export const ALL_LIFECYCLE_STATES: ReadonlyArray<CapabilityLifecycleState> = [ |
| "created", |
| "cold_start", |
| "graduated", |
| "live", |
| "degraded", |
| ]; |
|
|