diff --git a/src/valibot/index.ts b/src/valibot/index.ts index 187d8e76..327f540b 100644 --- a/src/valibot/index.ts +++ b/src/valibot/index.ts @@ -221,8 +221,13 @@ function generateFieldTypeValibotSchema(config: ValidationSchemaPluginConfig, vi const actions = actionsFromDirectives(config, field); - if (isNonNullType(parentType)) - return pipeSchemaAndActions(gen, actions); ; + if (isNonNullType(parentType)) { + if (visitor.shouldEmitAsNotAllowEmptyString(type.name.value)) { + actions.push('v.minLength(1)'); + } + + return pipeSchemaAndActions(gen, actions); + } return `v.nullish(${pipeSchemaAndActions(gen, actions)})`; } diff --git a/tests/valibot.spec.ts b/tests/valibot.spec.ts index 61f5a535..ad77d5f6 100644 --- a/tests/valibot.spec.ts +++ b/tests/valibot.spec.ts @@ -129,7 +129,28 @@ describe('valibot', () => { " `); }) - it.todo('nested input object') + it('nested input object', async () => { + const schema = buildSchema(/* GraphQL */ ` + input NestedInput { + child: NestedInput + childrens: [NestedInput] + } + `); + const scalars = undefined + const result = await plugin(schema, [], { schema: 'valibot', scalars }, {}); + + expect(result.content).toMatchInlineSnapshot(` + " + + export function NestedInputSchema(): v.GenericSchema { + return v.object({ + child: v.lazy(() => v.nullish(NestedInputSchema())), + childrens: v.nullish(v.array(v.lazy(() => v.nullable(NestedInputSchema())))) + }) + } + " + `) + }) it('enum', async () => { const schema = buildSchema(/* GraphQL */ ` enum PageType { @@ -301,8 +322,82 @@ describe('valibot', () => { " `); }); - it.todo('with notAllowEmptyString') - it.todo('with notAllowEmptyString issue #386') + it('with notAllowEmptyString', async () => { + const schema = buildSchema(/* GraphQL */ ` + input PrimitiveInput { + a: ID! + b: String! + c: Boolean! + d: Int! + e: Float! + } + `); + const result = await plugin( + schema, + [], + { + schema: 'valibot', + notAllowEmptyString: true, + scalars: { + ID: 'string', + }, + }, + {}, + ); + expect(result.content).toMatchInlineSnapshot(` + " + + export function PrimitiveInputSchema(): v.GenericSchema { + return v.object({ + a: v.pipe(v.string(), v.minLength(1)), + b: v.pipe(v.string(), v.minLength(1)), + c: v.boolean(), + d: v.number(), + e: v.number() + }) + } + " + `) + }) + it('with notAllowEmptyString issue #386', async () => { + const schema = buildSchema(/* GraphQL */ ` + input InputOne { + field: InputNested! + } + + input InputNested { + field: String! + } + `); + const result = await plugin( + schema, + [], + { + schema: 'valibot', + notAllowEmptyString: true, + scalars: { + ID: 'string', + }, + }, + {}, + ); + expect(result.content).toMatchInlineSnapshot(` + " + + export function InputOneSchema(): v.GenericSchema { + return v.object({ + field: v.lazy(() => InputNestedSchema()) + }) + } + + export function InputNestedSchema(): v.GenericSchema { + return v.object({ + field: v.pipe(v.string(), v.minLength(1)) + }) + } + " + `) + }) it('with scalarSchemas', async () => { const schema = buildSchema(/* GraphQL */ ` input ScalarsInput { @@ -338,8 +433,72 @@ describe('valibot', () => { " `) }); - it.todo('with typesPrefix') - it.todo('with typesSuffix') + it('with typesPrefix', async () => { + const schema = buildSchema(/* GraphQL */ ` + input Say { + phrase: String! + } + `); + const result = await plugin( + schema, + [], + { + schema: 'valibot', + typesPrefix: 'I', + importFrom: './types', + }, + {}, + ); + expect(result.prepend).toMatchInlineSnapshot(` + [ + "import * as v from 'valibot'", + "import { ISay } from './types'", + ] + `) + expect(result.content).toMatchInlineSnapshot(` + " + + export function ISaySchema(): v.GenericSchema { + return v.object({ + phrase: v.string() + }) + } + " + `) + }) + it('with typesSuffix', async () => { + const schema = buildSchema(/* GraphQL */ ` + input Say { + phrase: String! + } + `); + const result = await plugin( + schema, + [], + { + schema: 'valibot', + typesSuffix: 'I', + importFrom: './types', + }, + {}, + ); + expect(result.prepend).toMatchInlineSnapshot(` + [ + "import * as v from 'valibot'", + "import { SayI } from './types'", + ] + `) + expect(result.content).toMatchInlineSnapshot(` + " + + export function SayISchema(): v.GenericSchema { + return v.object({ + phrase: v.string() + }) + } + " + `) + }) it.todo('with default input values') describe('issues #19', () => { it('string field', async () => {