Skip to content

Commit 56fbf8d

Browse files
tyhoppLekoArts
andauthored
feat(gatsby-core-utils,gatsby-cli): Allow write to gatsby-config.ts (#35074)
Co-authored-by: Lennart <[email protected]>
1 parent fb9c014 commit 56fbf8d

File tree

13 files changed

+613
-166
lines changed

13 files changed

+613
-166
lines changed

packages/gatsby-cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"@babel/core": "^7.15.5",
1515
"@babel/generator": "^7.16.8",
1616
"@babel/helper-plugin-utils": "^7.16.7",
17+
"@babel/preset-typescript": "^7.16.7",
1718
"@babel/runtime": "^7.15.4",
1819
"@babel/template": "^7.16.7",
1920
"@babel/types": "^7.16.8",
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`addPlugins gatsby-config.js should not write with no plugins 1`] = `
4+
"module.exports = {
5+
siteMetadata: {
6+
siteUrl: \`https://www.yourdomain.tld\`,
7+
},
8+
plugins: [],
9+
}
10+
"
11+
`;
12+
13+
exports[`addPlugins gatsby-config.js should write a plugin with options 1`] = `
14+
"module.exports = {
15+
siteMetadata: {
16+
siteUrl: \`https://www.yourdomain.tld\`
17+
},
18+
plugins: [{
19+
resolve: 'gatsby-plugin-hello',
20+
options: {
21+
\\"greet\\": true
22+
}
23+
}]
24+
};"
25+
`;
26+
27+
exports[`addPlugins gatsby-config.js should write a single plugin 1`] = `
28+
"module.exports = {
29+
siteMetadata: {
30+
siteUrl: \`https://www.yourdomain.tld\`
31+
},
32+
plugins: [\\"gatsby-plugin-hello\\"]
33+
};"
34+
`;
35+
36+
exports[`addPlugins gatsby-config.js should write multiple plugins 1`] = `
37+
"module.exports = {
38+
siteMetadata: {
39+
siteUrl: \`https://www.yourdomain.tld\`
40+
},
41+
plugins: [\\"gatsby-plugin-hello\\", \\"gatsby-plugin-world\\"]
42+
};"
43+
`;
44+
45+
exports[`addPlugins gatsby-config.ts should not write with no plugins 1`] = `
46+
"import type { GatsbyConfig } from \\"gatsby\\"
47+
48+
const config: GatsbyConfig = {
49+
siteMetadata: {
50+
siteUrl: \`https://www.yourdomain.tld\`,
51+
},
52+
plugins: [],
53+
}
54+
55+
export default config
56+
"
57+
`;
58+
59+
exports[`addPlugins gatsby-config.ts should write a plugin with options 1`] = `
60+
"import type { GatsbyConfig } from \\"gatsby\\";
61+
62+
const config: GatsbyConfig = {
63+
siteMetadata: {
64+
siteUrl: \`https://www.yourdomain.tld\`
65+
},
66+
plugins: [{
67+
resolve: 'gatsby-plugin-hello',
68+
options: {
69+
\\"greet\\": true
70+
}
71+
}]
72+
};
73+
74+
export default config;
75+
"
76+
`;
77+
78+
exports[`addPlugins gatsby-config.ts should write a single plugin 1`] = `
79+
"import type { GatsbyConfig } from \\"gatsby\\";
80+
81+
const config: GatsbyConfig = {
82+
siteMetadata: {
83+
siteUrl: \`https://www.yourdomain.tld\`
84+
},
85+
plugins: [\\"gatsby-plugin-hello\\"]
86+
};
87+
88+
export default config;
89+
"
90+
`;
91+
92+
exports[`addPlugins gatsby-config.ts should write multiple plugins 1`] = `
93+
"import type { GatsbyConfig } from \\"gatsby\\";
94+
95+
const config: GatsbyConfig = {
96+
siteMetadata: {
97+
siteUrl: \`https://www.yourdomain.tld\`
98+
},
99+
plugins: [\\"gatsby-plugin-hello\\", \\"gatsby-plugin-world\\"]
100+
};
101+
102+
export default config;
103+
"
104+
`;
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import { ensureDir, copyFile, readFile, rm } from "fs-extra"
2+
import { join } from "path"
3+
import { addPlugins } from "../../handlers/plugin-add"
4+
5+
/**
6+
* Copy files from minimal starters instead of testing against static gatsby-configs
7+
* in fixtues so that these break if we change the starter configs in a breaking way.
8+
*
9+
* Not using `jest.each` since I find that much harder to read and debug.
10+
* @see {@link https://jestjs.io/docs/api#testeachtablename-fn-timeout}
11+
*/
12+
13+
const root = join(__dirname, `../../../../..`)
14+
const fixtures = join(__dirname, `../fixtures`)
15+
const config = {
16+
js: {
17+
starter: `${root}/starters/gatsby-starter-minimal/gatsby-config.js`,
18+
fixture: `${fixtures}/gatsby-config.js`,
19+
},
20+
ts: {
21+
starter: `${root}/starters/gatsby-starter-minimal-ts/gatsby-config.ts`,
22+
fixture: `${fixtures}/gatsby-config.ts`,
23+
},
24+
}
25+
const plugin = {
26+
hello: `gatsby-plugin-hello`,
27+
world: `gatsby-plugin-world`,
28+
}
29+
30+
describe(`addPlugins`, () => {
31+
beforeAll(async () => {
32+
await ensureDir(fixtures)
33+
})
34+
35+
describe(`gatsby-config.js`, () => {
36+
beforeEach(async () => {
37+
await copyFile(config.js.starter, config.js.fixture)
38+
})
39+
40+
afterEach(async () => {
41+
await rm(config.js.fixture)
42+
})
43+
44+
it(`should not write with no plugins`, async () => {
45+
await addPlugins([], {}, fixtures, [])
46+
const gatsbyConfig = (await readFile(config.js.fixture)).toString()
47+
expect(gatsbyConfig).toMatchSnapshot()
48+
})
49+
50+
it(`should write a single plugin`, async () => {
51+
await addPlugins([plugin.hello], {}, fixtures, [])
52+
const gatsbyConfig = (await readFile(config.js.fixture)).toString()
53+
expect(gatsbyConfig).toMatchSnapshot()
54+
})
55+
56+
it(`should write multiple plugins`, async () => {
57+
await addPlugins([plugin.hello, plugin.world], {}, fixtures, [])
58+
const gatsbyConfig = (await readFile(config.js.fixture)).toString()
59+
expect(gatsbyConfig).toMatchSnapshot()
60+
})
61+
62+
it(`should write a plugin with options`, async () => {
63+
await addPlugins(
64+
[plugin.hello],
65+
{
66+
[plugin.hello]: {
67+
greet: true,
68+
},
69+
},
70+
fixtures,
71+
[]
72+
)
73+
const gatsbyConfig = (await readFile(config.js.fixture)).toString()
74+
expect(gatsbyConfig).toMatchSnapshot()
75+
})
76+
})
77+
78+
describe.skip(`gatsby-config.ts`, () => {
79+
beforeEach(async () => {
80+
await copyFile(config.ts.starter, config.ts.fixture)
81+
})
82+
83+
afterEach(async () => {
84+
await rm(config.ts.fixture)
85+
})
86+
87+
it(`should not write with no plugins`, async () => {
88+
await addPlugins([], {}, fixtures, [])
89+
const gatsbyConfig = (await readFile(config.ts.fixture)).toString()
90+
expect(gatsbyConfig).toMatchSnapshot()
91+
})
92+
93+
it(`should write a single plugin`, async () => {
94+
await addPlugins([plugin.hello], {}, fixtures, [])
95+
const gatsbyConfig = (await readFile(config.ts.fixture)).toString()
96+
expect(gatsbyConfig).toMatchSnapshot()
97+
})
98+
99+
it(`should write multiple plugins`, async () => {
100+
await addPlugins([plugin.hello, plugin.world], {}, fixtures, [])
101+
const gatsbyConfig = (await readFile(config.ts.fixture)).toString()
102+
expect(gatsbyConfig).toMatchSnapshot()
103+
})
104+
105+
it(`should write a plugin with options`, async () => {
106+
await addPlugins(
107+
[plugin.hello],
108+
{
109+
[plugin.hello]: {
110+
greet: true,
111+
},
112+
},
113+
fixtures,
114+
[]
115+
)
116+
const gatsbyConfig = (await readFile(config.ts.fixture)).toString()
117+
expect(gatsbyConfig).toMatchSnapshot()
118+
})
119+
})
120+
})

