Skip to content

Commit

Permalink
recipes: Improve providers (#22764)
Browse files Browse the repository at this point in the history
* Don't overwrite files by default

* Handle object style plugin config

* Handle object style plugin config

* Update todo

* Use fs-extra, improve plugin config tests

* Fix file check

* Remove overwrite logic, this will be part of the plan step
  • Loading branch information
johno authored Apr 2, 2020
1 parent f044af7 commit 66ff708
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 57 deletions.
31 changes: 19 additions & 12 deletions packages/gatsby/src/recipes/providers/fs/file.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,42 @@
const fs = require(`fs`)
const fs = require(`fs-extra`)
const path = require(`path`)
const { promisify } = require(`util`)
const mkdirp = require(`mkdirp`)

const readFile = promisify(fs.readFile)
const writeFile = promisify(fs.writeFile)
const destroyFile = promisify(fs.unlink)
const fileExists = ({ root }, { path: filePath }) => {
const fullPath = path.join(root, filePath)
try {
fs.accessSync(fullPath, fs.constants.F_OK)
return true
} catch (e) {
return false
}
}

const create = async ({ root }, { path: filePath, content, children }) => {
const create = async ({ root }, { path: filePath, content }) => {
const fullPath = path.join(root, filePath)
const { dir } = path.parse(fullPath)

content = content || children

await mkdirp(dir)
await writeFile(fullPath, content)
await fs.writeFile(fullPath, content)
}

const update = create

const read = async ({ root }, { path: filePath }) => {
const fullPath = path.join(root, filePath)
const content = await readFile(fullPath, `utf8`)
const content = await fs.readFile(fullPath, `utf8`)

return { content }
}

const destroy = async ({ root }, { path: filePath }) => {
const fullPath = path.join(root, filePath)
await destroyFile(fullPath)
await fs.unlink(fullPath)
}

module.exports.exists = fileExists

module.exports.create = create
module.exports.update = create
module.exports.update = update
module.exports.read = read
module.exports.destroy = destroy
30 changes: 30 additions & 0 deletions packages/gatsby/src/recipes/providers/fs/file.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const file = require(`./file`)

const root = __dirname
const content = `Hello, world!`

test(`create writes a file`, async () => {
const filePath = `bar.txt`

await file.create({ root }, { path: filePath, content })

const result = await file.read({ root }, { path: filePath })

expect(result.content).toEqual(content)

await file.destroy({ root }, { path: filePath })
})

test(`update overwrites a file`, async () => {
const filePath = `bar.txt`
const newContent = `new content!`

await file.create({ root }, { path: filePath, content })
await file.update({ root }, { path: filePath, content: newContent })

const result = await file.read({ root }, { path: filePath })

expect(result.content).toEqual(newContent)

await file.destroy({ root }, { path: filePath })
})
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const redish = `#c5484d`

module.exports = {
siteMetadata: {
title: `Bricolage`,
Expand Down Expand Up @@ -63,8 +62,7 @@ module.exports = {
display: `minimal-ui`,
},
},
`gatsby-plugin-offline`,
// `gatsby-plugin-preact`,
`gatsby-plugin-offline`, // `gatsby-plugin-preact`,
`gatsby-plugin-react-helmet`,
],
}
74 changes: 51 additions & 23 deletions packages/gatsby/src/recipes/providers/gatsby/plugin.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const fs = require(`fs`)
const fs = require(`fs-extra`)
const path = require(`path`)
const babel = require(`@babel/core`)

Expand All @@ -18,6 +18,31 @@ const isDefaultExport = node => {
return true
}

const getValueFromLiteral = node => {
if (node.type === `StringLiteral`) {
return node.value
}

if (node.type === `TemplateLiteral`) {
return node.quasis[0].value.raw
}

return null
}

const getNameForPlugin = node => {
if (node.type === `StringLiteral` || node.type === `TemplateLiteral`) {
return getValueFromLiteral(node)
}

if (node.type === `ObjectExpression`) {
const resolve = node.properties.find(p => p.key.name === `resolve`)
return resolve ? getValueFromLiteral(resolve.value) : null
}

return null
}

const addPluginToConfig = (src, pluginName) => {
const addPlugins = new BabelPluginAddPluginsToGatsbyConfig({
pluginOrThemeName: pluginName,
Expand All @@ -31,31 +56,35 @@ const addPluginToConfig = (src, pluginName) => {
return code
}

const create = ({ root }, { name }) => {
const configPath = path.join(root, `gatsby-config.js`)
const configSrc = fs.readFileSync(configPath)
const getPluginsFromConfig = src => {
const getPlugins = new BabelPluginGetPluginsFromGatsbyConfig()

const code = addPluginToConfig(configSrc, name)
babel.transform(src, {
plugins: [getPlugins.plugin],
})

fs.writeFileSync(configPath, code)
return getPlugins.state
}

const read = ({ root }) => {
const create = async ({ root }, { name }) => {
const configPath = path.join(root, `gatsby-config.js`)
const configSrc = fs.readFileSync(configPath)
const configSrc = await fs.readFile(configPath, `utf8`)

const getPlugins = new BabelPluginGetPluginsFromGatsbyConfig()
const code = addPluginToConfig(configSrc, name)

babel.transform(configSrc, {
plugins: [getPlugins.plugin],
})
await fs.writeFile(configPath, code)
}

return getPlugins.state
const read = async ({ root }) => {
const configPath = path.join(root, `gatsby-config.js`)
const configSrc = await fs.readFile(configPath, `utf8`)

return getPluginsFromConfig(configSrc)
}

const destroy = ({ root }, { name }) => {
const destroy = async ({ root }, { name }) => {
const configPath = path.join(root, `gatsby-config.js`)
const configSrc = fs.readFileSync(configPath)
const configSrc = await fs.readFile(configPath, `utf8`)

const addPlugins = new BabelPluginAddPluginsToGatsbyConfig({
pluginOrThemeName: name,
Expand All @@ -66,7 +95,7 @@ const destroy = ({ root }, { name }) => {
plugins: [addPlugins.plugin],
})

fs.writeFileSync(configPath, code)
await fs.writeFile(configPath, code)
}

class BabelPluginAddPluginsToGatsbyConfig {
Expand All @@ -88,15 +117,14 @@ class BabelPluginAddPluginsToGatsbyConfig {
const plugins = right.properties.find(p => p.key.name === `plugins`)

if (shouldAdd) {
const exists = plugins.value.elements.some(
node => node.value === pluginOrThemeName
)
const pluginNames = plugins.value.elements.map(getNameForPlugin)
const exists = pluginNames.includes(node.value)
if (!exists) {
plugins.value.elements.push(t.stringLiteral(pluginOrThemeName))
}
} else {
plugins.value.elements = plugins.value.elements.filter(
node => node.value !== pluginOrThemeName
node => getNameForPlugin(node) !== pluginOrThemeName
)
}

Expand Down Expand Up @@ -127,9 +155,8 @@ class BabelPluginGetPluginsFromGatsbyConfig {

const plugins = right.properties.find(p => p.key.name === `plugins`)

plugins.value.elements.forEach(node => {
// TODO: handle { resolve: 'thing' }
this.state.push(node.value)
plugins.value.elements.map(node => {
this.state.push(getNameForPlugin(node))
})
},
},
Expand All @@ -139,6 +166,7 @@ class BabelPluginGetPluginsFromGatsbyConfig {
}

module.exports.addPluginToConfig = addPluginToConfig
module.exports.getPluginsFromConfig = getPluginsFromConfig

module.exports.create = create
module.exports.update = create
Expand Down
35 changes: 28 additions & 7 deletions packages/gatsby/src/recipes/providers/gatsby/plugin.test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,35 @@
const fs = require(`fs`)
const path = require(`path`)

const { addPluginToConfig } = require(`./plugin`)
const plugin = require(`./plugin`)

const CONFIG_PATH = path.join(__dirname, `./fixtures/gatsby-config.js`)
const root = path.join(__dirname, `./fixtures`)
const name = `gatsby-plugin-foo`

test(`babel plugin to get list of plugins and their options!`, () => {
const src = fs.readFileSync(CONFIG_PATH, `utf8`)
describe(`gatsby-config`, () => {
test(`adds a plugin to a gatsby config`, async () => {
await plugin.create({ root }, { name })

const result = addPluginToConfig(src, `gatsby-plugin-foo`)
const result = await plugin.read({ root })

expect(result).toMatch(`gatsby-plugin-foo`)
expect(result).toContain(`gatsby-plugin-foo`)

await plugin.destroy({ root }, { name })
})

test(`retrieves plugins from a config`, async () => {
const result = await plugin.read({ root })

expect(result).toEqual([
`gatsby-source-filesystem`,
`gatsby-transformer-sharp`,
`gatsby-plugin-emotion`,
`gatsby-plugin-typography`,
`gatsby-transformer-remark`,
`gatsby-plugin-sharp`,
`gatsby-plugin-google-analytics`,
`gatsby-plugin-manifest`,
`gatsby-plugin-offline`,
`gatsby-plugin-react-helmet`,
])
})
})
17 changes: 6 additions & 11 deletions packages/gatsby/src/recipes/providers/gatsby/shadow-file.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
const path = require(`path`)
const fs = require(`fs`)
const { promisify } = require(`util`)
const fs = require(`fs-extra`)
const mkdirp = require(`mkdirp`)

const readFile = promisify(fs.readFile)
const writeFile = promisify(fs.writeFile)
const destroyFile = promisify(fs.unlink)

const create = async ({ root }, { theme, path: filePath }) => {
const relativePathInTheme = filePath.replace(theme + `/`, ``)
const fullFilePathToShadow = path.join(
Expand All @@ -16,13 +11,13 @@ const create = async ({ root }, { theme, path: filePath }) => {
relativePathInTheme
)

const contents = await readFile(fullFilePathToShadow, `utf8`)
const contents = await fs.readFile(fullFilePathToShadow, `utf8`)

const fullPath = path.join(root, filePath)
const { dir } = path.parse(fullPath)

await mkdirp(dir)
await writeFile(fullPath, contents)
await fs.writeFile(fullPath, contents)
}

const read = async ({ root }, { theme, path: filePath }) => {
Expand All @@ -34,13 +29,13 @@ const read = async ({ root }, { theme, path: filePath }) => {
relativePathInTheme
)

const contents = await readFile(fullFilePathToShadow, `utf8`)
const contents = await fs.readFile(fullFilePathToShadow, `utf8`)
return contents
}

const destroy = async ({ root }, { theme, path: filePath }) => {
const destroy = async ({ root }, { path: filePath }) => {
const fullPath = path.join(root, filePath)
await destroyFile(fullPath)
await fs.unlink(fullPath)
}

module.exports.create = create
Expand Down
5 changes: 4 additions & 1 deletion packages/gatsby/src/recipes/todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@
- [ ] Step by step design
- [ ] Select input supported recipes
- [ ] Make port selection dynamic
- [x] Use `fs-extra`
- [x] Handle object style plugins
- [x] Improve gatsby-config test
- [ ] use yarn/npm based on the user config

## Near-ish future

- [ ] Make a proper "Config" provider to add recipes dir, store data, etc.
- [ ] Client sends the MDX file to the server (maybe?)
- [ ] Move parsing to the server

0 comments on commit 66ff708

Please sign in to comment.