qwik
qwik copied to clipboard
feat: add Valibot support with `valibot$` to qwik-city
Overview
Adds Valibot support with a valibot$ function similarly to how Zod is supported by zod$.
Fixes #4924
What is it?
- [x] Feature / enhancement
- [ ] Bug
- [ ] Docs / tests / types / typos
Description
Requires:
valibot
Use cases and why
So you can use Valibot to validate your actions
Checklist:
- [x] My code follows the developer guidelines of this project
- [x] I have performed a self-review of my own code
- [x] I have made corresponding changes to the documentation
- [ ] Added new tests to cover the fix / functionality
Run & review this pull request in StackBlitz Codeflow.
Deploy Preview for qwik-insights canceled.
| Name | Link |
|---|---|
| Latest commit | bfb1d8a25fc15ca41ed58a0a3c7c2025bc0293db |
| Latest deploy log | https://app.netlify.com/sites/qwik-insights/deploys/651de4314b616a0008a4368f |
Thanks for your nice PR, can you add the documentation for this please?
Thanks for your nice PR, can you add the documentation for this please?
Sure. Not done, yet. Will update docs tomorrow! Just wanted to share what I had so far.
@fabian-hiller Is there a way with Valibot to check if a value is an ObjectSchema at runtime?
@brandonpittman yes, this should work via the .schema key: https://github.com/fabian-hiller/valibot/blob/v0.13.1/library/src/schemas/object/object.ts#L65
And via .async you can find out if it needs to be validated async: https://github.com/fabian-hiller/valibot/blob/v0.13.1/library/src/schemas/object/object.ts#L75
Note that you must also include BaseSchemaAsync and ObjectShapeAsync to support async validation.
Note that you must also include
BaseSchemaAsyncandObjectShapeAsyncto support async validation.
@fabian-hiller
It's not clear if we need async support. I've updated my PR with working code that satisfies TypeScript. I've removed any async types though. Can you take a look, please?
It's not clear if we need async support.
Since the validation is done in an async function, we could enable async validation with safeParseAsync, BaseSchemaAsync and ObjectShapeAsync. This would allow, for example, to do network requests as part of the validation. If someone uses only sync validation, this is not a disadvantage. async is compatible with sync, but sync is not compatible with async.
If you want to add async support, you need to replace safeParse with safePareseAsync and also add BaseSchemaAsync and ObjectShapeAsync to the types.
If you want to add async support, you need to replace
safeParsewithsafePareseAsyncand also addBaseSchemaAsyncandObjectShapeAsyncto the types.
Okay. Will update it. Thanks.
You must not remove BaseSchema and ObjectShape from the types. Otherwise the sync validation will not be accepted.
You must not remove
BaseSchemaandObjectShapefrom the types. Otherwise the sync validation will not be accepted.
@fabian-hiller
Should I use BaseSchema instead of ObjectSchema<ObjectShape>? When I tried BaseSchema the .schema === "object' check encountered a type error.
Do I need to do something like obj.async ? safeParseAsync(obj, data) : safeParse(obj, data) or can I just give safeParseAsync a synchronous schema?
Thanks for working on this! β€οΈ
Should I use
BaseSchemainstead ofObjectSchema<ObjectShape>? When I triedBaseSchemathe.schema === "object'check encountered a type error.
I think I would write BaseSchema | BaseSchemaAsync | ObjectShape | ObjectShapeAsync. If we recognize that an object with typeof obj._parse === "function" is passed, it is a scheme that can be passed directly in safeParseAsync. Otherwise the object must be passed into objectAsync before we call safeParseAsync.
Do I need to do something like
obj.async ? safeParseAsync(obj, data) : safeParse(obj, data)or can I just givesafeParseAsynca synchronous schema?
This is not required. safeParseAsync can also handle BaseSchema.
Thank you very much @brandonpittman and @fabian-hiller π
One thought from my side regarding exporting both libs now from the qwik-city pkg is, if we should think about flag the zod$ and z exports as deprecated? it shouldn't be our long term goal to keep both within the framework imo. end users would still be able to additionally add zod$ if they want to keep it. @mhevery would like to pass that to you and the team π
@mhevery
I updated the validation heading structure because I added separate Valibot sections. Is this okay?
No problems with the runtime code, but there's a lot of Zod-specific types mixed into the routeAction-adjacent types (starting here: https://github.com/BuilderIO/qwik/blob/d27177d1e4749805492d23164f9e655142f24601/packages/qwik-city/runtime/src/types.ts#L810-L813C2).
Going to need to update them to play nicely with Valibot types.
Thank you @brandonpittman for your efforts! π
Thank you @brandonpittman for your efforts! π
@fabian-hiller I think the last thing should be adjusting the action value type. After removing the any, itβs not correctly type hinting the error key when failed is true. I still need to figure that out.
Can you highlight what you mean? Then I can have a look at it.
@fabian-hiller
starts here: https://github.com/BuilderIO/qwik/blob/3d4715e4a4b76eed3db3163f7850bee8d7dfc089/packages/qwik-city/runtime/src/types.ts#L827-L851
continues through to here: https://github.com/BuilderIO/qwik/blob/3d4715e4a4b76eed3db3163f7850bee8d7dfc089/packages/qwik-city/runtime/src/types.ts#L419-L608
The types for the routeAction$ success value seem fine, but when there's an error, I had trouble getting the error values to correctly type hint. TypeScript doesn't think nested will exist when action.value.failed === true.
https://github.com/BuilderIO/qwik/blob/7412c64fcf85999fc347d64316c340611f1e1ea4/packages/docs/src/routes/demo/valibot/simple/index.tsx#L34
I also haven't been able to get correct types for returned values in the template. Getting TS errors that say the value isn't valid JSXβbut it displays just fine in practice.
https://github.com/BuilderIO/qwik/blob/7412c64fcf85999fc347d64316c340611f1e1ea4/packages/docs/src/routes/demo/valibot/simple/index.tsx#L54
Thanks for the info. I will have a closer look next week.
Thanks for the info. I will have a closer look next week.
Hopefully I can figure it out before then. π
Ok. Sorry. I'm moving this weekend. Otherwise I would have looked at it right away.
Ok. Sorry. I'm moving this weekend. Otherwise I would have looked at it right away.
@fabian-hiller Sorry, I hope that didn't sound like I was rushing you. I just meant I really want to solve the problem. I'm very grateful for all the help you've given me so far. ππ»
I will try to review the changes in the next few days.
Thank you @brandonpittman. I will check your changes tomorrow.
@fabian-hiller
Is there any way to get type hints out of flatten()? FlatErrors isn't generic, so I can't see a way to pass a schema type along to get type hints from the return value of flatten().
Currently this is not possible. Do you know if this works with Zod? I think it will be difficult to make it completely type-safe.
Currently this is not possible. Do you know if this works with Zod? I think it will be difficult to make it completely type-safe.
@fabian-hiller
Zod has a couple helpers for inferring flattened error types.
https://github.com/colinhacks/zod/blob/f59be093ec21430d9f32bbcb628d7e39116adf34/src/ZodError.ts#L7-L16