packages/gatsby-cli/src/handlers/plugin-add-utils.ts

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import {
77
getConfigPath,
88
getConfigStore,
99
} from "gatsby-core-utils"
10-
import { transform } from "@babel/core"
11-
import { BabelPluginAddPluginsToGatsbyConfig } from "./plugin-babel-utils"
10+
import { transform, TransformOptions } from "@babel/core"
11+
import BabelPluginAddPluginsToGatsbyConfig from "./plugin-babel-utils"
1212

1313
const addPluginToConfig = (
1414
src: string,
15+
srcPath: string,
1516
{
1617
name,
1718
options,
@@ -22,19 +23,41 @@ const addPluginToConfig = (
2223
key: string
2324
}
2425
): string => {
25-
const addPlugins = new BabelPluginAddPluginsToGatsbyConfig({
26-
pluginOrThemeName: name,
27-
options,
28-
shouldAdd: true,
29-
key,
30-
})
26+
let code
3127

32-
// @ts-ignore - fix me
33-
const { code } = transform(src, {
34-
// @ts-ignore - fix me
35-
plugins: [addPlugins.plugin],
36-
configFile: false,
37-
})
28+
try {
29+
const transformOptions: TransformOptions = {
30+
plugins: [
31+
[
32+
BabelPluginAddPluginsToGatsbyConfig,
33+
{
34+
pluginOrThemeName: name,
35+
options,
36+
key,
37+
},
38+
],
39+
],
40+
filename: srcPath,
41+
configFile: false,
42+
}
43+
44+
// Use the Babel TS preset if we're operating on `gatsby-config.ts`
45+
if (srcPath.endsWith(`ts`)) {
46+
transformOptions.presets = [`@babel/preset-typescript`]
47+
}
48+
49+
code = transform(src, transformOptions)?.code
50+
51+
// Add back stripped type import, do light formatting, remove added empty module export.
52+
// Use semicolon since Babel does that anyway, and we might as well be consistent.
53+
if (srcPath.endsWith(`ts`)) {
54+
code = `import type { GatsbyConfig } from "gatsby";\n\n${code}`
55+
code = code.replace(`export {};`, ``)
56+
code = code.replace(`export default config;`, `\nexport default config;`)
57+
}
58+
} catch (error) {
59+
console.error(`Failed to transform gatsby config`, error)
60+
}
3861

3962
return code
4063
}
@@ -53,10 +76,13 @@ export const GatsbyPluginCreate = async ({
5376
key,
5477
}: IGatsbyPluginCreateInput): Promise<void> => {
5578
const release = await lock(`gatsby-config.js`)
79+
const configSrcPath = getConfigPath(root)
5680
const configSrc = await readConfigFile(root)
57-
58-
const code = addPluginToConfig(configSrc, { name, options, key })
59-
81+
const code = addPluginToConfig(configSrc, configSrcPath, {
82+
name,
83+
options,
84+
key,
85+
})
6086
await fs.writeFile(getConfigPath(root), code)
6187
release()
6288
}

packages/gatsby-cli/src/handlers/plugin-add.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ async function installPluginConfig(
5454
options,
5555
key: pluginKey,
5656
})
57-
reporter.info(`Installed ${pluginName || pluginKey} in gatsby-config.js`)
57+
reporter.info(`Installed ${pluginName || pluginKey} in gatsby-config`)
5858
} catch (err) {
5959
reporter.error(JSON.parse(err)?.message)
6060
installTimer.setStatus(`FAILED`)

0 commit comments

Comments
 (0)