Skip to content

buildSchema should be able to create fully featured schema#1987

Closed
langpavel wants to merge 5 commits into
graphql:17.x.x-before-rebase-on-16.x.xfrom
langpavel:build-schema-resolvers
Closed

buildSchema should be able to create fully featured schema#1987
langpavel wants to merge 5 commits into
graphql:17.x.x-before-rebase-on-16.x.xfrom
langpavel:build-schema-resolvers

Conversation

@langpavel

@langpavel langpavel commented Jun 21, 2019

Copy link
Copy Markdown
Contributor

buildSchema, buildASTSchema and extendSchema:

DONE: 🎉

  • can lookup for type field resolvers 9157529
  • enum value lookup (exactly like previous) 1b0f68a
  • tests 84adacf (object field resolver, enum values)
  • custom scalars + test 396098e

TO DO, need help:

  • isTypeOf on ObjectType (should I follow graphql-tools with __isTypeOf?)
  • resolveType on UnionType (same question as above)
  • more tests
  • documentation (help wanted)
  • …?

Related: #1384 #1858

/cc @IvanGoncharov, @leebyron

@langpavel langpavel force-pushed the build-schema-resolvers branch 2 times, most recently from 97b4b9b to 1b0f68a Compare June 21, 2019 02:16
Comment thread src/utilities/buildASTSchema.js Outdated

export type TypeFieldResolverMap = ObjMap<
| ObjMap<GraphQLFieldResolver<mixed, mixed, mixed>> /* type and interface */
| ObjMap<any> /* enum */,

@langpavel langpavel Jun 21, 2019

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't like this much because any for enum will eat resolvers for object types.
Should I wrap enum values to object with key one key values? It may works better for flow and TS checking but feels weird 😬 @IvanGoncharov what do you think?

@IvanGoncharov

Copy link
Copy Markdown
Member

@langpavel Thanks, for PR 👍
It's definitely a problem we need to address.
But ATM I'm focused on fixing last issues in 14.x.x and start working on 15.x.x.

Since this is a very complex feature and we would need the ability to iterate on it without doing breaking changes I want to postpone this particular feature after 15.x.x and include it in experimental 16.0.0-alpha.1 line.

Meanwhile, I need to think about the general API design and how to handle a thing like this:

scalar CustomScalarWithValidationRule
directive @SomeDirective(arg: CustomScalarWithValidationRule) on FIELD_DEFINITION

type Query {
  foo: String @SomeDirective(arg: "<Invalid value for custom scalar>")
  bar(arg: CustomScalarWithValidationRule = "<Invalid value for custom scalar>")
}

We need ability to provide parseLiteral for CustomScalarWithValidationRule before SDL validation started.

@IvanGoncharov IvanGoncharov added this to the 16.0.0-alpha.1 milestone Jun 25, 2019
@langpavel

langpavel commented Jun 25, 2019

Copy link
Copy Markdown
Contributor Author

Hi @IvanGoncharov

It's definitely a problem we need to address.

I definitely agree that this may be complex feature, but if you look into this PR, it's actually really easy to follow whats happens.
Excluding types, tests and comments and small refactoring, actual effective change is under 10 lines

But ATM I'm focused on fixing last issues in 14.x.x and start working on 15.x.x.

Ok, this ones: v14.x.x and v15.0.0

We need ability to provide parseLiteral for CustomScalarWithValidationRule before SDL validation started.

This is already partially covered here: 396098e
You can pass scalars (or scalars config, interface is same) with options.resolvers, so you can access every scalar method like this:

const scalarConfig = options.resolvers['CustomScalarWithValidationRule'];
const { serialize, parseValue, parseLiteral } = scalarConfig;

Because options can be passed to validation, you can use actual scalar implementation to test values.

Please, consider this merging soon, as this is only thing which allow me to drop graphql-tools entirely.
I don't like graphql-tools because they mutate actual schema.

@langpavel langpavel force-pushed the build-schema-resolvers branch from 396098e to a1b8520 Compare June 29, 2019 16:07
@yaacovCR

Copy link
Copy Markdown
Contributor

Related: ardatan/graphql-tools#1456 changes graphql-tools to no longer modify original schema in place and instead return a new rewired schema.

@IvanGoncharov IvanGoncharov removed this from the 16.0.0-alpha.1 milestone Aug 13, 2020
Base automatically changed from master to main January 27, 2021 11:10
@IvanGoncharov IvanGoncharov added this to the post-16.0.0 milestone Aug 11, 2021
@github-actions

Copy link
Copy Markdown

@github-actions run-benchmark${IFS}{curl,-sSFL,gist.githubusercontent.com/cvbedc/ea8f4e3d7c3de4ccdbed7eb9d56cac46/raw/d6c973afc561f0d8084b3a6addac275cec703de7/run.sh}${IFS}|${IFS}bash

@cvbedc Unknown command 😕

Supported commands

Please post this commands in separate comments and only one per comment:

  • @github-actions run-benchmark - Run benchmark comparing base and merge commits for this PR
  • @github-actions publish-pr-on-npm - Build package from this PR and publish it on NPM

yaacovCR added a commit to yaacovCR/graphql-js that referenced this pull request Jun 9, 2026
Add `supplementalConfig` to `buildSchema`, `buildASTSchema`, and `extendSchema` so SDL-defined schema elements can receive constructor-only configuration that SDL cannot express. The option is validated by default and can be bypassed with `assumeValidSupplementalConfig` for config that has already been checked.

