Skip to content

TransformQuery path also matches fragments #4171

@saerdnaer

Description

@saerdnaer

Describe the bug

When TransformQuery is used with a too generic path which might also match an attribute in the subtree, users get unexpected results when using fragments:

For example using TransformQuery with path ['editorialCategory'] transform both matches the query and the fragment:

query NestedTestQuery {
  editorialCategory(id: "42914694") {
    id
    sections {
        nodes {
          ...Show
        }
    }
  }
}

fragment Show on ProgramSet {
  id
  title
  editorialCategory {
    id
    title
  }
}

The problem is probably in this section: The visitor needs an indication if it currently in the root query or the fragment, als in both cases the index is set to 1:

public transformRequest(
originalRequest: ExecutionRequest,
delegationContext: DelegationContext,
transformationContext: Record<string, any>
): ExecutionRequest {
const pathLength = this.path.length;
let index = 0;
const document = visit(originalRequest.document, {
[Kind.FIELD]: {
enter: node => {
if (index === pathLength || node.name.value !== this.path[index] || node.selectionSet == null) {
return false;
}
index++;
if (index === pathLength) {
const selectionSet = this.queryTransformer(
node.selectionSet,
this.fragments,
delegationContext,
transformationContext
);
return {
...node,
selectionSet,
};
}
},

Example delegateToSchema call using transform

await delegateToSchema({
        schema: subschema
	fieldName: 'editorialCategory',
	args: { id },
	context,
	info,
	transforms: [
		// Wrap document takes a subtree as an AST node
		new TransformQuery({
			// path at which to apply wrapping and extracting
			path: [ 'editorialCategory' ],
			queryTransformer: (subtree: SelectionSetNode) => ({
				kind: Kind.SELECTION_SET,
				selections: [
					{
						kind: Kind.FIELD,
						name: {
							kind: Kind.NAME,
							value: 'programSets',
						},
						selectionSet: {
							kind: Kind.SELECTION_SET,
							selections: [
								{
									// we create a wrapping AST Field
									kind: Kind.FIELD,
									name: {
										kind: Kind.NAME,
										value: 'nodes',
									},
									// Inside the field selection
									selectionSet: subtree,
								},
							],
						},
					},
				],
			}),
			// how to process the data result at path
			resultTransformer: (result) => result?.programSets?.nodes,
			errorPathTransformer: (path) => path.slice(2),
		}),
	]
});

To Reproduce
Steps to reproduce the behaviour:

Query A, which triggers path matching bug

query NestedTestQuery {
  editorialCategory(id: "42914694") {
    id
    sections {
      ...SectionType
    }
  }
}

fragment SectionType on Section {
  id
  title
  type
  nodes {
    ...Show
  }
}

fragment Show on ProgramSet {
  id
  title
  editorialCategory {
    id
    title
  }
}

Query B, with workaround for path matching bug

query GetEditorialCategoryById {
  editorialCategory(id: "42914694") {
    id
    sections {
      ...SectionType
    }
  }
}

fragment SectionType on Section {
  id
  title
  type
  nodes {
    ... on ProgramSet {
      id
      title
      editorialCategory {
        id
        title
      }
    }
  }
}

Expected behavior

Environment:

    "@graphql-tools/batch-delegate": "8.2.3",
    "@graphql-tools/delegate": "8.4.3",
    "@graphql-tools/graphql-file-loader": "7.3.3",
    "@graphql-tools/load": "7.5.1",
    "@graphql-tools/merge": "8.2.1",
    "@graphql-tools/stitch": "8.4.3",
    "@graphql-tools/utils": "8.6.1",
    "@graphql-tools/wrap": "8.3.3",

Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions