Skip to content
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

stitchSchemas with namespaced queries and mutations #4047

Open
Tracked by #5201 ...
wmwart opened this issue Dec 23, 2021 Discussed in #4042 · 3 comments
Open
Tracked by #5201 ...

stitchSchemas with namespaced queries and mutations #4047

wmwart opened this issue Dec 23, 2021 Discussed in #4042 · 3 comments
Labels
stage/1-reproduction A reproduction exists

Comments

@wmwart
Copy link

wmwart commented Dec 23, 2021

Discussed in #4042

Originally posted by wmwart December 22, 2021
Good afternoon.
I have a question about using stitchSchemas with namespaced queries and mutations.
I have 2 remote services:

###AssetService
type Asset {
  id: ID!
  name: String!
  description: String
  ...
}

type AssetPayload {
  item: Asset
}

type AssetsPayload {
  items: [Asset!]
  pageInfo: PaginationInfo
}

input AssetWhereUniqueInput {
  id: ID
}

type AssetQuery {
  getOne(where: AssetWhereUniqueInput!): AssetPayload! @withAuth
  getList(filter: AssetFilter = {} sort: [AssetSort! ] = [{id: asc}] page: Int = 1 perPage: Int = 100): AssetsPayload! @withAuth
  getMany(ids: [ID!]!): AssetsPayload! @withAuth
}

type AssetMutation {
  create(input: AssetCreateInput!): AssetPayload! @withAuth
  update( where: AssetWhereUniqueInput! input: AssetUpdateInput!): AssetPayload! @withAuth
  remove(where: AssetWhereUniqueInput!): AssetPayload! @withAuth
  restore(where: AssetWhereUniqueInput!): AssetPayload! @withAuth
  delete(where: AssetWhereUniqueInput!): AssetPayload! @withAuth
}

type Query {
  Asset: AssetQuery
}

type Mutation {
  Asset: AssetMutation
}

...

and

### AssetClassService
type AssetClass {
  id: ID!
  name: String!
  assets: [AssetWithoutAssetClass!]!
}

type AssetClassPayload {
  item: AssetClass
}

type AssetClassesPayload {
  items: [AssetClass!]
  pageInfo: PaginationInfo
}

type AssetClassQuery {
  getOne(where: AssetClassWhereUniqueInput!): AssetClassPayload! @withAuth
  getList(filter: AssetClassFilter = {} sort: [AssetClassSort! ] = [{id: asc}] page: Int = 1 perPage: Int = 100): AssetClassesPayload! @withAuth
  getMany(ids: [ID!]): [AssetClass!]!
}

type AssetClassMutation {
  create(input: AssetClassCreateInput!): AssetClassPayload! @withAuth
  update( where: AssetClassWhereUniqueInput! input: AssetClassUpdateInput!): AssetClassPayload! @withAuth
  remove(where: AssetClassWhereUniqueInput!): AssetClassPayload! @withAuth
  restore(where: AssetClassWhereUniqueInput!): AssetClassPayload! @withAuth
  delete(where: AssetClassWhereUniqueInput!): AssetClassPayload! @withAuth
}

type Asset {
  id: ID!
  assetClass: AssetClass
}


type AssetQuery {
  getMany(ids: [ID!]!): [Asset!]!
}


type Query {
  AssetClass: AssetClassQuery
  Asset: AssetQuery 
}

type Mutation {
  AssetClass: AssetClassMutation
}

Thus, when using stitchSchemas in my proxy service, a function for obtaining a stitched schema appeared:

const makeGatewaySchema = async () => {

  const assetServiceExecutor = makeRemoteExecutor('http://localhost:7702', { log: true });
  const assetClassServiceExecutor = makeRemoteExecutor('http://localhost:7703', { log: true });

  return stitchSchemas({
    subschemas: [
      {
        schema: await introspectSchema(assetServiceExecutor),
        executor: assetServiceExecutor,
        merge: {...}
      },
      {
        schema: await introspectSchema(assetClassServiceExecutor),
        executor: assetClassServiceExecutor,
        merge: {...}
      },
    ],
  });
}

Which allows me to fulfill the request:

query Items {
  Asset {
    getList {
      items {
        id
        name
        assetClass {
          id
          name
          description
        }
      }
    }
  }
}

However, none of the combination of merge options of these subcircuits specified in the documentation and examples of use returned me the required answer.
I assume that the problem is precisely in the namespaced types.

Please help me specify the correct settings for merge options or share a link to a solution to a similar problem

@wmwart
Copy link
Author

wmwart commented Dec 23, 2021

I used different options for describing fieldName with merge AssetClass from AssetClassService:
fieldName: 'AssetClass.getMany',
fieldName: { AssetClass: "getMany"},
fieldName: "getMany",
and other. But nothing happened

In addition, the query that I indicated above gave the result without additional merge options, but except for the assetClass {..., assetClass: null} field.

However, when I added to the AssetClassService in the schema

type AssetQuery {
  getMany(ids: [ID!]): AssetsPayload! @withAuth
}

type Query {
  Asset: AssetQuery
}

The request stopped returning data.

{
  "data": {
    "Asset": null
  }
}

test various options ...

return stitchSchemas({
    subschemas: [
      {
        schema: await introspectSchema(assetServiceExecutor),
        executor: assetServiceExecutor,

        merge: {
          Asset: {
            canonical: true,
            selectionSet: '{ id }',
            fieldName: 'Asset.getList',
            args: ({ id }) => {

              return { id }
            },
          },
          AssetClass: {
            selectionSet: '{ id }',
            fieldName: 'getMany',
            key: (root, args, context, info) => {

              return root.id
            },
            argsFromKeys: (root, args, context, info) => {

              return { ids: root.ids }
            },
          }
        }
      },
      {
        schema: await introspectSchema(assetClassServiceExecutor),
        executor: assetClassServiceExecutor,
        batch: true,
        merge: {
          Asset: {
            selectionSet: '{ id assets }',
            fieldName: 'Asset._resolveReference',
            key: (root, args, context, info) => {

              return root.assets
            },
            argsFromKeys: (root, args, context, info) => {

              return { ids: root.assets }
            },
          },
          AssetClass: {
            canonical: true,
            selectionSet: '{ id }',
            fieldName: 'AssetClass.getMany',
            key: (root, args, context, info) => {

              return root.id
            },
            argsFromKeys: (root, args, context, info) => {

              return { ids: root.ids }
            },
          }
        }
      },
    ],
  });
}

@ardatan
Copy link
Owner

ardatan commented Jan 4, 2022

Thanks for reporting this issue. Would you create a PR with a failing test?

@ardatan ardatan added the stage/1-reproduction A reproduction exists label Jan 4, 2022
@wmwart
Copy link
Author

wmwart commented Jul 25, 2022

@ardatan , Here is a repository with two examples: https://github.com/denisgnt/gateway-service-example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stage/1-reproduction A reproduction exists
Projects
None yet
Development

No branches or pull requests

2 participants