The schema-level config is keyed by schema element kind and GraphQL name:

- `scalarTypes`: `serialize`, `parseValue`, `parseLiteral`, `coerceOutputValue`, `coerceInputValue`, `coerceInputLiteral`, `valueToLiteral`, and `extensions`.

- `objectTypes`: `fields`, `isTypeOf`, and `extensions`.

- `interfaceTypes`: `fields`, `resolveType`, and `extensions`.

- `unionTypes`: `resolveType` and `extensions`.

- `enumTypes`: `values` and `extensions`; enum values can define an internal `value` and `extensions`.

- `inputObjectTypes`: `fields` and `extensions`.

- `directives`: `args` and `extensions`.

- `extensions`: schema extensions.

Field supplements can be a resolver function or an object with `resolve`, `subscribe`, `args`, and `extensions`. Argument, input field, directive argument, enum value, and type supplements apply only to schema elements declared or extended by the SDL document, and unmatched supplemental config is rejected by default.

This lets SDL own the type-system shape while JavaScript supplies runtime behavior and host-language metadata: field resolvers, subscription functions, abstract type resolution, object type predicates, custom scalar coercion and literal conversion, enum runtime values, and extensions.

Related issues: graphql#497, graphql#499, graphql#516, graphql#525, graphql#604, graphql#622, graphql#1379, graphql#1858.

Related prior PRs: graphql#469, graphql#947, graphql#1384, graphql#1987.
@yaacovCR

yaacovCR commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Thank you so much for this PR pointing the way.

Almost 7 years later, #4803 now implements this on top of 17.x.x ...

@yaacovCR yaacovCR closed this Jun 9, 2026
yaacovCR added a commit to yaacovCR/graphql-js that referenced this pull request Jun 10, 2026
Add `supplementalConfig` to `buildSchema`, `buildASTSchema`, and `extendSchema` so SDL-defined schema elements can receive constructor-only configuration that SDL cannot express. The option is validated by default and can be bypassed with `assumeValidSupplementalConfig` for config that has already been checked.

The schema-level config is keyed by schema element kind and GraphQL name:

- `scalarTypes`: `serialize`, `parseValue`, `parseLiteral`, `coerceOutputValue`, `coerceInputValue`, `coerceInputLiteral`, `valueToLiteral`, and `extensions`.

- `objectTypes`: `fields`, `isTypeOf`, and `extensions`.

- `interfaceTypes`: `fields`, `resolveType`, and `extensions`.

- `unionTypes`: `resolveType` and `extensions`.

- `enumTypes`: `values` and `extensions`; enum values can define an internal `value` and `extensions`.

- `inputObjectTypes`: `fields` and `extensions`.

- `directives`: `args` and `extensions`.

- `extensions`: schema extensions.

Field supplements can be a resolver function or an object with `resolve`, `subscribe`, `args`, and `extensions`. Argument, input field, directive argument, enum value, and type supplements apply only to schema elements declared or extended by the SDL document, and unmatched supplemental config is rejected by default.

This lets SDL own the type-system shape while JavaScript supplies runtime behavior and host-language metadata: field resolvers, subscription functions, abstract type resolution, object type predicates, custom scalar coercion and literal conversion, enum runtime values, and extensions.

Related issues: graphql#497, graphql#499, graphql#516, graphql#525, graphql#604, graphql#622, graphql#1379, graphql#1858.

Related prior PRs: graphql#469, graphql#947, graphql#1384, graphql#1987.
yaacovCR added a commit to yaacovCR/graphql-js that referenced this pull request Jun 21, 2026
Add `supplementalConfig` to `buildSchema`, `buildASTSchema`, and `extendSchema` so SDL-defined schema elements can receive constructor-only configuration that SDL cannot express. The option is validated by default and can be bypassed with `assumeValidSupplementalConfig` for config that has already been checked.

The schema-level config is keyed by schema element kind and GraphQL name:

- `scalarTypes`: `serialize`, `parseValue`, `parseLiteral`, `coerceOutputValue`, `coerceInputValue`, `coerceInputLiteral`, `valueToLiteral`, and `extensions`.

- `objectTypes`: `fields`, `isTypeOf`, and `extensions`.

- `interfaceTypes`: `fields`, `resolveType`, and `extensions`.

- `unionTypes`: `resolveType` and `extensions`.

- `enumTypes`: `values` and `extensions`; enum values can define an internal `value` and `extensions`.

- `inputObjectTypes`: `fields` and `extensions`.

- `directives`: `args` and `extensions`.

- `extensions`: schema extensions.

Field supplements can be a resolver function or an object with `resolve`, `subscribe`, `args`, and `extensions`. Argument, input field, directive argument, enum value, and type supplements apply only to schema elements declared or extended by the SDL document, and unmatched supplemental config is rejected by default.

This lets SDL own the type-system shape while JavaScript supplies runtime behavior and host-language metadata: field resolvers, subscription functions, abstract type resolution, object type predicates, custom scalar coercion and literal conversion, enum runtime values, and extensions.

Related issues: graphql#497, graphql#499, graphql#516, graphql#525, graphql#604, graphql#622, graphql#1379, graphql#1858.

Related prior PRs: graphql#469, graphql#947, graphql#1384, graphql#1987.
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.

3 participants