Skip to content

Commit

Permalink
feat(gatsby-transformer-yaml): support typeName (#13563)
Browse files Browse the repository at this point in the history
see #7914 for json transformer
  • Loading branch information
MeLlamoPablo authored and wardpeet committed Apr 24, 2019
1 parent ea0b46e commit 80c07e6
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 9 deletions.
74 changes: 74 additions & 0 deletions packages/gatsby-transformer-yaml/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,77 @@ Which would return:
```

Please do **note** that `allLettersYaml` **will not** show up if you do not have any `.yaml` files.

## Configuration options

**`typeName`** [string|function][optional]

The default naming convention documented above can be changed with
either a static string value (e.g. to be able to query all yaml with a
simple query):

```javascript
module.exports = {
plugins: [
{
resolve: `gatsby-transformer-yaml`,
options: {
typeName: `Yaml`, // a fixed string
},
},
],
}
```

```graphql
{
allYaml {
edges {
node {
value
}
}
}
}
```

or a function that receives the following arguments:

- `node`: the graphql node that is being processed, e.g. a File node with
yaml content
- `object`: a single object (either an item from an array or the whole yaml content)
- `isArray`: boolean, true if `object` is part of an array

```yaml
- level: info
message: hurray
- level: info
message: it works
- level: warning
message: look out
```
```javascript
module.exports = {
plugins: [
{
resolve: `gatsby-transformer-yaml`,
options: {
typeName: ({ node, object, isArray }) => object.level,
},
},
],
}
```

```graphql
{
allInfo {
edges {
node {
message
}
}
}
}
```
110 changes: 110 additions & 0 deletions packages/gatsby-transformer-yaml/src/__tests__/gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,114 @@ describe(`Process YAML nodes correctly`, () => {
expect(createParentChildLink).toHaveBeenCalledTimes(1)
})
})

it(`correctly sets node type for array of objects`, () =>
Promise.all(
[
{
typeName: null,
expectedNodeTypes: [`TestYaml`, `TestYaml`],
},
{
typeName: `fixed`,
expectedNodeTypes: [`fixed`, `fixed`],
},
{
typeName: ({ node, object }) => object.funny,
expectedNodeTypes: [`yup`, `nope`],
},
].map(
async ({ typeName, expectedNodeTypes: [expectedOne, expectedTwo] }) => {
const data = [
{ id: `foo`, blue: true, funny: `yup` },
{ blue: false, funny: `nope` },
]

node.content = yaml.safeDump(data)
node.dir = `${os.tmpdir()}/bar/`

const createNode = jest.fn()
const createParentChildLink = jest.fn()
const actions = { createNode, createParentChildLink }
const createNodeId = jest.fn()
createNodeId.mockReturnValue(`uuid-from-gatsby`)
const createContentDigest = jest.fn().mockReturnValue(`contentDigest`)

return onCreateNode(
{
node,
loadNodeContent,
actions,
createNodeId,
createContentDigest,
},
{ typeName }
).then(() => {
expect(createNode).toBeCalledWith(
expect.objectContaining({
internal: expect.objectContaining({
type: expectedOne,
}),
})
)
expect(createNode).toBeCalledWith(
expect.objectContaining({
internal: expect.objectContaining({
type: expectedTwo,
}),
})
)
})
}
)
))

it(`correctly sets node type for single object`, () =>
Promise.all(
[
{
typeName: null,
expectedNodeType: `TestdirYaml`,
},
{
typeName: `fixed`,
expectedNodeType: `fixed`,
},
{
typeName: ({ node, object }) => object.funny,
expectedNodeType: `yup`,
},
].map(async ({ typeName, expectedNodeType }) => {
const data = { id: `foo`, blue: true, funny: `yup` }

node.content = yaml.safeDump(data)
node.dir = `${os.tmpdir()}/testdir/`

const createNode = jest.fn()
const createParentChildLink = jest.fn()
const actions = { createNode, createParentChildLink }
const createNodeId = jest.fn()
createNodeId.mockReturnValue(`uuid-from-gatsby`)
const createContentDigest = jest.fn().mockReturnValue(`contentDigest`)

return onCreateNode(
{
node,
loadNodeContent,
actions,
createNodeId,
createContentDigest,
},
{ typeName }
).then(() => {
expect(createNode).toBeCalledWith(
expect.objectContaining({
internal: expect.objectContaining({
type: expectedNodeType,
}),
})
)
})
})
))
})
27 changes: 18 additions & 9 deletions packages/gatsby-transformer-yaml/src/gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@ const jsYaml = require(`js-yaml`)
const _ = require(`lodash`)
const path = require(`path`)

async function onCreateNode({
node,
actions,
loadNodeContent,
createNodeId,
createContentDigest,
}) {
async function onCreateNode(
{ node, actions, loadNodeContent, createNodeId, createContentDigest },
pluginOptions
) {
function getType({ node, object, isArray }) {
if (pluginOptions && _.isFunction(pluginOptions.typeName)) {
return pluginOptions.typeName({ node, object, isArray })
} else if (pluginOptions && _.isString(pluginOptions.typeName)) {
return pluginOptions.typeName
} else if (isArray) {
return _.upperFirst(_.camelCase(`${node.name} Yaml`))
} else {
return _.upperFirst(_.camelCase(`${path.basename(node.dir)} Yaml`))
}
}

function transformObject(obj, id, type) {
const yamlNode = {
...obj,
Expand Down Expand Up @@ -38,14 +47,14 @@ async function onCreateNode({
transformObject(
obj,
obj.id ? obj.id : createNodeId(`${node.id} [${i}] >>> YAML`),
_.upperFirst(_.camelCase(`${node.name} Yaml`))
getType({ node, object: obj, isArray: true })
)
})
} else if (_.isPlainObject(parsedContent)) {
transformObject(
parsedContent,
parsedContent.id ? parsedContent.id : createNodeId(`${node.id} >>> YAML`),
_.upperFirst(_.camelCase(`${path.basename(node.dir)} Yaml`))
getType({ node, object: parsedContent, isArray: false })
)
}
}
Expand Down

0 comments on commit 80c07e6

Please sign in to comment.