dify/web/features/deployments/create-guide/state/target.ts
Stephen Zhou a84c2d36a3
style: format with vp fmt (#38803)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-12 15:57:46 +00:00

173 lines
5.6 KiB
TypeScript

'use client'
import type {
EnvVarBindingSlot,
EnvVarValueSelection,
} from '@/features/deployments/shared/components/env-var-bindings'
import { atom } from 'jotai'
import {
envVarBindingSlotFromContract,
envVarBindingValueType,
} from '@/features/deployments/shared/components/env-var-bindings-utils'
import {
hasMissingRequiredRuntimeCredentialBinding,
runtimeCredentialSlotKey,
selectedRuntimeCredentialSelections,
} from '@/features/deployments/shared/components/runtime-credential-bindings-utils'
import { dslEnvVarSlots } from '@/features/deployments/shared/domain/dsl'
import { environmentMatchesIdentifier } from './environment'
import {
effectiveMethodAtom,
envVarValuesAtom,
manualBindingSelectionsAtom,
selectedEnvironmentIdAtom,
} from './primitives'
import {
deployableEnvironmentsDataAtom,
deploymentOptionsDataAtom,
deploymentOptionsReadyAtom,
} from './queries'
import { submittedReleaseReadyAtom } from './release'
import { dslContentAtom, sourceReady } from './source'
import { envVarSelectionReady } from './utils'
export const deployableEnvironmentsAtom = atom((get) => {
const deployableEnvironments = get(deployableEnvironmentsDataAtom)
return sourceReady(get) ? (deployableEnvironments?.environments ?? []) : []
})
const deployableEnvironmentsReadyAtom = atom((get) => {
return sourceReady(get) && Boolean(get(deployableEnvironmentsDataAtom))
})
export const effectiveSelectedEnvironmentIdAtom = atom((get) => {
return get(selectedEnvironmentIdAtom) || get(deployableEnvironmentsAtom)[0]?.id
})
export const deploymentTargetBindingSlotsAtom = atom((get) => {
const deploymentOptions = get(deploymentOptionsDataAtom)
return sourceReady(get)
? (deploymentOptions?.options?.credentialSlots?.filter((slot) =>
runtimeCredentialSlotKey(slot),
) ?? [])
: []
})
export const deploymentTargetBindingSelectionsAtom = atom((get) => {
return selectedRuntimeCredentialSelections(
get(deploymentTargetBindingSlotsAtom),
get(manualBindingSelectionsAtom),
)
})
export const requiredBindingsReadyAtom = atom((get) => {
const bindingSelections = get(deploymentTargetBindingSelectionsAtom)
return get(deploymentTargetBindingSlotsAtom).every(
(slot) =>
!hasMissingRequiredRuntimeCredentialBinding(
slot,
bindingSelections[runtimeCredentialSlotKey(slot)],
),
)
})
export const deploymentTargetEnvVarSlotsAtom = atom((get) => {
const method = get(effectiveMethodAtom)
const deploymentOptions = get(deploymentOptionsDataAtom)
const slots = sourceReady(get) ? deploymentOptions?.options?.envVarSlots : undefined
const dslContent = get(dslContentAtom)
// Deployment options own the canonical slot list; DSL metadata only enriches import-DSL defaults.
const deploymentOptionEnvVarSlots =
slots?.flatMap((slot): EnvVarBindingSlot[] => {
const bindingSlot = envVarBindingSlotFromContract(slot)
return bindingSlot ? [bindingSlot] : []
}) ?? []
const dslEnvVarMetadataSlots =
method === 'importDsl' && dslContent
? dslEnvVarSlots(dslContent).flatMap((slot) => {
const key = slot.key.trim()
if (!key) return []
return [
{
key,
...(slot.description ? { description: slot.description } : {}),
...(slot.defaultValue !== undefined
? { defaultValue: slot.defaultValue, hasDefaultValue: true }
: {}),
...(slot.valueType ? { valueType: envVarBindingValueType(slot.valueType) } : {}),
},
]
})
: []
if (dslEnvVarMetadataSlots.length === 0) return deploymentOptionEnvVarSlots
const metadataByKey = new Map(dslEnvVarMetadataSlots.map((slot) => [slot.key, slot] as const))
return deploymentOptionEnvVarSlots.map((slot) => {
const metadata = metadataByKey.get(slot.key)
if (!metadata) return slot
const nextSlot = { ...slot }
if (!nextSlot.description && metadata.description) nextSlot.description = metadata.description
if (!nextSlot.hasDefaultValue && metadata.defaultValue !== undefined) {
nextSlot.defaultValue = metadata.defaultValue
nextSlot.hasDefaultValue = true
}
if (nextSlot.valueType === 'string' && metadata.valueType)
nextSlot.valueType = metadata.valueType
return nextSlot
})
})
export const requiredEnvVarsReadyAtom = atom((get) => {
const envVarValues = get(envVarValuesAtom)
return get(deploymentTargetEnvVarSlotsAtom).every((slot) =>
envVarSelectionReady(slot, envVarValues[slot.key]),
)
})
export const canDeployAtom = atom((get) => {
const effectiveSelectedEnvironmentId = get(effectiveSelectedEnvironmentIdAtom)
const selectedEnvironment = effectiveSelectedEnvironmentId
? get(deployableEnvironmentsAtom).find((env) =>
environmentMatchesIdentifier(env, effectiveSelectedEnvironmentId),
)
: undefined
return Boolean(
selectedEnvironment?.id &&
get(deployableEnvironmentsReadyAtom) &&
get(deploymentOptionsReadyAtom) &&
get(requiredBindingsReadyAtom) &&
get(requiredEnvVarsReadyAtom) &&
get(submittedReleaseReadyAtom),
)
})
export const canSkipDeploymentAtom = atom((get) => {
return get(submittedReleaseReadyAtom) && get(deploymentOptionsReadyAtom)
})
export const selectBindingAtom = atom(null, (get, set, slot: string, value: string) => {
set(manualBindingSelectionsAtom, {
...get(manualBindingSelectionsAtom),
[slot]: value,
})
})
export const setEnvVarAtom = atom(null, (get, set, key: string, value: EnvVarValueSelection) => {
set(envVarValuesAtom, {
...get(envVarValuesAtom),
[key]: value,
})
})