diff --git a/e2e-tests/contentful/schema.gql b/e2e-tests/contentful/schema.gql index 5f4ef8d58f623..86b7511083dd6 100644 --- a/e2e-tests/contentful/schema.gql +++ b/e2e-tests/contentful/schema.gql @@ -74,8 +74,6 @@ type Directory implements Node @dontInfer { type Site implements Node @dontInfer { buildTime: Date @dateformat siteMetadata: SiteSiteMetadata - port: Int - host: String polyfill: Boolean pathPrefix: String jsxRuntime: String @@ -124,12 +122,11 @@ type SiteBuildMetadata implements Node @dontInfer { interface ContentfulReference implements Node { id: ID! - sys: ContentfulSys + sys: ContentfulSys! } -type ContentfulSys { +type ContentfulSys implements Node @dontInfer { type: String! - id: String! spaceId: String! environmentId: String! contentType: ContentfulContentType @link(by: "id", from: "contentType___NODE") @@ -145,13 +142,27 @@ type ContentfulContentType implements Node @dontInfer { description: String! } -interface ContentfulEntry implements Node { +interface ContentfulEntry implements ContentfulReference & Node { id: ID! - sys: ContentfulSys + sys: ContentfulSys! + metadata: ContentfulMetadata! +} + +type ContentfulMetadata @dontInfer { + tags: [ContentfulTag]! @link(by: "id", from: "tags___NODE") +} + +type ContentfulTag implements Node @dontInfer { + name: String! + contentful_id: String! +} + +type ContentfulAssetFields @dontInfer { + localFile: File @link(by: "id") } type ContentfulAsset implements ContentfulReference & Node @dontInfer { - sys: ContentfulSys + sys: ContentfulSys! title: String description: String contentType: String @@ -163,15 +174,6 @@ type ContentfulAsset implements ContentfulReference & Node @dontInfer { fields: ContentfulAssetFields } -type ContentfulAssetFields { - localFile: String -} - -type ContentfulTag implements Node @dontInfer { - name: String! - contentful_id: String! -} - type ContentfulRichTextAssets { block: [ContentfulAsset]! hyperlink: [ContentfulAsset]! @@ -203,7 +205,8 @@ type ContentfulText implements Node @dontInfer { } type ContentfulContentTypeNumber implements ContentfulReference & ContentfulEntry & Node @dontInfer { - sys: ContentfulSys + sys: ContentfulSys! + metadata: ContentfulMetadata! title: String integer: Int integerLocalized: Int @@ -212,7 +215,8 @@ type ContentfulContentTypeNumber implements ContentfulReference & ContentfulEntr } type ContentfulContentTypeText implements ContentfulReference & ContentfulEntry & Node @dontInfer { - sys: ContentfulSys + sys: ContentfulSys! + metadata: ContentfulMetadata! title: String short: String shortLocalized: String @@ -224,7 +228,8 @@ type ContentfulContentTypeText implements ContentfulReference & ContentfulEntry } type ContentfulContentTypeMediaReference implements ContentfulReference & ContentfulEntry & Node @dontInfer { - sys: ContentfulSys + sys: ContentfulSys! + metadata: ContentfulMetadata! title: String one: ContentfulAsset @link(by: "id", from: "one___NODE") oneLocalized: ContentfulAsset @link(by: "id", from: "oneLocalized___NODE") @@ -233,14 +238,16 @@ type ContentfulContentTypeMediaReference implements ContentfulReference & Conten } type ContentfulContentTypeBoolean implements ContentfulReference & ContentfulEntry & Node @dontInfer { - sys: ContentfulSys + sys: ContentfulSys! + metadata: ContentfulMetadata! title: String boolean: Boolean booleanLocalized: Boolean } type ContentfulContentTypeDate implements ContentfulReference & ContentfulEntry & Node @dontInfer { - sys: ContentfulSys + sys: ContentfulSys! + metadata: ContentfulMetadata! title: String date: Date @dateformat dateTime: Date @dateformat @@ -249,44 +256,53 @@ type ContentfulContentTypeDate implements ContentfulReference & ContentfulEntry } type ContentfulContentTypeLocation implements ContentfulReference & ContentfulEntry & Node @dontInfer { - sys: ContentfulSys + sys: ContentfulSys! + metadata: ContentfulMetadata! title: String location: ContentfulLocation locationLocalized: ContentfulLocation } type ContentfulContentTypeJson implements ContentfulReference & ContentfulEntry & Node @dontInfer { - sys: ContentfulSys + sys: ContentfulSys! + metadata: ContentfulMetadata! title: String json: JSON jsonLocalized: JSON } type ContentfulContentTypeRichText implements ContentfulReference & ContentfulEntry & Node @dontInfer { - sys: ContentfulSys + sys: ContentfulSys! + metadata: ContentfulMetadata! title: String richText: ContentfulRichText richTextLocalized: ContentfulRichText richTextValidated: ContentfulRichText } -type ContentfulContentTypeContentReference implements ContentfulReference & ContentfulEntry & Node @dontInfer { - sys: ContentfulSys +type ContentfulContentTypeContentReference implements ContentfulReference & ContentfulEntry & Node @isPlaceholder @dontInfer { + sys: ContentfulSys! + metadata: ContentfulMetadata! title: String one: ContentfulEntry @link(by: "id", from: "one___NODE") oneLocalized: ContentfulEntry @link(by: "id", from: "oneLocalized___NODE") - many: [ContentfulEntry] @link(by: "id", from: "many___NODE") + many: [UnionContentfulContentReferenceNumberText] @link(by: "id", from: "many___NODE") manyLocalized: [ContentfulEntry] @link(by: "id", from: "manyLocalized___NODE") } +union UnionContentfulContentReferenceNumberText = ContentfulContentTypeContentReference | ContentfulContentTypeNumber | ContentfulContentTypeText + +union UnionContentfulNumberText = ContentfulContentTypeNumber | ContentfulContentTypeText + type ContentfulContentTypeValidatedContentReference implements ContentfulReference & ContentfulEntry & Node @dontInfer { - sys: ContentfulSys + sys: ContentfulSys! + metadata: ContentfulMetadata! title: String - oneItemSingleType: ContentfulEntry @link(by: "id", from: "oneItemSingleType___NODE") - oneItemManyTypes: ContentfulEntry @link(by: "id", from: "oneItemManyTypes___NODE") + oneItemSingleType: ContentfulContentTypeText @link(by: "id", from: "oneItemSingleType___NODE") + oneItemManyTypes: UnionContentfulNumberText @link(by: "id", from: "oneItemManyTypes___NODE") oneItemAllTypes: ContentfulEntry @link(by: "id", from: "oneItemAllTypes___NODE") - multipleItemsSingleType: [ContentfulEntry] @link(by: "id", from: "multipleItemsSingleType___NODE") - multipleItemsManyTypes: [ContentfulEntry] @link(by: "id", from: "multipleItemsManyTypes___NODE") + multipleItemsSingleType: [ContentfulContentTypeText] @link(by: "id", from: "multipleItemsSingleType___NODE") + multipleItemsManyTypes: [UnionContentfulNumberText] @link(by: "id", from: "multipleItemsManyTypes___NODE") multipleItemsAllTypes: [ContentfulEntry] @link(by: "id", from: "multipleItemsAllTypes___NODE") } @@ -317,7 +333,7 @@ type MarkdownWordCount { words: Int } -type MarkdownRemark implements Node @childOf(mimeTypes: ["text/markdown", "text/x-markdown"], types: ["ContentfulText"]) @dontInfer { +type MarkdownRemark implements Node @childOf(mimeTypes: ["text/markdown", "text/x-markdown"], types: ["ContentfulText"]) @derivedTypes @dontInfer { frontmatter: MarkdownRemarkFrontmatter excerpt: String rawMarkdownBody: String @@ -481,7 +497,7 @@ type ImageSharpResize { originalName: String } -type ImageSharp implements Node @childOf(mimeTypes: [], types: ["File"]) @dontInfer { +type ImageSharp implements Node @childOf(types: ["File"]) @dontInfer { fixed(width: Int, height: Int, base64Width: Int, jpegProgressive: Boolean = true, pngCompressionSpeed: Int = 4, grayscale: Boolean = false, duotone: DuotoneGradient, traceSVG: Potrace, quality: Int, jpegQuality: Int, pngQuality: Int, webpQuality: Int, toFormat: ImageFormat = AUTO, toFormatBase64: ImageFormat = AUTO, cropFocus: ImageCropFocus = ATTENTION, fit: ImageFit = COVER, background: String = "rgba(0,0,0,1)", rotate: Int = 0, trim: Float = 0): ImageSharpFixed fluid( maxWidth: Int @@ -652,7 +668,7 @@ enum GatsbyImagePlaceholder { NONE } -type ContentfulContentTypeContentType implements Node @dontInfer { +type ContentfulContentTypeContentType implements Node @derivedTypes @dontInfer { name: String displayField: String description: String diff --git a/e2e-tests/contentful/snapshots.js b/e2e-tests/contentful/snapshots.js index 4633f5746f014..492be39f16f3e 100644 --- a/e2e-tests/contentful/snapshots.js +++ b/e2e-tests/contentful/snapshots.js @@ -28,7 +28,7 @@ module.exports = { }, "rich-text": { "rich-text: All Features": { - "1": "
\n

Rich Text: All Features

\n

The European languages

\n

are members of the same family. Their separate existence is a myth. For:

\n \n

Europe uses the same vocabulary.

\n
\n
\"\"\n\n
\n
\n \n \n \"\"\n\n \n \n
\n

\n
\n

The languages only differ in:

\n
    \n
  1. \n

    their grammar

    \n
  2. \n
  3. \n

    their pronunciation

    \n
  4. \n
  5. \n

    their most common words

    \n
  6. \n
  7. \n

    [Inline-ContentfulText]\n Text: Short\n :\n The quick brown fox jumps over the lazy dog.

    \n
  8. \n
\n

Everyone realizes why a new common language would be desirable: one could\n refuse to pay expensive translators.

\n

{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"delectus aut autem\",\n \"completed\": false\n }

\n

To achieve this, it would be necessary to have uniform grammar,\n pronunciation and more common words.

\n

[ContentfulLocation] Lat:\n 52.51627\n , Long:\n 13.3777

\n
\n

If several languages coalesce, the grammar of the resulting language is\n more simple and regular than that of the individual languages.

\n
\n

The new common language will be more simple and regular than the existing\n European languages. It will be as simple as Occidental; in fact, it will be\n

\n
\n
" + "1": "
\n

Rich Text: All Features

\n

The European languages

\n

are members of the same family. Their separate existence is a myth. For:

\n \n

Europe uses the same vocabulary.

\n
\n
\"\"\n\n
\n
\n \n \n \"\"\n\n \n \n
\n

\n
\n

The languages only differ in:

\n
    \n
  1. \n

    their grammar

    \n
  2. \n
  3. \n

    their pronunciation

    \n
  4. \n
  5. \n

    their most common words

    \n
  6. \n
  7. \n

    [Inline-ContentfulContentTypeText]\n The quick brown fox jumps over the lazy dog.

    \n
  8. \n
\n

Everyone realizes why a new common language would be desirable: one could\n refuse to pay expensive translators.

\n

{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"delectus aut autem\",\n \"completed\": false\n }

\n

To achieve this, it would be necessary to have uniform grammar,\n pronunciation and more common words.

\n

[ContentfulContentTypeLocation] Lat:\n 52.51627\n , Long:\n 13.3777

\n
\n

If several languages coalesce, the grammar of the resulting language is\n more simple and regular than that of the individual languages.

\n
\n

The new common language will be more simple and regular than the existing\n European languages. It will be as simple as Occidental; in fact, it will be\n

\n
\n
" }, "rich-text: Basic": { "1": "
\n

Rich Text: Basic

\n

The European languages

\n

are members of the same family. Their separate existence is a myth. For:

\n \n

Europe uses the same vocabulary.

\n
\n

The languages only differ in:

\n
    \n
  1. \n

    their grammar

    \n
  2. \n
  3. \n

    their pronunciation

    \n
  4. \n
  5. \n

    their most common words

    \n
  6. \n
\n

Everyone realizes why a new common language would be desirable: one could\n refuse to pay expensive translators.

\n

{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"delectus aut autem\",\n \"completed\": false\n }

\n

To achieve this, it would be necessary to have uniform grammar,\n pronunciation and more common words.

\n
\n

If several languages coalesce, the grammar of the resulting language is\n more simple and regular than that of the individual languages.

\n
\n

The new common language will be more simple and regular than the existing\n European languages. It will be as simple as Occidental; in fact, it will be\n

\n
\n
" @@ -46,7 +46,7 @@ module.exports = { "1": "
\n

Rich Text: Embedded entry with reference loop

\n

Embedded entry with reference loop

\n

[ContentfulContentTypeContentReference]\n Content Reference: One (Loop B -> A)\n : [\n Content Reference: One (Loop A -> B)\n ]

\n

\n
\n
" }, "rich-text: Inline Entry": { - "1": "
\n

Rich Text: Inline entry

\n

Inline entry with reference loop

\n

Should be rendered after this [Inline-\n ContentfulContentTypeText\n ] and before that

\n

\n

\n
\n
" + "1": "
\n

Rich Text: Inline entry

\n

Inline entry with reference loop

\n

Should be rendered after this [Inline-ContentfulContentTypeText]\n The quick brown fox jumps over the lazy dog. and before\n that

\n

\n

\n
\n
" }, "rich-text: Inline Entry With Deep Reference Loop": { "1": "
\n

Rich Text: Inline entry with deep reference loop

\n

Inline entry with deep reference loop

\n

Should be rendered after this [Inline-\n ContentfulContentTypeContentReference\n ] and before that

\n

\n

\n
\n
" diff --git a/e2e-tests/contentful/src/pages/content-reference.js b/e2e-tests/contentful/src/pages/content-reference.js index af6400da98f3b..d31fdb8f8b14b 100644 --- a/e2e-tests/contentful/src/pages/content-reference.js +++ b/e2e-tests/contentful/src/pages/content-reference.js @@ -109,8 +109,10 @@ export const pageQuery = graphql` } one { __typename - sys { - id + ... on ContentfulEntry { + sys { + id + } } ... on ContentfulContentTypeText { title @@ -152,8 +154,10 @@ export const pageQuery = graphql` } many { __typename - sys { - id + ... on ContentfulEntry { + sys { + id + } } ... on ContentfulContentTypeText { title @@ -165,6 +169,11 @@ export const pageQuery = graphql` } ... on ContentfulContentTypeContentReference { title + ... on ContentfulEntry { + sys { + id + } + } one { ... on ContentfulContentTypeText { title diff --git a/e2e-tests/contentful/src/pages/rich-text.js b/e2e-tests/contentful/src/pages/rich-text.js index c3488ad37f63a..33c360059c08f 100644 --- a/e2e-tests/contentful/src/pages/rich-text.js +++ b/e2e-tests/contentful/src/pages/rich-text.js @@ -50,10 +50,10 @@ const makeOptions = ({ assetBlockMap, entryBlockMap, entryInlineMap }) => ({ }, [INLINES.EMBEDDED_ENTRY]: node => { const entry = entryInlineMap.get(node?.data?.target?.sys.id) - if (entry.__typename === "ContentfulText") { + if (entry.__typename === "ContentfulContentTypeText") { return ( - [Inline-ContentfulText] {entry.title}: {entry.short} + [Inline-ContentfulContentTypeText] {entry.short} ) } @@ -156,8 +156,10 @@ export const pageQuery = graphql` title one { __typename - sys { - id + ... on ContentfulEntry { + sys { + id + } } ... on ContentfulContentTypeText { title @@ -179,8 +181,10 @@ export const pageQuery = graphql` } many { __typename - sys { - id + ... on ContentfulEntry { + sys { + id + } } ... on ContentfulContentTypeText { title @@ -212,6 +216,10 @@ export const pageQuery = graphql` id type } + ... on ContentfulContentTypeText { + title + short + } } } } diff --git a/packages/gatsby-source-contentful/src/__fixtures__/content-types.js b/packages/gatsby-source-contentful/src/__fixtures__/content-types.js new file mode 100644 index 0000000000000..d3e4a10105aa7 --- /dev/null +++ b/packages/gatsby-source-contentful/src/__fixtures__/content-types.js @@ -0,0 +1,786 @@ +export const contentTypes = [ + { + sys: { + space: { + sys: { + type: `Link`, + linkType: `Space`, + id: `k8iqpp6u0ior`, + }, + }, + id: `number`, + type: `ContentType`, + createdAt: `2021-03-01T16:59:23.010Z`, + updatedAt: `2021-05-21T11:20:58.851Z`, + environment: { + sys: { + id: `master`, + type: `Link`, + linkType: `Environment`, + }, + }, + revision: 5, + }, + displayField: `title`, + name: `Number`, + description: ``, + fields: [ + { + id: `title`, + name: `Title`, + type: `Symbol`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `integer`, + name: `Integer`, + type: `Integer`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `integerLocalized`, + name: `Integer Localized`, + type: `Integer`, + localized: true, + required: false, + disabled: false, + omitted: false, + }, + { + id: `decimal`, + name: `Decimal`, + type: `Number`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `decimalLocalized`, + name: `Decimal Localized`, + type: `Number`, + localized: true, + required: false, + disabled: false, + omitted: false, + }, + ], + }, + { + sys: { + space: { + sys: { + type: `Link`, + linkType: `Space`, + id: `k8iqpp6u0ior`, + }, + }, + id: `text`, + type: `ContentType`, + createdAt: `2021-03-01T17:02:35.612Z`, + updatedAt: `2021-05-21T10:48:06.210Z`, + environment: { + sys: { + id: `master`, + type: `Link`, + linkType: `Environment`, + }, + }, + revision: 3, + }, + displayField: `title`, + name: `Text`, + description: ``, + fields: [ + { + id: `title`, + name: `Title`, + type: `Symbol`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `short`, + name: `Short`, + type: `Symbol`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `shortLocalized`, + name: `Short Localized`, + type: `Symbol`, + localized: true, + required: false, + disabled: false, + omitted: false, + }, + { + id: `shortList`, + name: `Short List`, + type: `Array`, + localized: false, + required: false, + disabled: false, + omitted: false, + items: { + type: `Symbol`, + validations: [], + }, + }, + { + id: `shortListLocalized`, + name: `Short List Localized`, + type: `Array`, + localized: true, + required: false, + disabled: false, + omitted: false, + items: { + type: `Symbol`, + validations: [], + }, + }, + { + id: `longPlain`, + name: `Long Plain`, + type: `Text`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `longMarkdown`, + name: `Long Markdown`, + type: `Text`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `longLocalized`, + name: `Long Localized`, + type: `Text`, + localized: true, + required: false, + disabled: false, + omitted: false, + }, + ], + }, + { + sys: { + space: { + sys: { + type: `Link`, + linkType: `Space`, + id: `k8iqpp6u0ior`, + }, + }, + id: `mediaReference`, + type: `ContentType`, + createdAt: `2021-03-01T17:03:21.639Z`, + updatedAt: `2021-05-21T11:11:20.265Z`, + environment: { + sys: { + id: `master`, + type: `Link`, + linkType: `Environment`, + }, + }, + revision: 8, + }, + displayField: `title`, + name: `Media Reference`, + description: ``, + fields: [ + { + id: `title`, + name: `Title`, + type: `Symbol`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `one`, + name: `One`, + type: `Link`, + localized: false, + required: false, + disabled: false, + omitted: false, + linkType: `Asset`, + }, + { + id: `oneLocalized`, + name: `One Localized`, + type: `Link`, + localized: true, + required: false, + disabled: false, + omitted: false, + linkType: `Asset`, + }, + { + id: `many`, + name: `Many`, + type: `Array`, + localized: false, + required: false, + disabled: false, + omitted: false, + items: { + type: `Link`, + validations: [], + linkType: `Asset`, + }, + }, + { + id: `manyLocalized`, + name: `Many Localized`, + type: `Array`, + localized: true, + required: false, + disabled: false, + omitted: false, + items: { + type: `Link`, + validations: [], + linkType: `Asset`, + }, + }, + ], + }, + { + sys: { + space: { + sys: { + type: `Link`, + linkType: `Space`, + id: `k8iqpp6u0ior`, + }, + }, + id: `boolean`, + type: `ContentType`, + createdAt: `2021-03-01T17:05:40.030Z`, + updatedAt: `2021-05-21T10:32:45.505Z`, + environment: { + sys: { + id: `master`, + type: `Link`, + linkType: `Environment`, + }, + }, + revision: 3, + }, + displayField: `title`, + name: `Boolean`, + description: ``, + fields: [ + { + id: `title`, + name: `Title`, + type: `Symbol`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `boolean`, + name: `Boolean`, + type: `Boolean`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `booleanLocalized`, + name: `Boolean Localized`, + type: `Boolean`, + localized: true, + required: false, + disabled: false, + omitted: false, + }, + ], + }, + { + sys: { + space: { + sys: { + type: `Link`, + linkType: `Space`, + id: `k8iqpp6u0ior`, + }, + }, + id: `date`, + type: `ContentType`, + createdAt: `2021-03-01T17:07:02.629Z`, + updatedAt: `2021-05-20T18:16:28.584Z`, + environment: { + sys: { + id: `master`, + type: `Link`, + linkType: `Environment`, + }, + }, + revision: 2, + }, + displayField: `title`, + name: `Date`, + description: ``, + fields: [ + { + id: `title`, + name: `Title`, + type: `Symbol`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `date`, + name: `Date`, + type: `Date`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `dateTime`, + name: `Date Time`, + type: `Date`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `dateTimeTimezone`, + name: `Date Time Timezone`, + type: `Date`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `dateLocalized`, + name: `Date Localized`, + type: `Date`, + localized: true, + required: false, + disabled: false, + omitted: false, + }, + ], + }, + { + sys: { + space: { + sys: { + type: `Link`, + linkType: `Space`, + id: `k8iqpp6u0ior`, + }, + }, + id: `location`, + type: `ContentType`, + createdAt: `2021-03-01T17:09:20.579Z`, + updatedAt: `2021-05-21T10:37:52.205Z`, + environment: { + sys: { + id: `master`, + type: `Link`, + linkType: `Environment`, + }, + }, + revision: 2, + }, + displayField: `title`, + name: `Location`, + description: ``, + fields: [ + { + id: `title`, + name: `Title`, + type: `Symbol`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `location`, + name: `Location`, + type: `Location`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `locationLocalized`, + name: `Location Localized`, + type: `Location`, + localized: true, + required: false, + disabled: false, + omitted: false, + }, + ], + }, + { + sys: { + space: { + sys: { + type: `Link`, + linkType: `Space`, + id: `k8iqpp6u0ior`, + }, + }, + id: `json`, + type: `ContentType`, + createdAt: `2021-03-01T17:09:56.970Z`, + updatedAt: `2021-05-21T10:36:57.432Z`, + environment: { + sys: { + id: `master`, + type: `Link`, + linkType: `Environment`, + }, + }, + revision: 2, + }, + displayField: `title`, + name: `JSON`, + description: ``, + fields: [ + { + id: `title`, + name: `Title`, + type: `Symbol`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `json`, + name: `JSON`, + type: `Object`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `jsonLocalized`, + name: `JSON Localized`, + type: `Object`, + localized: true, + required: false, + disabled: false, + omitted: false, + }, + ], + }, + { + sys: { + space: { + sys: { + type: `Link`, + linkType: `Space`, + id: `k8iqpp6u0ior`, + }, + }, + id: `richText`, + type: `ContentType`, + createdAt: `2021-03-01T17:11:01.406Z`, + updatedAt: `2021-11-05T12:56:39.942Z`, + environment: { + sys: { + id: `master`, + type: `Link`, + linkType: `Environment`, + }, + }, + revision: 7, + }, + displayField: `title`, + name: `Rich Text`, + description: ``, + fields: [ + { + id: `title`, + name: `Title`, + type: `Symbol`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `richText`, + name: `Rich Text`, + type: `RichText`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `richTextLocalized`, + name: `Rich Text Localized`, + type: `RichText`, + localized: true, + required: false, + disabled: false, + omitted: false, + }, + { + id: `richTextValidated`, + name: `Rich Text Validated`, + type: `RichText`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + ], + }, + { + sys: { + space: { + sys: { + type: `Link`, + linkType: `Space`, + id: `k8iqpp6u0ior`, + }, + }, + id: `contentReference`, + type: `ContentType`, + createdAt: `2021-03-02T09:17:08.210Z`, + updatedAt: `2021-05-21T10:36:34.506Z`, + environment: { + sys: { + id: `master`, + type: `Link`, + linkType: `Environment`, + }, + }, + revision: 7, + }, + displayField: `title`, + name: `Content Reference`, + description: ``, + fields: [ + { + id: `title`, + name: `Title`, + type: `Symbol`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `one`, + name: `One`, + type: `Link`, + localized: false, + required: false, + disabled: false, + omitted: false, + linkType: `Entry`, + }, + { + id: `oneLocalized`, + name: `One Localized`, + type: `Link`, + localized: true, + required: false, + disabled: false, + omitted: false, + linkType: `Entry`, + }, + { + id: `many`, + name: `Many`, + type: `Array`, + localized: false, + required: false, + disabled: false, + omitted: false, + items: { + type: `Link`, + validations: [ + { + linkContentType: [`contentReference`, `number`, `text`], + }, + ], + linkType: `Entry`, + }, + }, + { + id: `manyLocalized`, + name: `Many Localized`, + type: `Array`, + localized: true, + required: false, + disabled: false, + omitted: false, + items: { + type: `Link`, + validations: [], + linkType: `Entry`, + }, + }, + ], + }, + { + sys: { + space: { + sys: { + type: `Link`, + linkType: `Space`, + id: `k8iqpp6u0ior`, + }, + }, + id: `validatedContentReference`, + type: `ContentType`, + createdAt: `2021-05-20T15:29:49.734Z`, + updatedAt: `2021-05-20T15:33:26.620Z`, + environment: { + sys: { + id: `master`, + type: `Link`, + linkType: `Environment`, + }, + }, + revision: 4, + }, + displayField: `title`, + name: `ValidatedContentReference`, + description: ``, + fields: [ + { + id: `title`, + name: `Title`, + type: `Symbol`, + localized: false, + required: false, + disabled: false, + omitted: false, + }, + { + id: `oneItemSingleType`, + name: `One Item: Single Type`, + type: `Link`, + localized: false, + required: false, + disabled: false, + omitted: false, + linkType: `Entry`, + validations: [ + { + linkContentType: [`text`], + }, + ], + }, + { + id: `oneItemManyTypes`, + name: `One Item: Many Types`, + type: `Link`, + localized: false, + required: false, + disabled: false, + omitted: false, + linkType: `Entry`, + validations: [ + { + linkContentType: [`number`, `text`], + }, + ], + }, + { + id: `oneItemAllTypes`, + name: `One Item: All Types`, + type: `Link`, + localized: false, + required: false, + disabled: false, + omitted: false, + linkType: `Entry`, + }, + { + id: `multipleItemsSingleType`, + name: `Multiple Items: Single Type`, + type: `Array`, + localized: false, + required: false, + disabled: false, + omitted: false, + items: { + type: `Link`, + validations: [ + { + linkContentType: [`text`], + }, + ], + linkType: `Entry`, + }, + }, + { + id: `multipleItemsManyTypes`, + name: `Multiple Items: Many Types`, + type: `Array`, + localized: false, + required: false, + disabled: false, + omitted: false, + items: { + type: `Link`, + validations: [ + { + linkContentType: [`number`, `text`], + }, + ], + linkType: `Entry`, + }, + }, + { + id: `multipleItemsAllTypes`, + name: `Multiple Items: All Types`, + type: `Array`, + localized: false, + required: false, + disabled: false, + omitted: false, + items: { + type: `Link`, + validations: [], + linkType: `Entry`, + }, + }, + ], + }, +] diff --git a/packages/gatsby-source-contentful/src/__tests__/__snapshots__/create-schema-customization.js.snap b/packages/gatsby-source-contentful/src/__tests__/__snapshots__/create-schema-customization.js.snap new file mode 100644 index 0000000000000..711739fd0aec2 --- /dev/null +++ b/packages/gatsby-source-contentful/src/__tests__/__snapshots__/create-schema-customization.js.snap @@ -0,0 +1,843 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`create-schema-customization builds schema based on Contentful Content Model 1`] = ` +Array [ + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "description": Object { + "type": "String!", + }, + "displayField": Object { + "type": "String!", + }, + "id": Object { + "type": "ID!", + }, + "name": Object { + "type": "String!", + }, + }, + "interfaces": Array [ + "Node", + ], + "name": "ContentfulContentType", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "contentType": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "contentType___NODE", + }, + }, + "type": "ContentfulContentType", + }, + "environmentId": Object { + "type": " String!", + }, + "firstPublishedAt": Object { + "type": " Date!", + }, + "id": Object { + "type": " String!", + }, + "locale": Object { + "type": " String!", + }, + "publishedAt": Object { + "type": " Date!", + }, + "publishedVersion": Object { + "type": " Int!", + }, + "spaceId": Object { + "type": " String!", + }, + "type": Object { + "type": " String!", + }, + }, + "interfaces": Array [ + "Node", + ], + "name": "ContentfulSys", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "tags": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "tags___NODE", + }, + }, + "type": "[ContentfulTag]!", + }, + }, + "name": "ContentfulMetadata", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "contentful_id": Object { + "type": "String!", + }, + "id": Object { + "type": "ID!", + }, + "name": Object { + "type": "String!", + }, + }, + "interfaces": Array [ + "Node", + ], + "name": "ContentfulTag", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "localFile": Object { + "extensions": Object { + "link": Object { + "by": "id", + }, + }, + "type": "File", + }, + }, + "name": "ContentfulAssetFields", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "contentType": Object { + "type": "String", + }, + "description": Object { + "type": "String", + }, + "fields": Object { + "type": "ContentfulAssetFields", + }, + "fileName": Object { + "type": "String", + }, + "height": Object { + "type": "Int", + }, + "id": Object { + "type": "ID!", + }, + "size": Object { + "type": "Int", + }, + "sys": Object { + "type": "ContentfulSys!", + }, + "title": Object { + "type": "String", + }, + "url": Object { + "type": "String", + }, + "width": Object { + "type": "Int", + }, + }, + "interfaces": Array [ + "ContentfulReference", + "Node", + ], + "name": "ContentfulAsset", + }, + ], + Array [ + Object { + "fields": Object { + "block": Object { + "resolve": [Function], + "type": "[ContentfulAsset]!", + }, + "hyperlink": Object { + "resolve": [Function], + "type": "[ContentfulAsset]!", + }, + }, + "name": "ContentfulRichTextAssets", + }, + ], + Array [ + Object { + "fields": Object { + "block": Object { + "resolve": [Function], + "type": "[ContentfulEntry]!", + }, + "hyperlink": Object { + "resolve": [Function], + "type": "[ContentfulEntry]!", + }, + "inline": Object { + "resolve": [Function], + "type": "[ContentfulEntry]!", + }, + }, + "name": "ContentfulRichTextEntries", + }, + ], + Array [ + Object { + "fields": Object { + "assets": Object { + "resolve": [Function], + "type": "ContentfulRichTextAssets", + }, + "entries": Object { + "resolve": [Function], + "type": "ContentfulRichTextEntries", + }, + }, + "name": "ContentfulRichTextLinks", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "json": Object { + "resolve": [Function], + "type": "JSON", + }, + "links": Object { + "resolve": [Function], + "type": "ContentfulRichTextLinks", + }, + }, + "name": "ContentfulRichText", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "lat": Object { + "type": "Float!", + }, + "lon": Object { + "type": "Float!", + }, + }, + "name": "ContentfulLocation", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "raw": "String!", + }, + "interfaces": Array [ + "Node", + ], + "name": "ContentfulText", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "decimal": Object { + "type": "Float", + }, + "decimalLocalized": Object { + "type": "Float", + }, + "id": Object { + "type": "ID!", + }, + "integer": Object { + "type": "Int", + }, + "integerLocalized": Object { + "type": "Int", + }, + "metadata": Object { + "type": "ContentfulMetadata!", + }, + "sys": Object { + "type": "ContentfulSys!", + }, + "title": Object { + "type": "String", + }, + }, + "interfaces": Array [ + "ContentfulReference", + "ContentfulEntry", + "Node", + ], + "name": "ContentfulContentTypeNumber", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "id": Object { + "type": "ID!", + }, + "longLocalized": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "longLocalized___NODE", + }, + }, + "type": "ContentfulText", + }, + "longMarkdown": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "longMarkdown___NODE", + }, + }, + "type": "ContentfulText", + }, + "longPlain": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "longPlain___NODE", + }, + }, + "type": "ContentfulText", + }, + "metadata": Object { + "type": "ContentfulMetadata!", + }, + "short": Object { + "type": "String", + }, + "shortList": Object { + "type": "[String]", + }, + "shortListLocalized": Object { + "type": "[String]", + }, + "shortLocalized": Object { + "type": "String", + }, + "sys": Object { + "type": "ContentfulSys!", + }, + "title": Object { + "type": "String", + }, + }, + "interfaces": Array [ + "ContentfulReference", + "ContentfulEntry", + "Node", + ], + "name": "ContentfulContentTypeText", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "id": Object { + "type": "ID!", + }, + "many": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "many___NODE", + }, + }, + "type": "[ContentfulAsset]", + }, + "manyLocalized": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "manyLocalized___NODE", + }, + }, + "type": "[ContentfulAsset]", + }, + "metadata": Object { + "type": "ContentfulMetadata!", + }, + "one": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "one___NODE", + }, + }, + "type": "ContentfulAsset", + }, + "oneLocalized": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "oneLocalized___NODE", + }, + }, + "type": "ContentfulAsset", + }, + "sys": Object { + "type": "ContentfulSys!", + }, + "title": Object { + "type": "String", + }, + }, + "interfaces": Array [ + "ContentfulReference", + "ContentfulEntry", + "Node", + ], + "name": "ContentfulContentTypeMediaReference", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "boolean": Object { + "type": "Boolean", + }, + "booleanLocalized": Object { + "type": "Boolean", + }, + "id": Object { + "type": "ID!", + }, + "metadata": Object { + "type": "ContentfulMetadata!", + }, + "sys": Object { + "type": "ContentfulSys!", + }, + "title": Object { + "type": "String", + }, + }, + "interfaces": Array [ + "ContentfulReference", + "ContentfulEntry", + "Node", + ], + "name": "ContentfulContentTypeBoolean", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "date": Object { + "extensions": Object { + "dateformat": Object {}, + }, + "type": "Date", + }, + "dateLocalized": Object { + "extensions": Object { + "dateformat": Object {}, + }, + "type": "Date", + }, + "dateTime": Object { + "extensions": Object { + "dateformat": Object {}, + }, + "type": "Date", + }, + "dateTimeTimezone": Object { + "extensions": Object { + "dateformat": Object {}, + }, + "type": "Date", + }, + "id": Object { + "type": "ID!", + }, + "metadata": Object { + "type": "ContentfulMetadata!", + }, + "sys": Object { + "type": "ContentfulSys!", + }, + "title": Object { + "type": "String", + }, + }, + "interfaces": Array [ + "ContentfulReference", + "ContentfulEntry", + "Node", + ], + "name": "ContentfulContentTypeDate", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "id": Object { + "type": "ID!", + }, + "location": Object { + "type": "ContentfulLocation", + }, + "locationLocalized": Object { + "type": "ContentfulLocation", + }, + "metadata": Object { + "type": "ContentfulMetadata!", + }, + "sys": Object { + "type": "ContentfulSys!", + }, + "title": Object { + "type": "String", + }, + }, + "interfaces": Array [ + "ContentfulReference", + "ContentfulEntry", + "Node", + ], + "name": "ContentfulContentTypeLocation", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "id": Object { + "type": "ID!", + }, + "json": Object { + "type": "JSON", + }, + "jsonLocalized": Object { + "type": "JSON", + }, + "metadata": Object { + "type": "ContentfulMetadata!", + }, + "sys": Object { + "type": "ContentfulSys!", + }, + "title": Object { + "type": "String", + }, + }, + "interfaces": Array [ + "ContentfulReference", + "ContentfulEntry", + "Node", + ], + "name": "ContentfulContentTypeJson", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "id": Object { + "type": "ID!", + }, + "metadata": Object { + "type": "ContentfulMetadata!", + }, + "richText": Object { + "type": "ContentfulRichText", + }, + "richTextLocalized": Object { + "type": "ContentfulRichText", + }, + "richTextValidated": Object { + "type": "ContentfulRichText", + }, + "sys": Object { + "type": "ContentfulSys!", + }, + "title": Object { + "type": "String", + }, + }, + "interfaces": Array [ + "ContentfulReference", + "ContentfulEntry", + "Node", + ], + "name": "ContentfulContentTypeRichText", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "id": Object { + "type": "ID!", + }, + "many": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "many___NODE", + }, + }, + "type": "[UnionContentfulContentReferenceNumberText]", + }, + "manyLocalized": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "manyLocalized___NODE", + }, + }, + "type": "[ContentfulEntry]", + }, + "metadata": Object { + "type": "ContentfulMetadata!", + }, + "one": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "one___NODE", + }, + }, + "type": "ContentfulEntry", + }, + "oneLocalized": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "oneLocalized___NODE", + }, + }, + "type": "ContentfulEntry", + }, + "sys": Object { + "type": "ContentfulSys!", + }, + "title": Object { + "type": "String", + }, + }, + "interfaces": Array [ + "ContentfulReference", + "ContentfulEntry", + "Node", + ], + "name": "ContentfulContentTypeContentReference", + }, + ], + Array [ + Object { + "extensions": Object { + "dontInfer": Object {}, + }, + "fields": Object { + "id": Object { + "type": "ID!", + }, + "metadata": Object { + "type": "ContentfulMetadata!", + }, + "multipleItemsAllTypes": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "multipleItemsAllTypes___NODE", + }, + }, + "type": "[ContentfulEntry]", + }, + "multipleItemsManyTypes": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "multipleItemsManyTypes___NODE", + }, + }, + "type": "[UnionContentfulNumberText]", + }, + "multipleItemsSingleType": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "multipleItemsSingleType___NODE", + }, + }, + "type": "[ContentfulContentTypeText]", + }, + "oneItemAllTypes": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "oneItemAllTypes___NODE", + }, + }, + "type": "ContentfulEntry", + }, + "oneItemManyTypes": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "oneItemManyTypes___NODE", + }, + }, + "type": "UnionContentfulNumberText", + }, + "oneItemSingleType": Object { + "extensions": Object { + "link": Object { + "by": "id", + "from": "oneItemSingleType___NODE", + }, + }, + "type": "ContentfulContentTypeText", + }, + "sys": Object { + "type": "ContentfulSys!", + }, + "title": Object { + "type": "String", + }, + }, + "interfaces": Array [ + "ContentfulReference", + "ContentfulEntry", + "Node", + ], + "name": "ContentfulContentTypeValidatedContentReference", + }, + ], +] +`; + +exports[`create-schema-customization builds schema based on Contentful Content Model 2`] = ` +Array [ + Array [ + Object { + "fields": Object { + "id": Object { + "type": "ID!", + }, + "sys": Object { + "type": "ContentfulSys!", + }, + }, + "interfaces": Array [ + "Node", + ], + "name": "ContentfulReference", + }, + ], + Array [ + Object { + "fields": Object { + "id": Object { + "type": "ID!", + }, + "metadata": Object { + "type": "ContentfulMetadata!", + }, + "sys": Object { + "type": "ContentfulSys!", + }, + }, + "interfaces": Array [ + "ContentfulReference", + "Node", + ], + "name": "ContentfulEntry", + }, + ], +] +`; + +exports[`create-schema-customization builds schema based on Contentful Content Model 3`] = ` +Array [ + Array [ + Object { + "name": "UnionContentfulContentReferenceNumberText", + "types": Array [ + "ContentfulContentTypeContentReference", + "ContentfulContentTypeNumber", + "ContentfulContentTypeText", + ], + }, + ], + Array [ + Object { + "name": "UnionContentfulNumberText", + "types": Array [ + "ContentfulContentTypeNumber", + "ContentfulContentTypeText", + ], + }, + ], +] +`; diff --git a/packages/gatsby-source-contentful/src/__tests__/create-schema-customization.js b/packages/gatsby-source-contentful/src/__tests__/create-schema-customization.js new file mode 100644 index 0000000000000..9ae3027eddacc --- /dev/null +++ b/packages/gatsby-source-contentful/src/__tests__/create-schema-customization.js @@ -0,0 +1,46 @@ +// @ts-check +import { createSchemaCustomization } from "../create-schema-customization" +import { contentTypes } from "../__fixtures__/content-types" + +const createMockCache = () => { + return { + get: jest.fn(key => contentTypes), + } +} + +describe(`create-schema-customization`, () => { + const actions = { createTypes: jest.fn() } + const schema = { + buildObjectType: jest.fn(), + buildInterfaceType: jest.fn(), + buildUnionType: jest.fn(), + } + const cache = createMockCache() + const reporter = { + info: jest.fn(), + verbose: jest.fn(), + panic: jest.fn(), + activityTimer: () => { + return { start: jest.fn(), end: jest.fn() } + }, + } + + beforeEach(() => { + cache.get.mockClear() + process.env.GATSBY_WORKER_ID = `mocked` + }) + + it(`builds schema based on Contentful Content Model`, async () => { + await createSchemaCustomization( + { schema, actions, reporter, cache }, + { spaceId: `testSpaceId` } + ) + + expect(schema.buildObjectType).toHaveBeenCalled() + expect(schema.buildObjectType.mock.calls).toMatchSnapshot() + expect(schema.buildInterfaceType).toHaveBeenCalled() + expect(schema.buildInterfaceType.mock.calls).toMatchSnapshot() + expect(schema.buildUnionType).toHaveBeenCalled() + expect(schema.buildUnionType.mock.calls).toMatchSnapshot() + }) +}) diff --git a/packages/gatsby-source-contentful/src/generate-schema.js b/packages/gatsby-source-contentful/src/generate-schema.js index 8a87d40e2c8a3..ba68bec289603 100644 --- a/packages/gatsby-source-contentful/src/generate-schema.js +++ b/packages/gatsby-source-contentful/src/generate-schema.js @@ -77,7 +77,64 @@ const ContentfulDataTypes = new Map([ ], ]) -const getLinkFieldType = (linkType, field) => { +const unionsNameSet = new Set() + +const getLinkFieldType = (linkType, field, schema, createTypes) => { + // Check for validations + const validations = + field.type === `Array` ? field.items?.validations : field?.validations + + if (validations) { + // We only handle content type validations + const linkContentTypeValidation = validations.find( + ({ linkContentType }) => !!linkContentType + ) + if (linkContentTypeValidation) { + const { linkContentType } = linkContentTypeValidation + const contentTypes = Array.isArray(linkContentType) + ? linkContentType + : [linkContentType] + + // Full type names for union members, shorter variant for the union type name + const translatedTypeNames = contentTypes.map(typeName => + makeTypeName(typeName) + ) + const shortTypeNames = contentTypes.map(typeName => + makeTypeName(typeName, ``) + ) + + // Single content type + if (translatedTypeNames.length === 1) { + return { + type: translatedTypeNames.shift(), + extensions: { + link: { by: `id`, from: `${field.id}___NODE` }, + }, + } + } + + // Multiple content types + const unionName = [`UnionContentful`, ...shortTypeNames].join(``) + + if (!unionsNameSet.has(unionName)) { + unionsNameSet.add(unionName) + createTypes( + schema.buildUnionType({ + name: unionName, + types: translatedTypeNames, + }) + ) + } + + return { + type: unionName, + extensions: { + link: { by: `id`, from: `${field.id}___NODE` }, + }, + } + } + } + return { type: `Contentful${linkType}`, extensions: { @@ -86,19 +143,19 @@ const getLinkFieldType = (linkType, field) => { } } -const translateFieldType = field => { +const translateFieldType = (field, schema, createTypes) => { let fieldType if (field.type === `Array`) { // Arrays of Contentful Links or primitive types const fieldData = field.items.type === `Link` - ? getLinkFieldType(field.items.linkType, field) - : translateFieldType(field.items) + ? getLinkFieldType(field.items.linkType, field, schema, createTypes) + : translateFieldType(field.items, schema, createTypes) fieldType = { ...fieldData, type: `[${fieldData.type}]` } } else if (field.type === `Link`) { // Contentful Link (reference) field types - fieldType = getLinkFieldType(field.linkType, field) + fieldType = getLinkFieldType(field.linkType, field, schema, createTypes) } else { // Primitive field types fieldType = ContentfulDataTypes.get(field.type)(field) @@ -408,7 +465,7 @@ export function generateSchema({ if (field.disabled || field.omitted) { return } - fields[field.id] = translateFieldType(field) + fields[field.id] = translateFieldType(field, schema, createTypes) }) const type = pluginConfig.get(`useNameForId`) diff --git a/packages/gatsby-source-contentful/src/normalize.js b/packages/gatsby-source-contentful/src/normalize.js index 626859b410d7c..f4c5a914c317f 100644 --- a/packages/gatsby-source-contentful/src/normalize.js +++ b/packages/gatsby-source-contentful/src/normalize.js @@ -3,8 +3,7 @@ import _ from "lodash" import { getGatsbyVersion } from "gatsby-core-utils" import { lt, prerelease } from "semver" -const typePrefix = `ContentfulContentType` -export const makeTypeName = type => +export const makeTypeName = (type, typePrefix = `ContentfulContentType`) => _.upperFirst(_.camelCase(`${typePrefix} ${type}`)) const GATSBY_VERSION_MANIFEST_V2 = `4.3.0`