import type { EnvironmentDeployment } from '@dify/contracts/enterprise/types.gen' type RuntimeInstanceStatusValue = number | string type RuntimeInstanceStatusRow = { status?: RuntimeInstanceStatusValue } type RuntimeInstanceStatus = NonNullable export type DeploymentUiStatus = | 'ready' | 'deploying' | 'deploy_failed' | 'drifted' | 'invalid' | 'not_deployed' | 'unknown' const DEPLOYMENT_STATUS_POLLING_INTERVAL = 3000 // Mirrors appdeploy/v1/common.proto RuntimeInstanceStatus for EnvironmentDeployment.status. const RUNTIME_INSTANCE_STATUS_UNDEPLOYED = 'RUNTIME_INSTANCE_STATUS_UNDEPLOYED' satisfies RuntimeInstanceStatus const RUNTIME_INSTANCE_STATUS_DEPLOYING = 'RUNTIME_INSTANCE_STATUS_DEPLOYING' satisfies RuntimeInstanceStatus const RUNTIME_INSTANCE_STATUS_READY = 'RUNTIME_INSTANCE_STATUS_READY' satisfies RuntimeInstanceStatus const RUNTIME_INSTANCE_STATUS_FAILED = 'RUNTIME_INSTANCE_STATUS_FAILED' satisfies RuntimeInstanceStatus const RUNTIME_INSTANCE_STATUS_DRIFTED = 'RUNTIME_INSTANCE_STATUS_DRIFTED' satisfies RuntimeInstanceStatus const RUNTIME_INSTANCE_STATUS_INVALID = 'RUNTIME_INSTANCE_STATUS_INVALID' satisfies RuntimeInstanceStatus type RuntimeInstanceStatusQueryData = { data?: RuntimeInstanceStatusRow[] } export function isUndeployedDeploymentRow(row?: EnvironmentDeployment) { return deploymentStatus(row) === 'not_deployed' || (!row?.currentRelease?.id && !row?.desiredRelease?.id && !row?.currentDeployment?.id) } export function hasRuntimeInstanceDeployment(row?: EnvironmentDeployment) { return Boolean(row?.environment?.id && !isUndeployedDeploymentRow(row)) } export function isAvailableDeploymentTarget(row?: EnvironmentDeployment) { return Boolean(row?.environment?.id && isUndeployedDeploymentRow(row)) } function normalizeRuntimeInstanceStatus(status?: RuntimeInstanceStatusValue): RuntimeInstanceStatus | undefined { if (typeof status === 'number') { switch (status) { case 1: return RUNTIME_INSTANCE_STATUS_UNDEPLOYED case 2: return RUNTIME_INSTANCE_STATUS_DEPLOYING case 3: return RUNTIME_INSTANCE_STATUS_READY case 4: return RUNTIME_INSTANCE_STATUS_FAILED case 5: return RUNTIME_INSTANCE_STATUS_DRIFTED case 6: return RUNTIME_INSTANCE_STATUS_INVALID default: return undefined } } const normalized = status?.trim().toUpperCase() if (!normalized) return undefined switch (normalized) { case '1': case 'UNDEPLOYED': case RUNTIME_INSTANCE_STATUS_UNDEPLOYED: return RUNTIME_INSTANCE_STATUS_UNDEPLOYED case '2': case 'DEPLOYING': case RUNTIME_INSTANCE_STATUS_DEPLOYING: return RUNTIME_INSTANCE_STATUS_DEPLOYING case '3': case 'READY': case RUNTIME_INSTANCE_STATUS_READY: return RUNTIME_INSTANCE_STATUS_READY case '4': case 'FAILED': case RUNTIME_INSTANCE_STATUS_FAILED: return RUNTIME_INSTANCE_STATUS_FAILED case '5': case 'DRIFTED': case RUNTIME_INSTANCE_STATUS_DRIFTED: return RUNTIME_INSTANCE_STATUS_DRIFTED case '6': case 'INVALID': case RUNTIME_INSTANCE_STATUS_INVALID: return RUNTIME_INSTANCE_STATUS_INVALID default: return undefined } } export function deploymentStatus(row?: RuntimeInstanceStatusRow): DeploymentUiStatus { const status = normalizeRuntimeInstanceStatus(row?.status) if (!status) return 'unknown' if (status === RUNTIME_INSTANCE_STATUS_UNDEPLOYED) return 'not_deployed' if (status === RUNTIME_INSTANCE_STATUS_DEPLOYING) return 'deploying' if (status === RUNTIME_INSTANCE_STATUS_FAILED) return 'deploy_failed' if (status === RUNTIME_INSTANCE_STATUS_READY) return 'ready' if (status === RUNTIME_INSTANCE_STATUS_DRIFTED) return 'drifted' if (status === RUNTIME_INSTANCE_STATUS_INVALID) return 'invalid' return 'unknown' } function hasDeployingDeployment(rows?: RuntimeInstanceStatusRow[]) { return rows?.some(row => deploymentStatus(row) === 'deploying') ?? false } export function deploymentStatusPollingInterval(data?: RuntimeInstanceStatusQueryData) { return hasDeployingDeployment(data?.data) ? DEPLOYMENT_STATUS_POLLING_INTERVAL : false }