Skip to content

Add Standard Schema v1 support #54

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

Merged
merged 5 commits into from
Jun 27, 2025

Conversation

ichizero
Copy link
Contributor

Description

Closes #52

This PR introduces a new utility, createStandardSchema, which generates a Standard Schema v1 compliant validator for Protobuf message types. The main features and changes are as follows:

  • Implements the StandardSchemaV1 interface, following the standard-schema specification.
  • Provides a validate method that returns results in the Standard Schema format, including detailed issues with error messages and paths.
  • Converts internal Violation objects to Standard Schema Issue objects, ensuring compatibility and clarity in error reporting.
  • Supports both input and output type inference via the types property.
  • Handles all validation outcomes: valid, invalid (with issues), and runtime errors.

This addition improves interoperability with tools and libraries that support the Standard Schema, and makes it easier to integrate Protobuf validation into broader validation workflows.

@CLAassistant
Copy link

CLAassistant commented Jun 24, 2025

CLA assistant check
All committers have signed the CLA.

@chrispine chrispine requested a review from timostamm June 24, 2025 20:06
@timostamm timostamm requested a review from paul-sachs June 24, 2025 20:06
Copy link
Member

@paul-sachs paul-sachs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All in all, a really nice addition. If we could just add some tests around the ValidTypes variants and add a comment on the one type oddity, I think this will make a really nice easy win.

*
* Copyright (c) 2024 Colin McDonnell
*/
export interface StandardSchemaV1<Input = unknown, Output = Input> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% clear on this but I wonder if we should just install the standardschema package and reexport those. The spec doesn't specify and suggests we can import or include here. This is the easiest approach I suppose.

@timostamm thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at arktype, this seems to be a the thing to do, redeclare these. So probably fine.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The FAQ says it's fine to copy and paste the types if you don't want the dependency. We don't want the dependency, so this approach looks good to me.

I don't think we should export the type from index.ts though. Can we remove the export?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also referred to the FAQ and concluded that it’s better not to add the dependency.

I’ve exported only the createStandardSchema function.
fixed c23dbae

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add an example test here as well. I know it's new to this repo, but one of the functionalities that standard schema affords is specifying different types for input and output (in our case MessageShape<Desc> and MessageValidType<Desc>). This way we can ensure that the generated types take into account things like required fields (removing the need for assertions for existence).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On looking over this again, I think we can skip adding an explicit test here and instead just write a tiny little bit of typescript that takes advantage of the MessageValidType. For example, if we use the OrderSchema in this file, and ensure that result.value has a user field without needing to use result.value.user? to conditionally access, that should be sufficient.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback!

I thought it would be helpful to include an example demonstrating how to use valid-type with standard-schema, so I updated it to follow the style of valid-types.js.

updated 91e89cc

Comment on lines +124 to +125
input: undefined as unknown as MessageShape<Desc>,
output: undefined as unknown as MessageValidType<Desc>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This strikes me as weird, ideally we could at least reference why these values need to exist but are in fact undefined. Maybe this is just an element of standard schema. Add a comment to indicate why these need to exist (ideally with references).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at arktype, they seem to just leave it out entirely and also refine the vendor value. I'm not sure we necessarily need to define the vendor stuff, but it seems like types might not actually be needed here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The types property is necessary for TypeScript’s type inference to work correctly, even though it’s not used at runtime.

types is used to associate type metadata with the schema. This property should be declared on the schema's type, but is not required to exist at runtime. Authors implementing a schema using a class are encouraged to use TypeScript's declare keyword or other means to avoid runtime overhead. InferInput and InferOutput can be used to extract their corresponding types.

https://github.com/standard-schema/standard-schema/blob/4db8364a/packages/web/index.md#the-interface

I’ve added a comment to clarify this. d230997

@ichizero ichizero changed the title feat: Add Standard Schema v1 support Add Standard Schema v1 support Jun 27, 2025
@ichizero ichizero requested a review from paul-sachs June 27, 2025 17:49
Copy link
Member

@paul-sachs paul-sachs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great. Let's merge it. Thanks for this!

@paul-sachs paul-sachs merged commit 6b3e4a7 into bufbuild:main Jun 27, 2025
9 checks passed
@paul-sachs paul-sachs mentioned this pull request Jun 27, 2025
paul-sachs added a commit that referenced this pull request Jun 27, 2025
## What's Changed
* Add Standard Schema v1 support by @ichizero in
#54

## New Contributors
* @ichizero made their first contribution in
#54

**Full Changelog**:
v0.4.0...v0.5.0
@timostamm timostamm mentioned this pull request Jul 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature Request] Add Standard Schema v1 support
4 participants