fabian-hiller / valibot

The modular and type safe schema library for validating structural data šŸ¤–
https://valibot.dev
MIT License
6.33k stars 204 forks source link

Add clear property to indicate invalid property path #818

Closed ZilvinasAbr closed 2 months ago

ZilvinasAbr commented 2 months ago

First of all, thanks for a great library!

There is a small improvement I thought would help me and others. A common case of using Valibot is to parse environment variables. I often get valibot errors on build time since I forget to add some env variables. An issue is that on deployment logs it does not tell which property has failed to be parsed. Example log I just recently got:

#14 89.87 web:build: {
#14 89.87 web:build: kind: 'schema',
#14 89.87 web:build: type: 'string',
#14 89.87 web:build: input: undefined,
#14 89.87 web:build: expected: 'string',
#14 89.87 web:build: received: 'undefined',
#14 89.87 web:build: message: 'Invalid type: Expected string but received undefined',
#14 89.87 web:build: requirement: undefined,
#14 89.87 web:build: path: [Array],
#14 89.87 web:build: issues: undefined,
#14 89.87 web:build: lang: undefined,
#14 89.87 web:build: abortEarly: undefined,
#14 89.87 web:build: abortPipeEarly: undefined
#14 89.87 web:build: }

I guess the failed key would be seen in the path, but the issue is that in logs it does not expand the Array and just show [Array].

Is there any way possible to maybe somehow show the failed property path?

fabian-hiller commented 2 months ago

Thank you for your kind words. Can you share your code that logs this information to the console? Maybe flatten or getDotPath is what you are looking for.

ZilvinasAbr commented 2 months ago

@fabian-hiller Hi, thanks for suggestions, they might work, will try them when I have time. Though in my case I am actually not handling the errors. And an issue might be that I am doing the parsing in file global scope, e.g.:

// serverEnvs.mjs

const serverEnvsSchema = object({
  SOME_ENV_VARIABLE: string()
})

export const serverEnvs = parse(serverEnvSchema, { SOME_ENV_VARIABLE: process.env['SOME_ENV_VARIABLE'] })

// next.config.mjs
import { serverEnvs } from "./serverEnvs"

// Importing it here makes it validate on build-time of Next.js
fabian-hiller commented 2 months ago

Can you try if this works?

import * as v from 'valibot';

const ServerEnvsSchema = v.object({
  SOME_ENV_VARIABLE: v.string(),
});

const result = v.safeParse(ServerEnvsSchema, process.env);

if (result.issues) {
  console.error('Issues:', v.flatten(result.issues).nested);
  throw new Error('Invalid environment variables');
}

export const serverEnvs = result.output;
ZilvinasAbr commented 2 months ago

Yeah, silly me, this looks exactly what I would need, thank you! I guess we can close the issue since no changes to valibot are necessary to be made.

For some reason I thought only about using try..catch to handle any errors and edit the error output, forgot I can use safeParse

fabian-hiller commented 2 months ago

Yeah, my first attempt was also with try/catch šŸ™ƒ

fabian-hiller commented 2 months ago

Note that you can also write a loop to freely format and log the issues:

for (const issue of result.issues) {
  console.error(v.getDotPath(issue), issue.message);
}