The standard process for converting MD to HTML in Gatsby is for complete files on the local system.
I need to convert a specific field, NOT a file. The top related question is this one, but as you can see that is using Contentful, which now provides a plugin to solve it.
The API I am using (Airtable) is returning a field that contains Markdown.
The recommended solution is to convert using a resolver...but I cannot fully understand the Gatsby docs on the topic.
The error I see when building is this:
UNHANDLED REJECTION Airtable.FAQ provided incorrect OutputType:
'Object({ resolve: [function resolve], extensions: Object({ createdFrom: "createResolvers" }) })'
I think I am close, but I don't know if I am meant to create a new type or actually what the resolver is meant to return...a new field?
The field in question is FAQ
, which you can see in this example of a query in the GraphQL explorer:
query MyQuery {
allAirtableManufacturer(filter: {data: {Premium: {eq: true}}}) {
edges {
node {
data {
Premium
Manufacturer
Premium_Manufacturers {
recordId
data {
FAQ
Downloads_File_Name
Is_Supplier
}
internal {
type
}
}
}
recordId
queryName
}
}
}
}
My understanding is that the resolver can/should add a new field with the markdown content converted to html.
So here is my resolver code, where you can see I am trying to add a field called "FAQ_html" to the Airtable node:
createResolvers({
Airtable: {
FAQ_html: {
resolve(source: any, args: any, context: any, info: any) {
return remark().use(html).processSync(source.data.FAQ).contents
},
},
}
})
My gatsby-config for airtable is:
resolve: `gatsby-source-airtable`,
options: {
apiKey: process.env.AIRTABLE_API_KEY,
concurrency: 5,
tables: [
{
baseId: `appP5vBdAitw6yyDH`,
tableName: `Manufacturers`,
queryName: `Manufacturer`,
tableView: `AppView_Details_DONOTCHANGE`,
tableLinks: [`Premium_Manufacturers`],
separateNodeType: true,
defaultValues: {
Company_Description: '',
},
},
{
baseId: `appP5vBdAitw6yyDH`,
tableName: 'Premium_Manufacturers',
tableLinks: [`Manufacturers`],
},
],
The table 'Premium_Manufacturers' is obviously linked as a child to 'Manufacturers'.
However, when I explore in GraphQL I also see them appear as a top-level node called 'Airtable', which I did not expect. You can see that here:
allAirtable {
edges {
node {
data {
FAQ
Downloads_File_Name
Last_update
Is_Supplier
Section_Name
Section_No
Name
Cell_Number
Email
Rep_Name
Technical_Rep_Name
Consolidated_Rep
}
}
}
}
That's why my resolver uses 'Airtable' as the name of the node, but clearly it does not work.
I also tried changing the config to provide a separate node:
{
baseId: `appP5vBdAitw6yyDH`,
tableName: 'Premium_Manufacturers',
queryName: 'Premium',
separateNodeType: true,
tableLinks: [`Manufacturers`],
},
so now 'allAirtable' becomes 'allAirtablePremium'.
I tried changing the resolver to use that:
createResolvers({
allAirtablePremium: {
FAQ_html: {
resolve(source: any, args: any, context: any, info: any) {
return remark().use(html).processSync(source.data.FAQ).contents
},
},
}
})
But that throws a warning:
warn `createResolvers` passed resolvers for type `allAirtablePremium` that doesn't exist in the schema.
So clearly it doesn't like the 'all', so then I changed it to remove the 'all' like so:
createResolvers({
AirtablePremium: {
FAQ_html: {
resolve(source: any, args: any, context: any, info: any) {
return remark().use(html).processSync(source.data.FAQ).contents
},
},
}
})
And I am back to the original error, which at least tells me there is something wrong with what I am trying to return (as the error clearly says 'wrong OutputType').
So what should that be returning?
Thanks in advance for any help!
UPDATE 1
The code now compiles, but I don't see my custom field.
This is the schema customisation (just create FAQ_HTML as an empty string to start off):
import { GatsbyNode, CreateSchemaCustomizationArgs } from 'gatsby'
export const createSchemaCustomization: GatsbyNode['createSchemaCustomization'] = async ({
actions,
}: CreateSchemaCustomizationArgs) => {
const { createFieldExtension, createTypes } = actions
createFieldExtension({
name: "FAQ_HTML",
extend() {
return ''
},
})
const typeDefs = `
type airtablePremium implements Node {
FAQ_HTML: String @FAQ_HTML
}
`
createTypes(typeDefs)
}
The resolver is now like this:
createResolvers({
airtablePremium: {
FAQ_HTML: {
resolve(source: any, args: any, context: any, info: any) {
console.log("SOURCE IS", source)
const faqHtml = remark().use(html).processSync(source.FAQ).contents
console.log("faqHtml IS", faqHtml)
return faqHtml;
},
},
},
})
It compiles but the field does not show up in the GraphQL explorer. No console output either.