import type { DependencyJobRequest, LogBackfillRequest, RunDistributionGenerateRequest, RunUpdateRequest, ServerInstanceUpdateRequest, ServerLifecycleCommandRequest, ServerLifecycleCreateRequest, ServerInstanceResponse } from "../api/types"; import type { ServerCreateFormState, ServerMetadataFormState, ServerRemovalConfirmationState } from "../contracts/serverManagement"; export function minimalServerCreateRequestFromForm(form: ServerCreateFormState, sequence = Date.now()): ServerLifecycleCreateRequest { const id = form.id.trim() || serverInstanceIdFromName(form.name, sequence); return { id, pluginId: form.pluginId.trim(), name: form.name.trim(), idempotencyKey: lifecycleIdempotencyKey("create", id, sequence) }; } export function serverCreateRequestFromForm(form: ServerCreateFormState, sequence = Date.now()): ServerLifecycleCreateRequest { const id = form.id.trim() || serverInstanceIdFromName(form.name, sequence); return { id, pluginId: form.pluginId.trim(), name: form.name.trim(), idempotencyKey: lifecycleIdempotencyKey("create", id, sequence), deployment: { mode: form.deploymentMode, createInputs: Object.fromEntries(Object.entries(form.createInputs).map(([key, value]) => [key, value.trim()])), serverRoot: form.serverRoot.trim() || undefined, workingDirectory: form.workingDirectory.trim() || undefined, installCommand: form.installCommand.trim() || undefined, startCommand: form.startCommand.trim() || undefined, stopCommand: form.stopCommand.trim() || undefined, statusCommand: form.statusCommand.trim() || undefined, shell: form.shell || undefined } }; } export function serverInstanceIdFromName(name: string, sequence = Date.now()): string { const normalized = name .trim() .toLowerCase() .normalize("NFKD") .replace(/[\u0300-\u036f]/g, "") .replace(/[^a-z0-9]+/g, "-") .replace(/^-+|-+$/g, "") .slice(0, 48) .replace(/-+$/g, ""); const suffix = String(Math.max(0, Math.floor(Number.isFinite(sequence) ? sequence : Date.now()))); return normalized ? `server-${normalized}-${suffix}` : `server-${suffix}`; } export function serverLifecycleCommandRequest(instance: ServerInstanceResponse, action: "deploy" | "start" | "stop" | "status", sequence = Date.now()): ServerLifecycleCommandRequest { return { expectedConfigVersion: instance.configVersion, idempotencyKey: lifecycleIdempotencyKey(action, instance.id, sequence) }; } export function serverMetadataUpdateRequestFromForm(form: ServerMetadataFormState): ServerInstanceUpdateRequest { return { name: form.name.trim() }; } export function serverDeleteConfirmation(instance: ServerInstanceResponse): ServerRemovalConfirmationState { return { action: "delete", serverInstanceId: instance.id, name: instance.name, state: instance.state }; } export function runDistributionGenerateRequest(serverInstanceId: string, targetOs: string, targetArch: string, sequence = Date.now()): RunDistributionGenerateRequest { return { targetOs, targetArch, idempotencyKey: runtimeIdempotencyKey("run.generate", serverInstanceId, sequence) }; } export function runUpdateRequest(serverInstanceId: string, artifactId: string, checksum?: string, sequence = Date.now()): RunUpdateRequest { return { artifactId, checksum, idempotencyKey: runtimeIdempotencyKey("run.update", serverInstanceId, sequence) }; } export function dependencyJobRequest(serverInstanceId: string, probeKey: string, installPlanKey = "", planDigest = "", sequence = Date.now()): DependencyJobRequest { return { probeKey: probeKey.trim(), installPlanKey: installPlanKey.trim() || undefined, planDigest: planDigest.trim() || undefined, idempotencyKey: runtimeIdempotencyKey(installPlanKey ? "dependencies.install" : "dependencies.check", serverInstanceId, sequence) }; } export function logBackfillRequest(serverInstanceId: string, sourceKey: string, checkpointRef = "", limit = 200, sequence = Date.now()): LogBackfillRequest { return { sourceKey: sourceKey.trim(), checkpointRef: checkpointRef.trim() || undefined, limit, idempotencyKey: runtimeIdempotencyKey("logs.backfill", serverInstanceId, sequence) }; } export function runtimeIdempotencyKey(action: string, serverInstanceId: string, sequence: number): string { return `web:${action}:${serverInstanceId}:${sequence}`; } export function lifecycleIdempotencyKey(action: "create" | "deploy" | "start" | "stop" | "status", serverInstanceId: string, sequence: number): string { return `web:${action}:${serverInstanceId}:${sequence}`; }