Skip to content

feat: adds nested query rule #367

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Conversation

theodesp
Copy link
Member

@theodesp theodesp commented Aug 12, 2025

Description

This PR introduces a new query analysis rule, NestedQueryRule, to the wpgraphql-debug-extensions plugin. This rule is designed to help developers identify and prevent overly nested GraphQL queries, which can lead to performance degradation and increased server load.

Related Issue

Dependant PRs

None.

Type of Change

[ ] ✅ Bug fix (non-breaking change which fixes an issue)

[x] ✨ New feature (non-breaking change which adds functionality)

[ ] 💥 Breaking change (fix or feature that would cause existing functionality to change)

[x] 🧹 Code refactoring (no functional changes)

[ ] 📄 Example update (no functional changes)

[ ] 📝 Documentation update

[ ] 🔍 Performance improvement

[ ] 🧪 Test update

Test Queries and Expected Output

1. Query does not trigger the rule (Simple)

Max depth: 5 (well below the limit of 8)

query {
  posts { # Depth 1
    nodes { # Depth 2
      id
      title
      author { # Depth 3
        node { # Depth 4
          name # Depth 5
        }
      }
    }
  }
}
Expected debugExtensions.nestedQuery Output:

```json
{
  "nestedQuery": {
    "triggered": false,
    "message": "Nested query depth of 5 is within the allowed limit of 8.",
    "details": {
      "maxDepthReached": 5,
      "maxAllowed": 8
    }
  }
}

2. Query triggers the rule (Deeply Nested)

This query exceeds the maximum depth of 8 with a nesting depth of 9.

query {
  posts { # Depth 1
    nodes { # Depth 2
      id
      categories { # Depth 3
        nodes { # Depth 4
          posts { # Depth 5
            nodes { # Depth 6
              author { # Depth 7
                node { # Depth 8
                  posts { # Depth 9
                    nodes {
                      id
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Expected debugExtensions.nestedQuery Output:

{
  "nestedQuery": {
    "triggered": true,
    "message": "Nested query depth of 9 reached or exceeded the configured maximum of 8.",
    "details": {
      "maxDepthReached": 9,
      "maxAllowed": 8
    }
  }
}

3. Query That Does Not Trigger the Rule (With a Fragment)

Max depth: 4 (fragment stays well within limit)

fragment AuthorDetails on Post {
  id
  author { # Depth 3 inside fragment spread
    node { # Depth 4
      name
    }
  }
}

query {
  posts { # Depth 1
    nodes { # Depth 2
      ...AuthorDetails # Spread at depth 3
    }
  }
}

Expected debugExtensions.nestedQuery Output:

{
  "nestedQuery": {
    "triggered": false,
    "message": "Nested query depth of 4 is within the allowed limit of 8.",
    "details": {
      "maxDepthReached": 4,
      "maxAllowed": 8
    }
  }
}

4. Query That Triggers the Rule (With a Fragment)

Max depth: 9 (fragment spread creates over-limit nesting)

fragment DeepAuthorDetails on Post {
  author { # Depth 3 from main query
    node { # Depth 4
      posts { # Depth 5
        nodes { # Depth 6
          author { # Depth 7
            node { # Depth 8
              posts { # Depth 9
                nodes { # Depth 10
                  id   # Depth 11
                }
              }
            }
          }
        }
      }
    }
  }
}

query {
  posts { # Depth 1
    nodes { # Depth 2
      ...DeepAuthorDetails # Spread at depth 2
    }
  }
}

Expected debugExtensions.nestedQuery Output:

{
  "nestedQuery": {
    "triggered": true,
    "message": "Nested query depth of 11 reached or exceeded the configured maximum of 8.",
    "details": {
      "maxDepthReached": 11,
      "maxAllowed": 8
    }
  }
}

Checklist
[x] I have read the CONTRIBUTING document

[x] My code follows the project's coding standards

[x] I have commented my code, particularly in hard-to-understand areas

[ ] I have made corresponding changes to the documentation (if applicable)

[x] My changes generate no new warnings

[x] I have added tests that prove my fix is effective or that my feature works (if applicable)

[ ] Any dependent changes have been highlighted, merged or published

@theodesp theodesp requested a review from a team as a code owner August 12, 2025 10:33
Copy link

changeset-bot bot commented Aug 12, 2025

⚠️ No Changeset found

Latest commit: c77a2ba

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link

github-actions bot commented Aug 12, 2025

ℹ️ Download the latest wpgraphql-debug-extensions plugin zip from this PR
(See the 'Artifacts' section at the bottom)

Copy link
Member

@colinmurphy colinmurphy left a comment

Choose a reason for hiding this comment

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

LGTM 🚀 🚀 🚀

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.

2 participants