Skip to content

fix: correct interface types for nested global fields, add taxonomy field support - #280

Merged
abhishek-ezhava-cstk merged 4 commits into
masterfrom
fix/DX-10112-nested-global-field-taxonomy
Aug 5, 2026
Merged

fix: correct interface types for nested global fields, add taxonomy field support#280
abhishek-ezhava-cstk merged 4 commits into
masterfrom
fix/DX-10112-nested-global-field-taxonomy

Conversation

@abhishek-ezhava-cstk

Copy link
Copy Markdown
Contributor

Summary

Fixes DX-10112. Reimplements a customer-supplied patch (gatsby-source-contentstack+5.4.3 2.patch) against current master, verified against the current codebase and live data rather than applied as-is.

1. Broken GraphQL interface types for nested global fields

In both buildBlockCustomSchema and buildCustomSchema (src/normalize.js), the interface-side field type for each field in a block/group was derived by blindly string-replacing the parent type name onto every child field's type string. This breaks when a child field is itself a global_field referencing another global field — its type name is built from its own reference_to, not from the parent name, so the blind replace produced a non-existent, malformed interface type.

Fix: detect the nested-global-field case explicitly (childField.data_type === 'global_field' && childField.reference_to) and point the interface field at the referenced global field's own interface type instead of doing the blind replace. Same fix applied in both places since they share the same pattern.

2. No support for the taxonomy field data type

buildCustomSchema's switch statement had no case 'taxonomy': — any content type with a taxonomy field had the field silently dropped from the schema. Added a case that defines a taxonomyType { taxonomy_uid: String term_uid: String } GraphQL type and resolves the field from the entry data, typed as [taxonomyType]/[taxonomyType]! per mandatory.

