Nesting entire root query #24
Comments
Does this help you? |
From what I recall, I think I had in mind that you first extend with new wrapped fields and then filter out original unwrapped fields using filterSchema |
Actually, that "wraps" by turning a field into a new type with its own fields wherever it appears, so, for example, you can move street, city, zip fields on some type to new Address subtype, but you have to hard code which fields you are moving to the subtype. That transform works wherever the type appears. You are talking about just wrapping root fields, so you may be able to get away with WrapQuery or the improved TransformQuery, but you would have to hard code somewhere the PrefixQuery definition. You could probably use these transforms as inspiration to automate that part. Would be happy to accept PR. |
Hm. Interesting. Several moments:
|
Preface: Intro to TransformsIn general, I find "transforms" a confusing subject. Just to make sure we are on the same page. Some transforms (type A?) implement only request and response middleware (the transformRequest/transformResponse methods) that can be tacked onto any schema delegation call, and they can be used to delegate to a conflicting schema. Other transforms (type B?) implement a transformSchema method. When used with the exported graphql-tools transformSchema function, they can be used to change the underlying schema. What the exported transformSchema function does is create an outer schema that delegates to the passed in schema (an "inner" schema). The outer schema initially has the same types as the inner/original schema. Each of the passed in transforms' transformSchema methods is called on that original schema to yield a new modified outer schema, with the inner/original schema unchanged. [As a side note, I found it confusing that the individual transforms' transformSchema methods are called the same thing as the exported transformSchema function, and so I gave that exported function an alias, 'wrapSchema' which I believe is more descriptive.] As mentioned, type B transforms shadow the original root fields and just delegate to the original schema, automatically including all of the passed transforms' request/response middleware. This extra complexity buys you the ability to stand up a graphql server with the new modified schema using the same tools (express-graphql/Apollo Server) that expect a regular schema. The WrapQuery transform is an original Apollo transform that is decidedly type A. Its docs are here. Because it does not modify the underling target schema, (i.e., is not a type B), you have to handle generation of the outer schema on your own, presumably by handcoding. WrapQuery is useful for people working directly with the underlying delegateToSchema function.](ardatan#901). My transformQuery is just an improved version that has better support for errors and fragments. For comparison, RenameRootFields and RenameTypes are original Apollo type B transforms that gives you a new schema with different root fields. Your Questions.
WrapType started off with just wrapping, and then, as linked above, modification of the existing selection set was added. This was before my TransformObjectFields transform and ExtendSchema transform allowed for easier ways of renaming fields.
WrapType is type B, and so you can use it with mergeSchemas/try to extend it/stand up a server with it. Check out an initial use case in the tests with namespacing the root Query type. Be careful when namespacing mutations, I am not sure, but it may in this implementation break the non-concurrent guarantee. I'm not sure at all what would happen when namespacing subscriptions with this transform, but please report back if you can. I think it technically breaks the spec to namespace subscriptions, as that means sub fields would be returning async iterators, but maybe it doesn't work at all, so the spec is ok. :)
ExtendSchema is type B. It lets you add arbitrary fields and types to an existing schema to provide custom functionality, similar to mergeSchemas, but with just one schema. Schema modification with the ExtendSchema is unidirectional, you are always modifying the function of the original/inner schema (and so that avoids the need to add a required fragment map = info.mergeInfo a la mergeSchemas). The advantage of using the ExtendSchema rather than mergeSchemas with just one schema is that ExtendSchemas gives you the ability to specify functions for how to modify the request to the inner schema rather than just hardcoding a fragment. With ExtendSchema, you pass a fieldNodeTransformerMap to the transform to specify how to modify the fieldNodes in the request and then you define your own resolvers to do what you want. In the examples in my tests, what I set up is wrapping/extracting fields, and so basically I am not adding extra functionality to the schema, just moving fields/data around. The fieldNodeTransformerMap uses helper functions for wrapping and extracting selections and the resolvers use helper functions for reversing those changes so the right data returned by the inner schema goes to the right place in the outer schema. That last part is where createMergedResolver comes in: it creates a resolver that handles a merge with path mapping between the outer and inner schema. To recap:
Finally...Hopefully, better documentation will be forthcoming. Your issue/request has been helpful toward providing some initial docs! |
@yaacovCR thank you very much! very helpful. I've tried to understand all of this, but there is so small amount of information on the topic. Now many thing are a lot clearer, thank you! |
Hello. I need to transform schema in such manner:
to
In other words to
Prefix
in example)Query
→PrefixQuery
)Prefixing is easily done with
RenameTypes
transform, but I can't figure out how to properly make nesting (that is in fact prefixing root types and creating a new root type with single field).Any suggestions on how to do this with existing tooling or how to make a transformer for this?
The text was updated successfully, but these errors were encountered: