Accept init shapes in Standard Schema validation - #169
Conversation
|
Thanks for the PR! I need some help understanding the changes.
I think that means it should be possible to simplify the changes?
Makes sense. When create throws, there is nothing to validate further. So I believe that the new |
The Standard Schema validator previously required a message instance created with create(). Plain objects failed with "Cannot validate message undefined" before any rule was evaluated, even for valid data. Standard Schema consumers usually hold plain values, not message instances: form libraries validate form state, and RPC frameworks validate deserialized JSON payloads. Requiring create() at every callsite defeats the interop the interface exists for. createStandardSchema now converts a plain object to a message with create() before validating; message instances are still validated directly. Its declared types are unchanged, so existing consumers, such as TanStack Form with defaultValues: create(Schema), see no type-level change. The new createStandardSchemaInit shares the same runtime but declares MessageInitShape as its input type, for consumers whose values are plain objects: form state typed from plain default values, or RPC input validation where the schema's input type dictates what callers may pass. Errors thrown by create() for malformed init values are reported as issues instead of escaping the validator. Fixes bufbuild#95.
a7fc1f7 to
ac1b169
Compare
|
Yes, you're right on both counts. We can just return |
create() returns message instances as-is and has no throw path.
|
I also realized that |
Fixes #95.
createStandardSchema()only accepts message instances. A plain object fails before any rule is evaluated, even when the data is valid:Standard Schema consumers usually hold plain values, not message instances: form state, or deserialized RPC payloads (e.g. TanStack Start's
inputValidator).Changes:
validate()now converts plain objects to messages withcreate()before validating. Message instances are validated directly, as before. Errors thrown bycreate()become issues, since Standard Schema validators must not throw.createStandardSchema()keeps its declared types. The Standard Schema input parameter is covariant, so widening it toMessageInitShapewould break existing consumers, e.g. TanStack Form withdefaultValues: create(Schema).createStandardSchemaInit()shares the runtime but declaresMessageInitShapeas its input, for consumers where the schema's input type dictates what callers pass.MessageInitShapeis not assignable toMessageShape, so one input type cannot serve both.