Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

discriminated union with dataType json causing SchemaError #519

Open
konstantinblaesi opened this issue Nov 27, 2024 · 1 comment
Open
Labels
bug Something isn't working

Comments

@konstantinblaesi
Copy link

konstantinblaesi commented Nov 27, 2024

Error trace

SchemaError: [addresses.additional.name] No default value specified for field (can be undefined, but must be explicit)
    at Defaults_traverseAndReplace (/projects/sveltekit-superforms/src/lib/errors.ts:290:11)
    at Errors_traverseAndReplace (/projects/sveltekit-superforms/src/lib/errors.ts:237:4)
    at Data_traverse (/projects/sveltekit-superforms/src/lib/errors.ts:221:3)
    at Module.replaceInvalidDefaults (/projects/sveltekit-superforms/src/lib/errors.ts:303:10)
    at Module.superValidate (/projects/sveltekit-superforms/src/lib/superValidate.ts:139:5)
    at /projects/sveltekit-superforms/src/tests/demo.test.ts:55:13
    at runTest (file:///projects/sveltekit-superforms/node_modules/.pnpm/@[email protected]/node_modules/@vitest/runner/dist/index.js:781:11)
    at runSuite (file:///projects/sveltekit-superforms/node_modules/.pnpm/@[email protected]/node_modules/@vitest/runner/dist/index.js:909:15)
    at runSuite (file:///projects/sveltekit-superforms/node_modules/.pnpm/@[email protected]/node_modules/@vitest/runner/dist/index.js:909:15)
    at runFiles (file:///projects/sveltekit-superforms/node_modules/.pnpm/@[email protected]/node_modules/@vitest/runner/dist/index.js:958:5) {
  path: 'addresses.additional.name'
}

From the repro: The testcase bad produces this error trace, testcase good works
Basically the feature is to provide one of three possible address types, something like

addresses.additional.type = { 'type1', 'type2', 'none' }

where the 'none' type has no additional fields

Repro

Code
import { zod } from "$lib/adapters/zod.js";
import { superValidate } from "$lib/superValidate.js";
import { describe, test } from 'vitest';
import { z } from "zod";


describe("Demo", () => {
    test("Bad", async () => {
        const schema = zod(
            z.object({
                addresses: z.object({
                    additional: z.discriminatedUnion('type', [
                        z.object({
                            type: z.literal('poBox'),
                            name: z.string().min(1, 'err min len').max(10, 'err max len')
                        }),
                        z.object({
                            type: z.literal('none'),
                        }),
                    ]).default({ type: 'none' })
                })
            })
        )

        const formInput = new FormData()
        formInput.set(
            '__superform_json',
            JSON.stringify([
                {
                    addresses: 1
                },
                {
                    additional: 2
                },
                {
                    type: 3,
                    name: 4
                },
                'poBox',
                ''
            ])
        )
        try {
            await superValidate(formInput, schema)
        } catch (err) {
            console.error(err)
            //
            throw err
        }
    })

    test("Good", async () => {
        const schema = zod(
            z.object({
                addresses: z.object({
                    additional: z.discriminatedUnion('type', [
                        z.object({
                            type: z.literal('poBox'),
                            name: z.string().min(1, 'err min len').max(10, 'err max len')
                        }),
                        z.object({
                            type: z.literal('none'),
                        }),
                    ]).default({ type: 'poBox', name: '' })
                })
            })
        )

        const formInput = new FormData()
        formInput.set(
            '__superform_json',
            JSON.stringify([
                {
                    addresses: 1
                },
                {
                    additional: 2
                },
                {
                    type: 3,
                    name: 4
                },
                'poBox',
                ''
            ])
        )
        try {
            await superValidate(formInput, schema)
        } catch (err) {
            console.error(err)
            throw err
        }
    })
})

Should this kind of schema work ? Should this be modeled differently?

@konstantinblaesi konstantinblaesi added the bug Something isn't working label Nov 27, 2024
@ciscoheat
Copy link
Owner

You can't stringify __superform_json directly, you need to use devalue. Try that and see if it works. Otherwise you should try to add a default value to the schema, as suggested by the error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants