Files
dify/web/utils/var.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

192 lines
4.8 KiB
TypeScript

import type { InputVar } from '@/app/components/workflow/types'
import type { I18nKeysByPrefix } from '@/types/i18n'
import {
CONTEXT_PLACEHOLDER_TEXT,
HISTORY_PLACEHOLDER_TEXT,
PRE_PROMPT_PLACEHOLDER_TEXT,
QUERY_PLACEHOLDER_TEXT,
} from '@/app/components/base/prompt-editor/constants'
import { InputVarType } from '@/app/components/workflow/types'
import {
getMaxVarNameLength,
MARKETPLACE_URL_PREFIX,
MAX_VAR_KEY_LENGTH,
VAR_ITEM_TEMPLATE,
VAR_ITEM_TEMPLATE_IN_WORKFLOW,
} from '@/config'
import { env } from '@/env'
const otherAllowedRegex = /^\w+$/
export const getNewVar = (key: string, type: string) => {
const { ...rest } = VAR_ITEM_TEMPLATE
if (type !== 'string') {
return {
...rest,
type: type || 'string',
key,
name: key.slice(0, getMaxVarNameLength(key)),
}
}
return {
...VAR_ITEM_TEMPLATE,
type: type || 'string',
key,
name: key.slice(0, getMaxVarNameLength(key)),
}
}
export const getNewVarInWorkflow = (key: string, type = InputVarType.textInput): InputVar => {
const { ...rest } = VAR_ITEM_TEMPLATE_IN_WORKFLOW
if (type !== InputVarType.textInput) {
return {
...rest,
type,
variable: key,
label: key.slice(0, getMaxVarNameLength(key)),
}
}
return {
...VAR_ITEM_TEMPLATE_IN_WORKFLOW,
type,
variable: key,
label: key.slice(0, getMaxVarNameLength(key)),
placeholder: '',
default: '',
hint: '',
}
}
type VarKeyErrorMessageKey = I18nKeysByPrefix<'appDebug', 'varKeyError.'>
export const checkKey = (
key: string,
canBeEmpty?: boolean,
_keys?: string[],
): true | VarKeyErrorMessageKey => {
if (key.length === 0 && !canBeEmpty) return 'canNoBeEmpty'
if (canBeEmpty && key === '') return true
if (key.length > MAX_VAR_KEY_LENGTH) return 'tooLong'
if (otherAllowedRegex.test(key)) {
if (/\d/.test(key[0]!)) return 'notStartWithNumber'
return true
}
return 'notValid'
}
type CheckKeysResult =
| { isValid: true; errorKey: ''; errorMessageKey: '' }
| { isValid: false; errorKey: string; errorMessageKey: VarKeyErrorMessageKey }
export const checkKeys = (keys: string[], canBeEmpty?: boolean): CheckKeysResult => {
let isValid = true
let errorKey = ''
let errorMessageKey: VarKeyErrorMessageKey | '' = ''
keys.forEach((key) => {
if (!isValid) return
const res = checkKey(key, canBeEmpty)
if (res !== true) {
isValid = false
errorKey = key
errorMessageKey = res
}
})
return { isValid, errorKey, errorMessageKey } as CheckKeysResult
}
export const hasDuplicateStr = (strArr: string[]) => {
const strObj: Record<string, number> = {}
strArr.forEach((str) => {
if (strObj[str]) strObj[str] += 1
else strObj[str] = 1
})
return !!Object.keys(strObj).find((key) => strObj[key]! > 1)
}
const varRegex = /\{\{([a-z_]\w*)\}\}/gi
export const getVars = (value: string) => {
if (!value) return []
const keys =
value
.match(varRegex)
?.filter((item) => {
return ![
CONTEXT_PLACEHOLDER_TEXT,
HISTORY_PLACEHOLDER_TEXT,
QUERY_PLACEHOLDER_TEXT,
PRE_PROMPT_PLACEHOLDER_TEXT,
].includes(item)
})
.map((item) => {
return item.replace('{{', '').replace('}}', '')
})
.filter((key) => key.length <= MAX_VAR_KEY_LENGTH) || []
const keyObj: Record<string, boolean> = {}
// remove duplicate keys
const res: string[] = []
keys.forEach((key) => {
if (keyObj[key]) return
keyObj[key] = true
res.push(key)
})
return res
}
// Set the value of basePath
// example: /dify
export const basePath = env.NEXT_PUBLIC_BASE_PATH
type MarketplaceUrlOptions = {
source?: string
}
const getUrlOrigin = (url?: string) => {
if (!url) return undefined
try {
return new URL(url).origin
} catch {
return undefined
}
}
const marketplaceSource = getUrlOrigin(env.NEXT_PUBLIC_WEB_PREFIX)
export function getMarketplaceUrl(
path: string,
params?: Record<string, string | undefined>,
options?: MarketplaceUrlOptions,
) {
const searchParams = new URLSearchParams()
const source = getUrlOrigin(options?.source) ?? marketplaceSource
if (source) searchParams.set('source', source)
if (params) {
Object.keys(params).forEach((key) => {
const value = params[key]
if (value !== undefined && value !== null) searchParams.append(key, value)
})
}
const queryString = searchParams.toString()
return queryString
? `${MARKETPLACE_URL_PREFIX}${path}?${queryString}`
: `${MARKETPLACE_URL_PREFIX}${path}`
}
export const replaceSpaceWithUnderscoreInVarNameInput = (input: HTMLInputElement) => {
const start = input.selectionStart
const end = input.selectionEnd
input.value = input.value.replaceAll(' ', '_')
if (start !== null && end !== null) input.setSelectionRange(start, end)
}