Skip to content

Commit 0da9120

Browse files
TylerBarneswardpeet
authored andcommitted
feat(gatsby-source-wordpress): allow path to js file for beforeChangeNode option (#32901)
* Allow path to js file for beforeChangeNode option * ensure Joi doesn't fail the build for inline beforeChangeNode fn's * Create gatsby-version.ts * Panic on Gatsby v4+ if beforeChangeNode is a function.
1 parent f04a966 commit 0da9120

File tree

11 files changed

+136
-5
lines changed

11 files changed

+136
-5
lines changed

integration-tests/gatsby-source-wordpress/__tests__/__snapshots__/index.js.snap

+2
Original file line numberDiff line numberDiff line change
@@ -4380,6 +4380,7 @@ Array [
43804380
"title",
43814381
"uri",
43824382
"nodeType",
4383+
"beforeChangeNodeTest",
43834384
"parent",
43844385
"children",
43854386
"internal",
@@ -4596,6 +4597,7 @@ Array [
45964597
"toPing",
45974598
"uri",
45984599
"nodeType",
4600+
"beforeChangeNodeTest",
45994601
"parent",
46004602
"children",
46014603
"internal",

integration-tests/gatsby-source-wordpress/gatsby-config.js

+8
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const wpPluginOptions = !process.env.DEFAULT_PLUGIN_OPTIONS
4040
},
4141
Page: {
4242
excludeFieldNames: [`enclosure`],
43+
beforeChangeNode: `./src/before-change-page.js`,
4344
},
4445
DatabaseIdentifier: {
4546
exclude: true,
@@ -66,6 +67,13 @@ const wpPluginOptions = !process.env.DEFAULT_PLUGIN_OPTIONS
6667
50
6768
: // and we don't actually need more than 1000 in production
6869
1000,
70+
71+
beforeChangeNode: ({ remoteNode }) => {
72+
console.log(`Hi from an inline fn!`)
73+
remoteNode.beforeChangeNodeTest = `TEST-${remoteNode.id}`
74+
75+
return remoteNode
76+
},
6977
},
7078
// excluding this because it causes Gatsby to throw errors
7179
BlockEditorContentNode: { exclude: true },
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
exports.createSchemaCustomization = ({ actions }) => {
2+
const { createTypes } = actions
3+
const typeDefs = `
4+
type WpPage {
5+
beforeChangeNodeTest: String
6+
}
7+
type WpPost {
8+
beforeChangeNodeTest: String
9+
}
10+
`
11+
createTypes(typeDefs)
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = ({ remoteNode }) => {
2+
remoteNode.beforeChangeNodeTest = `TEST-${remoteNode.id}`
3+
4+
return remoteNode
5+
}

integration-tests/gatsby-source-wordpress/test-fns/data-resolution.js

+32
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,38 @@ describe(`data resolution`, () => {
219219
expect(result.data.testUser.name).toEqual(`admin`)
220220
})
221221

222+
it(`resolves data added via a fn file in onBeforeChangeNode type option`, async () => {
223+
const result = await fetchGraphql({
224+
url,
225+
query: /* GraphQL */ `
226+
{
227+
# fn as a file path
228+
allWpPage {
229+
nodes {
230+
id
231+
beforeChangeNodeTest
232+
}
233+
}
234+
# inline fn in gatsby-config.js
235+
# support for this will be removed in future versions
236+
allWpPost {
237+
nodes {
238+
id
239+
beforeChangeNodeTest
240+
}
241+
}
242+
}
243+
`,
244+
})
245+
246+
result.data.allWpPage.nodes.forEach(node => {
247+
expect(node.beforeChangeNodeTest).toBe(`TEST-${node.id}`)
248+
})
249+
result.data.allWpPost.nodes.forEach(node => {
250+
expect(node.beforeChangeNodeTest).toBe(`TEST-${node.id}`)
251+
})
252+
})
253+
222254
it(`resolves root fields`, async () => {
223255
const result = await fetchGraphql({
224256
url,

packages/gatsby-source-wordpress/__tests__/plugin-options-schema.test.js

+8
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ describe(`pluginOptionsSchema`, () => {
9696
MenuItem: {
9797
beforeChangeNode: null,
9898
},
99+
Page: {
100+
beforeChangeNode: `./docs-generation.test.js`,
101+
},
102+
Post: {
103+
beforeChangeNode: () => {
104+
console.log(`Hi from an inline fn!`)
105+
},
106+
},
99107
EnqueuedScript: {
100108
exclude: true,
101109
},

packages/gatsby-source-wordpress/docs/plugin-options.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1107,9 +1107,9 @@ Determines whether or not this type will be treated as an interface comprised en
11071107

11081108
#### type.\_\_all.beforeChangeNode
11091109

1110-
A function which is invoked before a node is created, updated, or deleted. This is a hook in point to modify the node or perform side-effects related to it.
1110+
A function which is invoked before a node is created, updated, or deleted. This is a hook in point to modify the node or perform side-effects related to it. This option should be a path to a JS file where the default export is the beforeChangeNode function. The path can be relative to your gatsby-node.js or absolute. Currently you can inline a function by writing it out directly in this option but starting from Gatsby v4 only a path to a function file will work.
11111111

1112-
**Field type**: `Function`
1112+
**Field type**: `String | Function`
11131113

11141114
### type.RootQuery
11151115

packages/gatsby-source-wordpress/generate-plugin-options-docs.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,10 @@ function joiKeysToMD({
6060
(value.meta && value.meta.find(meta => `trueType` in meta)) || {}
6161

6262
mdString += `\n\n`
63-
mdString += `**Field type**: \`${_.startCase(trueType || value.type)}\``
63+
mdString += `**Field type**: \`${(trueType || value.type)
64+
.split(`|`)
65+
.map(typename => _.startCase(typename))
66+
.join(` | `)}\``
6467
}
6568

6669
if (

packages/gatsby-source-wordpress/src/steps/declare-plugin-options-schema.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,10 @@ const pluginOptionsSchema = ({ Joi }) => {
8888
.allow(null)
8989
.allow(false)
9090
.meta({
91-
trueType: `function`,
91+
trueType: `string|function`,
9292
})
9393
.description(
94-
`A function which is invoked before a node is created, updated, or deleted. This is a hook in point to modify the node or perform side-effects related to it.`
94+
`A function which is invoked before a node is created, updated, or deleted. This is a hook in point to modify the node or perform side-effects related to it. This option should be a path to a JS file where the default export is the beforeChangeNode function. The path can be relative to your gatsby-node.js or absolute. Currently you can inline a function by writing it out directly in this option but starting from Gatsby v4 only a path to a function file will work.`
9595
),
9696
})
9797

packages/gatsby-source-wordpress/src/steps/process-and-validate-plugin-options.ts

+56
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import path from "path"
12
import { formatLogMessage } from "~/utils/format-log-message"
23
import isInteger from "lodash/isInteger"
34
import { IPluginOptions } from "~/models/gatsby-api"
45
import { GatsbyNodeApiHelpers } from "~/utils/gatsby-types"
6+
import { usingGatsbyV4OrGreater } from "~/utils/gatsby-version"
57
interface IProcessorOptions {
68
userPluginOptions: IPluginOptions
79
helpers: GatsbyNodeApiHelpers
@@ -46,6 +48,60 @@ const optionsProcessors: Array<IOptionsProcessor> = [
4648

4749
delete userPluginOptions.schema.queryDepth
4850

51+
return userPluginOptions
52+
},
53+
},
54+
{
55+
name: `Require beforeChangeNode type setting functions by absolute or relative path`,
56+
test: ({ userPluginOptions }: IProcessorOptions): boolean =>
57+
!!userPluginOptions?.type,
58+
processor: ({
59+
helpers,
60+
userPluginOptions,
61+
}: IProcessorOptions): IPluginOptions => {
62+
const gatsbyStore = helpers.store.getState()
63+
const typeSettings = Object.entries(userPluginOptions.type)
64+
65+
typeSettings.forEach(([typeName, settings]) => {
66+
const beforeChangeNodePath = settings?.beforeChangeNode
67+
68+
if (
69+
usingGatsbyV4OrGreater &&
70+
typeof beforeChangeNodePath === `function`
71+
) {
72+
helpers.reporter.panic(
73+
`Since Gatsby v4+ you cannot use the ${typeName}.beforeChangeNode option as a function. Please make the option a relative or absolute path to a JS file where the beforeChangeNode fn is the default export.`
74+
)
75+
}
76+
77+
if (!beforeChangeNodePath || typeof beforeChangeNodePath !== `string`) {
78+
return
79+
}
80+
81+
try {
82+
const absoluteRequirePath: string | undefined = path.isAbsolute(
83+
beforeChangeNodePath
84+
)
85+
? beforeChangeNodePath
86+
: require.resolve(
87+
path.join(gatsbyStore.program.directory, beforeChangeNodePath)
88+
)
89+
90+
const beforeChangeNodeFn = require(absoluteRequirePath)
91+
92+
if (beforeChangeNodeFn) {
93+
userPluginOptions.type[typeName].beforeChangeNode =
94+
beforeChangeNodeFn
95+
}
96+
} catch (e) {
97+
helpers.reporter.panic(
98+
formatLogMessage(
99+
`beforeChangeNode type setting for ${typeName} threw error:\n${e.message}`
100+
)
101+
)
102+
}
103+
})
104+
49105
return userPluginOptions
50106
},
51107
},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import semver from "semver"
2+
const gatsbyVersion = require(`gatsby/package.json`)?.version
3+
4+
// gt = greater than
5+
export const usingGatsbyV4OrGreater = semver.gt(gatsbyVersion, `4.0.0`)

0 commit comments

Comments
 (0)