42
packages/forge/blocks/anthropic/actions/generateVariables.ts
Normal file
42
packages/forge/blocks/anthropic/actions/generateVariables.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { createAction } from '@typebot.io/forge'
|
||||
import { auth } from '../auth'
|
||||
import { isDefined } from '@typebot.io/lib'
|
||||
import { createAnthropic } from '@ai-sdk/anthropic'
|
||||
import { parseGenerateVariablesOptions } from '@typebot.io/openai-block/shared/parseGenerateVariablesOptions'
|
||||
import { runGenerateVariables } from '@typebot.io/openai-block/shared/runGenerateVariables'
|
||||
import { anthropicModels } from '../constants'
|
||||
|
||||
export const generateVariables = createAction({
|
||||
name: 'Generate variables',
|
||||
auth,
|
||||
options: parseGenerateVariablesOptions({ modelFetch: anthropicModels }),
|
||||
turnableInto: [
|
||||
{
|
||||
blockId: 'openai',
|
||||
},
|
||||
{
|
||||
blockId: 'mistral',
|
||||
},
|
||||
],
|
||||
getSetVariableIds: (options) =>
|
||||
options.variablesToExtract?.map((v) => v.variableId).filter(isDefined) ??
|
||||
[],
|
||||
run: {
|
||||
server: ({ credentials, options, variables, logs }) => {
|
||||
if (credentials?.apiKey === undefined)
|
||||
return logs.add('No API key provided')
|
||||
|
||||
if (options.model === undefined) return logs.add('No model provided')
|
||||
|
||||
return runGenerateVariables({
|
||||
model: createAnthropic({
|
||||
apiKey: credentials.apiKey,
|
||||
})(options.model),
|
||||
prompt: options.prompt,
|
||||
variablesToExtract: options.variablesToExtract,
|
||||
variables,
|
||||
logs,
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -2,6 +2,7 @@ import { createBlock } from '@typebot.io/forge'
|
||||
import { AnthropicLogo } from './logo'
|
||||
import { auth } from './auth'
|
||||
import { createChatMessage } from './actions/createChatMessage'
|
||||
import { generateVariables } from './actions/generateVariables'
|
||||
|
||||
export const anthropicBlock = createBlock({
|
||||
id: 'anthropic',
|
||||
@@ -9,5 +10,5 @@ export const anthropicBlock = createBlock({
|
||||
tags: ['ai', 'chat', 'completion', 'claude', 'anthropic'],
|
||||
LightLogo: AnthropicLogo,
|
||||
auth,
|
||||
actions: [createChatMessage],
|
||||
actions: [createChatMessage, generateVariables],
|
||||
})
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "0.20.6",
|
||||
"ai": "3.1.12",
|
||||
"@ai-sdk/anthropic": "0.0.21",
|
||||
"@typebot.io/openai-block": "workspace:*",
|
||||
"ai": "3.1.34",
|
||||
"ky": "1.2.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,6 @@
|
||||
"typescript": "5.4.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"ai": "3.1.12"
|
||||
"ai": "3.1.34"
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,8 @@ import { isDefined } from '@typebot.io/lib'
|
||||
import { auth } from '../auth'
|
||||
import { parseMessages } from '../helpers/parseMessages'
|
||||
import { createMistral } from '@ai-sdk/mistral'
|
||||
import { apiBaseUrl } from '../constants'
|
||||
import ky from 'ky'
|
||||
import { generateText, streamText } from 'ai'
|
||||
import { fetchModels } from '../helpers/fetchModels'
|
||||
|
||||
const nativeMessageContentSchema = {
|
||||
content: option.string.layout({
|
||||
@@ -98,19 +97,7 @@ export const createChatCompletion = createAction({
|
||||
{
|
||||
id: 'fetchModels',
|
||||
dependencies: [],
|
||||
fetch: async ({ credentials }) => {
|
||||
if (!credentials?.apiKey) return []
|
||||
|
||||
const { data } = await ky
|
||||
.get(apiBaseUrl + '/v1/models', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${credentials.apiKey}`,
|
||||
},
|
||||
})
|
||||
.json<{ data: { id: string }[] }>()
|
||||
|
||||
return data.map((model) => model.id)
|
||||
},
|
||||
fetch: fetchModels,
|
||||
},
|
||||
],
|
||||
run: {
|
||||
|
||||
53
packages/forge/blocks/mistral/actions/generateVariables.ts
Normal file
53
packages/forge/blocks/mistral/actions/generateVariables.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { createAction } from '@typebot.io/forge'
|
||||
import { auth } from '../auth'
|
||||
import { isDefined } from '@typebot.io/lib'
|
||||
import { createMistral } from '@ai-sdk/mistral'
|
||||
import { fetchModels } from '../helpers/fetchModels'
|
||||
import { parseGenerateVariablesOptions } from '@typebot.io/openai-block/shared/parseGenerateVariablesOptions'
|
||||
import { runGenerateVariables } from '@typebot.io/openai-block/shared/runGenerateVariables'
|
||||
|
||||
export const generateVariables = createAction({
|
||||
name: 'Generate variables',
|
||||
auth,
|
||||
options: parseGenerateVariablesOptions({ modelFetch: 'fetchModels' }),
|
||||
fetchers: [
|
||||
{
|
||||
id: 'fetchModels',
|
||||
dependencies: [],
|
||||
fetch: fetchModels,
|
||||
},
|
||||
],
|
||||
turnableInto: [
|
||||
{
|
||||
blockId: 'openai',
|
||||
},
|
||||
{
|
||||
blockId: 'anthropic',
|
||||
transform: (options) => ({
|
||||
...options,
|
||||
model: undefined,
|
||||
}),
|
||||
},
|
||||
],
|
||||
getSetVariableIds: (options) =>
|
||||
options.variablesToExtract?.map((v) => v.variableId).filter(isDefined) ??
|
||||
[],
|
||||
run: {
|
||||
server: ({ credentials, options, variables, logs }) => {
|
||||
if (credentials?.apiKey === undefined)
|
||||
return logs.add('No API key provided')
|
||||
|
||||
if (options.model === undefined) return logs.add('No model provided')
|
||||
|
||||
return runGenerateVariables({
|
||||
model: createMistral({
|
||||
apiKey: credentials.apiKey,
|
||||
})(options.model),
|
||||
variablesToExtract: options.variablesToExtract,
|
||||
prompt: options.prompt,
|
||||
variables,
|
||||
logs,
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
20
packages/forge/blocks/mistral/helpers/fetchModels.ts
Normal file
20
packages/forge/blocks/mistral/helpers/fetchModels.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import ky from 'ky'
|
||||
import { apiBaseUrl } from '../constants'
|
||||
|
||||
export const fetchModels = async ({
|
||||
credentials,
|
||||
}: {
|
||||
credentials?: { apiKey?: string }
|
||||
}) => {
|
||||
if (!credentials?.apiKey) return []
|
||||
|
||||
const { data } = await ky
|
||||
.get(apiBaseUrl + '/v1/models', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${credentials.apiKey}`,
|
||||
},
|
||||
})
|
||||
.json<{ data: { id: string }[] }>()
|
||||
|
||||
return data.map((model) => model.id)
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { createBlock } from '@typebot.io/forge'
|
||||
import { MistralLogo } from './logo'
|
||||
import { auth } from './auth'
|
||||
import { createChatCompletion } from './actions/createChatCompletion'
|
||||
import { generateVariables } from './actions/generateVariables'
|
||||
|
||||
export const mistralBlock = createBlock({
|
||||
id: 'mistral',
|
||||
@@ -9,6 +10,6 @@ export const mistralBlock = createBlock({
|
||||
tags: ['ai', 'chat', 'completion'],
|
||||
LightLogo: MistralLogo,
|
||||
auth,
|
||||
actions: [createChatCompletion],
|
||||
actions: [createChatCompletion, generateVariables],
|
||||
docsUrl: 'https://docs.typebot.io/forge/blocks/mistral',
|
||||
})
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
"typescript": "5.4.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ai-sdk/mistral": "0.0.11",
|
||||
"ai": "3.1.12",
|
||||
"@ai-sdk/mistral": "0.0.18",
|
||||
"@typebot.io/openai-block": "workspace:*",
|
||||
"ai": "3.1.34",
|
||||
"ky": "1.2.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { createAction } from '@typebot.io/forge'
|
||||
import OpenAI, { ClientOptions } from 'openai'
|
||||
import { defaultOpenAIOptions } from '../constants'
|
||||
import { auth } from '../auth'
|
||||
import { baseOptions } from '../baseOptions'
|
||||
@@ -8,6 +7,7 @@ import { getChatCompletionSetVarIds } from '../shared/getChatCompletionSetVarIds
|
||||
import { runChatCompletion } from '../shared/runChatCompletion'
|
||||
import { runChatCompletionStream } from '../shared/runChatCompletionStream'
|
||||
import { getChatCompletionStreamVarId } from '../shared/getChatCompletionStreamVarId'
|
||||
import { fetchGPTModels } from '../helpers/fetchModels'
|
||||
|
||||
export const createChatCompletion = createAction({
|
||||
name: 'Create chat completion',
|
||||
@@ -45,34 +45,12 @@ export const createChatCompletion = createAction({
|
||||
{
|
||||
id: 'fetchModels',
|
||||
dependencies: ['baseUrl', 'apiVersion'],
|
||||
fetch: async ({ credentials, options }) => {
|
||||
if (!credentials?.apiKey) return []
|
||||
|
||||
const baseUrl = options?.baseUrl ?? defaultOpenAIOptions.baseUrl
|
||||
const config = {
|
||||
apiKey: credentials.apiKey,
|
||||
baseURL: baseUrl ?? defaultOpenAIOptions.baseUrl,
|
||||
defaultHeaders: {
|
||||
'api-key': credentials.apiKey,
|
||||
},
|
||||
defaultQuery: options?.apiVersion
|
||||
? {
|
||||
'api-version': options.apiVersion,
|
||||
}
|
||||
: undefined,
|
||||
} satisfies ClientOptions
|
||||
|
||||
const openai = new OpenAI(config)
|
||||
|
||||
const models = await openai.models.list()
|
||||
|
||||
return (
|
||||
models.data
|
||||
.filter((model) => model.id.includes('gpt'))
|
||||
.sort((a, b) => b.created - a.created)
|
||||
.map((model) => model.id) ?? []
|
||||
)
|
||||
},
|
||||
fetch: ({ credentials, options }) =>
|
||||
fetchGPTModels({
|
||||
apiKey: credentials?.apiKey,
|
||||
baseUrl: options.baseUrl,
|
||||
apiVersion: options.apiVersion,
|
||||
}),
|
||||
},
|
||||
],
|
||||
run: {
|
||||
|
||||
61
packages/forge/blocks/openai/actions/generateVariables.ts
Normal file
61
packages/forge/blocks/openai/actions/generateVariables.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { createAction } from '@typebot.io/forge'
|
||||
import { auth } from '../auth'
|
||||
import { baseOptions } from '../baseOptions'
|
||||
import { fetchGPTModels } from '../helpers/fetchModels'
|
||||
import { isDefined } from '@typebot.io/lib'
|
||||
import { runGenerateVariables } from '../shared/runGenerateVariables'
|
||||
import { parseGenerateVariablesOptions } from '../shared/parseGenerateVariablesOptions'
|
||||
import { createOpenAI } from '@ai-sdk/openai'
|
||||
|
||||
export const generateVariables = createAction({
|
||||
name: 'Generate variables',
|
||||
auth,
|
||||
baseOptions,
|
||||
options: parseGenerateVariablesOptions({ modelFetch: 'fetchModels' }),
|
||||
fetchers: [
|
||||
{
|
||||
id: 'fetchModels',
|
||||
dependencies: ['baseUrl', 'apiVersion'],
|
||||
fetch: ({ credentials, options }) =>
|
||||
fetchGPTModels({
|
||||
apiKey: credentials?.apiKey,
|
||||
baseUrl: options.baseUrl,
|
||||
apiVersion: options.apiVersion,
|
||||
}),
|
||||
},
|
||||
],
|
||||
turnableInto: [
|
||||
{
|
||||
blockId: 'mistral',
|
||||
},
|
||||
{
|
||||
blockId: 'anthropic',
|
||||
transform: (options) => ({
|
||||
...options,
|
||||
model: undefined,
|
||||
}),
|
||||
},
|
||||
],
|
||||
getSetVariableIds: (options) =>
|
||||
options.variablesToExtract?.map((v) => v.variableId).filter(isDefined) ??
|
||||
[],
|
||||
run: {
|
||||
server: ({ credentials, options, variables, logs }) => {
|
||||
if (credentials?.apiKey === undefined)
|
||||
return logs.add('No API key provided')
|
||||
|
||||
if (options.model === undefined) return logs.add('No model provided')
|
||||
|
||||
return runGenerateVariables({
|
||||
model: createOpenAI({
|
||||
apiKey: credentials.apiKey,
|
||||
compatibility: 'strict',
|
||||
})(options.model),
|
||||
prompt: options.prompt,
|
||||
variablesToExtract: options.variablesToExtract,
|
||||
variables,
|
||||
logs,
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
40
packages/forge/blocks/openai/helpers/fetchModels.ts
Normal file
40
packages/forge/blocks/openai/helpers/fetchModels.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import OpenAI, { ClientOptions } from 'openai'
|
||||
import { defaultOpenAIOptions } from '../constants'
|
||||
|
||||
type Props = {
|
||||
apiKey?: string
|
||||
baseUrl?: string
|
||||
apiVersion?: string
|
||||
}
|
||||
|
||||
export const fetchGPTModels = async ({
|
||||
apiKey,
|
||||
baseUrl = defaultOpenAIOptions.baseUrl,
|
||||
apiVersion,
|
||||
}: Props) => {
|
||||
if (!apiKey) return []
|
||||
|
||||
const config = {
|
||||
apiKey: apiKey,
|
||||
baseURL: baseUrl ?? defaultOpenAIOptions.baseUrl,
|
||||
defaultHeaders: {
|
||||
'api-key': apiKey,
|
||||
},
|
||||
defaultQuery: apiVersion
|
||||
? {
|
||||
'api-version': apiVersion,
|
||||
}
|
||||
: undefined,
|
||||
} satisfies ClientOptions
|
||||
|
||||
const openai = new OpenAI(config)
|
||||
|
||||
const models = await openai.models.list()
|
||||
|
||||
return (
|
||||
models.data
|
||||
.filter((model) => model.id.includes('gpt'))
|
||||
.sort((a, b) => b.created - a.created)
|
||||
.map((model) => model.id) ?? []
|
||||
)
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { createBlock } from '@typebot.io/forge'
|
||||
import { auth } from './auth'
|
||||
import { baseOptions } from './baseOptions'
|
||||
import { askAssistant } from './actions/askAssistant'
|
||||
import { generateVariables } from './actions/generateVariables'
|
||||
|
||||
export const openAIBlock = createBlock({
|
||||
id: 'openai' as const,
|
||||
@@ -14,6 +15,11 @@ export const openAIBlock = createBlock({
|
||||
DarkLogo: OpenAIDarkLogo,
|
||||
auth,
|
||||
options: baseOptions,
|
||||
actions: [createChatCompletion, askAssistant, createSpeech],
|
||||
actions: [
|
||||
createChatCompletion,
|
||||
askAssistant,
|
||||
generateVariables,
|
||||
createSpeech,
|
||||
],
|
||||
docsUrl: 'https://docs.typebot.io/forge/blocks/openai',
|
||||
})
|
||||
|
||||
@@ -7,16 +7,17 @@
|
||||
"author": "Baptiste Arnaud",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"ai": "3.1.12",
|
||||
"@ai-sdk/openai": "0.0.31",
|
||||
"ai": "3.1.34",
|
||||
"openai": "4.47.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typebot.io/forge": "workspace:*",
|
||||
"@typebot.io/tsconfig": "workspace:*",
|
||||
"@types/react": "18.2.15",
|
||||
"typescript": "5.4.5",
|
||||
"@typebot.io/lib": "workspace:*",
|
||||
"@typebot.io/tsconfig": "workspace:*",
|
||||
"@typebot.io/variables": "workspace:*",
|
||||
"ky": "1.2.4"
|
||||
"@types/react": "18.2.15",
|
||||
"ky": "1.2.4",
|
||||
"typescript": "5.4.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
import { option } from '@typebot.io/forge'
|
||||
import { z } from '@typebot.io/forge/zod'
|
||||
import { baseOptions } from '../baseOptions'
|
||||
|
||||
const extractInfoBaseShape = {
|
||||
variableId: option.string.layout({
|
||||
inputType: 'variableDropdown',
|
||||
}),
|
||||
description: option.string.layout({
|
||||
label: 'Description',
|
||||
accordion: 'Advanced',
|
||||
}),
|
||||
isRequired: option.boolean.layout({
|
||||
label: 'Is required',
|
||||
moreInfoTooltip:
|
||||
'If set to false, there is a chance the variable will be empty',
|
||||
accordion: 'Advanced',
|
||||
defaultValue: true,
|
||||
}),
|
||||
}
|
||||
|
||||
export const toolParametersSchema = option
|
||||
.array(
|
||||
option.discriminatedUnion('type', [
|
||||
option
|
||||
.object({
|
||||
type: option.literal('string'),
|
||||
})
|
||||
.extend(extractInfoBaseShape),
|
||||
option
|
||||
.object({
|
||||
type: option.literal('number'),
|
||||
})
|
||||
.extend(extractInfoBaseShape),
|
||||
option
|
||||
.object({
|
||||
type: option.literal('boolean'),
|
||||
})
|
||||
.extend(extractInfoBaseShape),
|
||||
option
|
||||
.object({
|
||||
type: option.literal('enum'),
|
||||
values: option
|
||||
.array(option.string)
|
||||
.layout({ itemLabel: 'possible value', mergeWithLastField: true }),
|
||||
})
|
||||
.extend(extractInfoBaseShape),
|
||||
])
|
||||
)
|
||||
.layout({
|
||||
itemLabel: 'variable mapping',
|
||||
accordion: 'Schema',
|
||||
})
|
||||
|
||||
type Props = {
|
||||
defaultModel?: string
|
||||
modelFetch: string | readonly [string, ...string[]]
|
||||
modelHelperText?: string
|
||||
}
|
||||
|
||||
export const parseGenerateVariablesOptions = ({
|
||||
defaultModel,
|
||||
modelFetch,
|
||||
modelHelperText,
|
||||
}: Props) =>
|
||||
option.object({
|
||||
model:
|
||||
typeof modelFetch === 'string'
|
||||
? option.string.layout({
|
||||
placeholder: 'Select a model',
|
||||
label: 'Model',
|
||||
defaultValue: defaultModel,
|
||||
fetcher: modelFetch,
|
||||
helperText: modelHelperText,
|
||||
})
|
||||
: option.enum(modelFetch).layout({
|
||||
placeholder: 'Select a model',
|
||||
label: 'Model',
|
||||
defaultValue: defaultModel,
|
||||
helperText: modelHelperText,
|
||||
}),
|
||||
prompt: option.string.layout({
|
||||
label: 'Prompt',
|
||||
placeholder: 'Type your text here',
|
||||
inputType: 'textarea',
|
||||
isRequired: true,
|
||||
moreInfoTooltip:
|
||||
'Meant to guide the model on what to generate. i.e. "Generate a role-playing game character", "Extract the company name from this text", etc.',
|
||||
}),
|
||||
variablesToExtract: toolParametersSchema,
|
||||
})
|
||||
|
||||
export type GenerateVariablesOptions = z.infer<
|
||||
ReturnType<typeof parseGenerateVariablesOptions>
|
||||
> &
|
||||
z.infer<typeof baseOptions>
|
||||
101
packages/forge/blocks/openai/shared/runGenerateVariables.ts
Normal file
101
packages/forge/blocks/openai/shared/runGenerateVariables.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { LogsStore, VariableStore } from '@typebot.io/forge/types'
|
||||
import {
|
||||
GenerateVariablesOptions,
|
||||
toolParametersSchema,
|
||||
} from './parseGenerateVariablesOptions'
|
||||
import { generateObject, LanguageModel } from 'ai'
|
||||
import { Variable } from '@typebot.io/variables/types'
|
||||
import { z } from '@typebot.io/forge/zod'
|
||||
import { isNotEmpty } from '@typebot.io/lib/utils'
|
||||
|
||||
type Props = {
|
||||
model: LanguageModel
|
||||
variables: VariableStore
|
||||
logs: LogsStore
|
||||
} & Pick<GenerateVariablesOptions, 'variablesToExtract' | 'prompt'>
|
||||
|
||||
export const runGenerateVariables = async ({
|
||||
variablesToExtract,
|
||||
model,
|
||||
prompt,
|
||||
variables: variablesStore,
|
||||
logs,
|
||||
}: Props) => {
|
||||
if (!prompt) return logs.add('No prompt provided')
|
||||
const variables = variablesStore.list()
|
||||
|
||||
const schema = convertVariablesToExtractToSchema({
|
||||
variablesToExtract,
|
||||
variables,
|
||||
})
|
||||
if (!schema) {
|
||||
logs.add('Could not parse variables to extract')
|
||||
return
|
||||
}
|
||||
|
||||
const hasOptionalVariables = variablesToExtract?.some(
|
||||
(variableToExtract) => variableToExtract.isRequired === false
|
||||
)
|
||||
|
||||
const { object } = await generateObject({
|
||||
model,
|
||||
schema,
|
||||
prompt:
|
||||
`${prompt}\n\nYou should generate a JSON object` +
|
||||
(hasOptionalVariables
|
||||
? ' and provide empty values if the information is not there or if you are unsure.'
|
||||
: '.'),
|
||||
})
|
||||
|
||||
Object.entries(object).forEach(([key, value]) => {
|
||||
if (value === null) return
|
||||
const existingVariable = variables.find((v) => v.name === key)
|
||||
if (!existingVariable) return
|
||||
variablesStore.set(existingVariable.id, value)
|
||||
})
|
||||
}
|
||||
|
||||
const convertVariablesToExtractToSchema = ({
|
||||
variablesToExtract,
|
||||
variables,
|
||||
}: {
|
||||
variablesToExtract: z.infer<typeof toolParametersSchema> | undefined
|
||||
variables: Variable[]
|
||||
}): z.ZodTypeAny | undefined => {
|
||||
if (!variablesToExtract || variablesToExtract?.length === 0) return
|
||||
|
||||
const shape: z.ZodRawShape = {}
|
||||
variablesToExtract.forEach((variableToExtract) => {
|
||||
if (!variableToExtract) return
|
||||
const matchingVariable = variables.find(
|
||||
(v) => v.id === variableToExtract.variableId
|
||||
)
|
||||
if (!matchingVariable) return
|
||||
switch (variableToExtract.type) {
|
||||
case 'string':
|
||||
shape[matchingVariable.name] = z.string()
|
||||
break
|
||||
case 'number':
|
||||
shape[matchingVariable.name] = z.number()
|
||||
break
|
||||
case 'boolean':
|
||||
shape[matchingVariable.name] = z.boolean()
|
||||
break
|
||||
case 'enum': {
|
||||
if (!variableToExtract.values || variableToExtract.values.length === 0)
|
||||
return
|
||||
shape[matchingVariable.name] = z.enum(variableToExtract.values as any)
|
||||
break
|
||||
}
|
||||
}
|
||||
if (variableToExtract.isRequired === false)
|
||||
shape[matchingVariable.name] = shape[matchingVariable.name].optional()
|
||||
|
||||
if (isNotEmpty(variableToExtract.description))
|
||||
shape[matchingVariable.name] = shape[matchingVariable.name].describe(
|
||||
variableToExtract.description
|
||||
)
|
||||
})
|
||||
|
||||
return z.object(shape)
|
||||
}
|
||||
@@ -23,6 +23,7 @@ export interface ZodLayoutMetadata<
|
||||
isHidden?: boolean | ((currentObj: Record<string, any>) => boolean)
|
||||
isDebounceDisabled?: boolean
|
||||
hiddenItems?: string[]
|
||||
mergeWithLastField?: boolean
|
||||
}
|
||||
|
||||
declare module 'zod' {
|
||||
|
||||
Reference in New Issue
Block a user