Skip to content

Override the types of input object custom scalar fields - #147

Closed
saga-dasgupta wants to merge 1 commit into
Shopify:mainfrom
saga-dasgupta:input-custom-scalar-overrides
Closed

saga-dasgupta wants to merge 1 commit into
Shopify:mainfrom
saga-dasgupta:input-custom-scalar-overrides

Conversation

@saga-dasgupta

@saga-dasgupta saga-dasgupta commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

query takes custom_scalar_overrides to give a custom scalar in a query's output a specific Rust type. Input objects have no equivalent, so a field typed with a catch-all scalar such as JSON can only be the scalar's type, usually an untyped value.

This adds the same option to typegen, for custom scalar fields of input objects:

#[typegen([
    scalar MyScalar
    input MyInput { myScalar: MyScalar, myScalarList: [MyScalar!]! }
    ...
], custom_scalar_overrides = {
    "MyInput.myScalar" => ::std::primitive::i32,
    "MyInput.myScalarList" => ::std::primitive::i32,
})]
  • Paths are "InputObject.field", and the field's base type must be a custom scalar. Lists and nullability are kept, so myScalar above becomes Option<i32> and myScalarList becomes Vec<i32>. oneOf input objects are covered too, for their variants.
  • Types not starting with :: are relative to the schema module, as with query.
  • Borrowing: an override that borrows gives the input object an 'a lifetime, and needs borrow = true, as with query.
  • Validation: it's a typegen error when a path isn't a custom scalar field of an input object, or when an override borrows without borrow = true.
  • Shared code: CustomScalarOverride gets parse_all and validate_all, which both options now use. The query option's behaviour and error messages don't change.

Compatibility

Nothing that compiles on main changes: the option is new, and without it the generated types are the same.

`typegen` now takes `custom_scalar_overrides`, like `query` does, to
override the type of a custom scalar field of an input object. Paths are
`"InputObject.field"`, and lists and nullability are kept. This lets a
field typed with a catch-all scalar such as `JSON` use a specific Rust
type instead of an untyped value.

Parsing and validation are shared with the `query` option, whose
behaviour doesn't change.
saga-dasgupta added a commit to Shopify/shopify-function-rust that referenced this pull request Oct 5, 2026
A prepare target returns the variables for its run target's input query as
untyped `JSON`. Nothing checked that they matched what the run query declares,
so a renamed, added, or retyped variable deployed fine and failed at checkout,
with the run query resolving nothing.

bluejay now generates a struct for the variables of each operation that
declares them: `<Operation>Variables`, or `RootVariables` for an anonymous
operation, with a field per variable. A non-null variable with no default is a
plain field; any other is an `Option` whose `None` omits it. `typegen`
implements wasm_api's `Serialize` and `Deserialize` for it with the same code
as input objects, so it serializes directly.

bluejay's `typegen` also takes `custom_scalar_overrides`, so a prepare result's
`variables` field can be typed as the run query's variables struct instead of
`JsonValue`:

    #[typegen("schema.graphql", custom_scalar_overrides = {
        "CartValidationsGeneratePrepareResult.variables" => cart_validations_generate_run::InputVariables,
    })]

A prepare target that no longer matches its run query then fails to compile:

- a renamed or removed variable is an unknown field (E0560)
- an added variable is a missing field (E0063)
- a retyped variable, or a hand-written `JsonValue`, is a mismatch (E0308)

Depends on Shopify/bluejay#146 and Shopify/bluejay#147, patched in from #146's
branch, which has both, until they ship in a release.
@saga-dasgupta
saga-dasgupta marked this pull request as ready for review October 6, 2026 13:37
@saga-dasgupta

Copy link
Copy Markdown
Contributor Author

Moved to #148, from a branch in this repo so that #149 can be stacked on it.

@saga-dasgupta
saga-dasgupta deleted the input-custom-scalar-overrides branch October 6, 2026 14:31
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.

1 participant