README updated with a "Querying taxonomy fields" section (nested global fields needed no new docs — that's a fix to already-documented behavior, not a new capability).

Test plan

  • New unit tests (src/tests/normalize-nested-global-field-taxonomy.test.js), verified to actually catch the regression: stashed the fix, all 3 new tests failed with the expected errors; restored, all pass.
  • npm test — full suite passes (10 tests, 4 suites).
  • Live verification against a real Contentstack stack via the contentstack-gatsby-starter-app:
    • Set up a doubly-nested global field (a modular block containing a global field seo_2, which itself contains another global field seo) — an even stronger test than the unit test's single-level nesting.
    • Confirmed via GraphQL introspection: Contentstack_seo_2's global_field field correctly resolves to type Contentstack_seo (the actual interface built one level down), not a malformed type name.
    • Added a real taxonomy field (referencing a taxonomy with 3 terms) to a content type, set 2 terms on a real entry, and confirmed the query returns exactly those terms (taxonomy_uid/term_uid) matching the CMS data.

…ield support

Nested global fields (a global field referencing another global field,
whether inside a plain field, a group, or a modular block) got the
wrong GraphQL interface type. The interface field name was derived by
blindly string-replacing the parent type name onto every child field,
which only works when the child's type name is literally built from
that parent name. A nested global field's type name is built from its
own reference_to instead, so the blind replace produced a
non-existent, malformed interface type.

Detect the nested-global-field case explicitly in both
buildBlockCustomSchema and buildCustomSchema, and point the interface
field at the referenced global field's own interface type instead.

Also add support for the `taxonomy` field data type, which previously
had no schema handling at all — content types with a taxonomy field
now correctly expose a `[taxonomyType]` field (taxonomy_uid, term_uid)
instead of the field being silently dropped.

Fixes DX-10112.
@snyk-io

snyk-io Bot commented Aug 4, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@abhishek-ezhava-cstk
abhishek-ezhava-cstk requested a lite review from Copilot August 4, 2026 09:43
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

🔒 Security Scan Results

ℹ️ Note: Only vulnerabilities with available fixes (upgrades or patches) are counted toward thresholds.

Check Type Count (with fixes) Without fixes Threshold Result
🔴 Critical Severity 0 1 10 ✅ Passed
🟠 High Severity 1 4 25 ✅ Passed
🟡 Medium Severity 3 41 500 ✅ Passed
🔵 Low Severity 0 0 1000 ✅ Passed

⏱️ SLA Breach Summary

✅ No SLA breaches detected. All vulnerabilities are within acceptable time thresholds.

Severity Breaches (with fixes) Breaches (no fixes) SLA Threshold (with/no fixes) Status
🔴 Critical 0 0 15 / 30 days ✅ Passed
🟠 High 0 0 30 / 120 days ✅ Passed
🟡 Medium 0 0 90 / 365 days ✅ Passed
🔵 Low 0 0 180 / 365 days ✅ Passed

ℹ️ Vulnerabilities Without Available Fixes (Informational Only)

The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:

  • Critical without fixes: 1
  • High without fixes: 4
  • Medium without fixes: 41
  • Low without fixes: 0

✅ BUILD PASSED - All security checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes schema generation issues in gatsby-source-contentstack around nested global fields and adds first-class GraphQL schema support for Contentstack taxonomy fields, along with documentation and regression tests.

Changes:

  • Fixes interface field typing for global fields nested inside blocks/groups so interface types are derived from the nested global field’s own reference_to.
  • Adds taxonomy field support in buildCustomSchema and documents how to query taxonomy fields.
  • Adds regression tests covering both nested-global-field interface typing and taxonomy schema generation.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/normalize.js Fixes interface type derivation for nested global fields; adds taxonomy field handling in schema generation.
src/tests/normalize-nested-global-field-taxonomy.test.js Adds unit tests for nested global-field interface typing and taxonomy field schema output.
tests/normalize-nested-global-field-taxonomy.test.js Adds compiled/duplicated test counterpart mirroring src/tests for the taxonomy + nested-global regression coverage.
README.md Documents how to query taxonomy fields via GraphQL.
.talismanrc Adds a checksum-based ignore entry for src/normalize.js in Talisman configuration.
Files not reviewed (1)
  • tests/normalize-nested-global-field-taxonomy.test.js: Generated file
Suppressed comments (1)

src/normalize.js:447

  • Same O(n²) pattern here: (field.schema || []).find(...) is executed for every nested field when building interface fields. Pre-index field.schema by uid once to avoid repeated linear scans.
        const typeFields = {};
        const interfaceFields = {};
        for (const key in result.fields) {
          typeFields[key] = result.fields[key].type || result.fields[key];
          // Same nested-global-field case as buildBlockCustomSchema above.
          const childField = (field.schema || []).find(f => f.uid === key);
          if (childField && childField.data_type === 'global_field' && childField.reference_to) {
            interfaceFields[key] = typeFields[key].replace(`${newParent}_${key}`, `${prefix}_${childField.reference_to}`);
          } else {
            interfaceFields[key] = typeFields[key].replace(newParent, newInterfaceParent);
          }
        }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/normalize.js
Comment thread src/normalize.js
Comment thread .talismanrc
@abhishek-ezhava-cstk
abhishek-ezhava-cstk requested a review from a team August 4, 2026 10:57
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

🔒 Security Scan Results

ℹ️ Note: Only vulnerabilities with available fixes (upgrades or patches) are counted toward thresholds.

Check Type Count (with fixes) Without fixes Threshold Result
🔴 Critical Severity 0 1 10 ✅ Passed
🟠 High Severity 0 1 25 ✅ Passed
🟡 Medium Severity 0 41 500 ✅ Passed
🔵 Low Severity 0 0 1000 ✅ Passed

⏱️ SLA Breach Summary

✅ No SLA breaches detected. All vulnerabilities are within acceptable time thresholds.

Severity Breaches (with fixes) Breaches (no fixes) SLA Threshold (with/no fixes) Status
🔴 Critical 0 0 15 / 30 days ✅ Passed
🟠 High 0 0 30 / 120 days ✅ Passed
🟡 Medium 0 0 90 / 365 days ✅ Passed
🔵 Low 0 0 180 / 365 days ✅ Passed

ℹ️ Vulnerabilities Without Available Fixes (Informational Only)

The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:

  • Critical without fixes: 1
  • High without fixes: 1
  • Medium without fixes: 41
  • Low without fixes: 0

✅ BUILD PASSED - All security checks passed

- Guard the taxonomyType type definition push so a content type with
  more than one taxonomy field doesn't push duplicate type defs into
  the same createTypes() call, which Gatsby would reject as a schema
  build error.
- Pre-index each block/group's own schema by uid once before the
  interface-field loop, instead of calling .find() per field — avoids
  an O(n^2) scan for large modular blocks.

Addresses Copilot review comments on PR #280.
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

🔒 Security Scan Results

ℹ️ Note: Only vulnerabilities with available fixes (upgrades or patches) are counted toward thresholds.

Check Type Count (with fixes) Without fixes Threshold Result
🔴 Critical Severity 0 1 10 ✅ Passed
🟠 High Severity 0 1 25 ✅ Passed
🟡 Medium Severity 0 41 500 ✅ Passed
🔵 Low Severity 0 0 1000 ✅ Passed

⏱️ SLA Breach Summary

✅ No SLA breaches detected. All vulnerabilities are within acceptable time thresholds.

Severity Breaches (with fixes) Breaches (no fixes) SLA Threshold (with/no fixes) Status
🔴 Critical 0 0 15 / 30 days ✅ Passed
🟠 High 0 0 30 / 120 days ✅ Passed
🟡 Medium 0 0 90 / 365 days ✅ Passed
🔵 Low 0 0 180 / 365 days ✅ Passed

ℹ️ Vulnerabilities Without Available Fixes (Informational Only)

The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:

  • Critical without fixes: 1
  • High without fixes: 1
  • Medium without fixes: 41
  • Low without fixes: 0

✅ BUILD PASSED - All security checks passed

Addresses a Copilot review comment on PR #280 asking why these
whole-file checksum ignores exist. Documents that they're false
positives on the literal string "api_key" (a plugin option name, not
a credential), and that each checksum is pinned to the file's content
at review time so a future edit — including a real secret — changes
the checksum and re-triggers scanning.
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

🔒 Security Scan Results

ℹ️ Note: Only vulnerabilities with available fixes (upgrades or patches) are counted toward thresholds.

Check Type Count (with fixes) Without fixes Threshold Result
🔴 Critical Severity 0 1 10 ✅ Passed
🟠 High Severity 0 0 25 ✅ Passed
🟡 Medium Severity 0 41 500 ✅ Passed
🔵 Low Severity 0 0 1000 ✅ Passed

⏱️ SLA Breach Summary

✅ No SLA breaches detected. All vulnerabilities are within acceptable time thresholds.

Severity Breaches (with fixes) Breaches (no fixes) SLA Threshold (with/no fixes) Status
🔴 Critical 0 0 15 / 30 days ✅ Passed
🟠 High 0 0 30 / 120 days ✅ Passed
🟡 Medium 0 0 90 / 365 days ✅ Passed
🔵 Low 0 0 180 / 365 days ✅ Passed

ℹ️ Vulnerabilities Without Available Fixes (Informational Only)

The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:

  • Critical without fixes: 1
  • High without fixes: 0
  • Medium without fixes: 41
  • Low without fixes: 0

✅ BUILD PASSED - All security checks passed

@abhishek-ezhava-cstk
abhishek-ezhava-cstk merged commit 6fa7a49 into master Aug 5, 2026
8 checks passed
@abhishek-ezhava-cstk
abhishek-ezhava-cstk deleted the fix/DX-10112-nested-global-field-taxonomy branch August 5, 2026 09:19
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.

4 participants