diff --git a/packages/gatsby-source-contentful/package.json b/packages/gatsby-source-contentful/package.json
index 817abc3b7fa7b..56e09ead6fde7 100644
--- a/packages/gatsby-source-contentful/package.json
+++ b/packages/gatsby-source-contentful/package.json
@@ -34,7 +34,7 @@
],
"license": "MIT",
"peerDependencies": {
- "gatsby": ">2.0.0-alpha"
+ "gatsby": "^2.0.33"
},
"repository": "https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-source-contentful",
"scripts": {
diff --git a/packages/gatsby-source-contentful/src/gatsby-node.js b/packages/gatsby-source-contentful/src/gatsby-node.js
index 9f922498dc0c4..ac425b77f332c 100644
--- a/packages/gatsby-source-contentful/src/gatsby-node.js
+++ b/packages/gatsby-source-contentful/src/gatsby-node.js
@@ -216,7 +216,7 @@ exports.sourceNodes = async (
// Check if there are any ContentfulAsset nodes and if gatsby-image is installed. If so,
// add fragments for ContentfulAsset and gatsby-image. The fragment will cause an error
// if there's not ContentfulAsset nodes and without gatsby-image, the fragment is useless.
-exports.onPreExtractQueries = async ({ store, getNodes }) => {
+exports.onPreExtractQueries = async ({ store, getNodesByType }) => {
const program = store.getState().program
const CACHE_DIR = path.resolve(
@@ -224,9 +224,7 @@ exports.onPreExtractQueries = async ({ store, getNodes }) => {
)
await fs.ensureDir(CACHE_DIR)
- const nodes = getNodes()
-
- if (!nodes.some(n => n.internal.type === `ContentfulAsset`)) {
+ if (getNodesByType(`ContentfulAsset`).length == 0) {
return
}
diff --git a/packages/gatsby-transformer-remark/package.json b/packages/gatsby-transformer-remark/package.json
index b5fd86d2671d1..796e94ffb0066 100644
--- a/packages/gatsby-transformer-remark/package.json
+++ b/packages/gatsby-transformer-remark/package.json
@@ -42,7 +42,7 @@
],
"license": "MIT",
"peerDependencies": {
- "gatsby": ">2.0.0-alpha"
+ "gatsby": "^2.0.33"
},
"repository": "https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-transformer-remark",
"scripts": {
diff --git a/packages/gatsby-transformer-remark/src/__tests__/extend-node.js b/packages/gatsby-transformer-remark/src/__tests__/extend-node.js
index 51fcb01df9803..53b3eeca6b783 100644
--- a/packages/gatsby-transformer-remark/src/__tests__/extend-node.js
+++ b/packages/gatsby-transformer-remark/src/__tests__/extend-node.js
@@ -11,7 +11,12 @@ const {
const extendNodeType = require(`../extend-node-type`)
// given a set of nodes and a query, return the result of the query
-async function queryResult(nodes, fragment, { types = [] } = {}, additionalParameters) {
+async function queryResult(
+ nodes,
+ fragment,
+ { types = [] } = {},
+ additionalParameters
+) {
const inferredFields = inferObjectStructureFromNodes({
nodes,
types: [...types],
@@ -23,7 +28,7 @@ async function queryResult(nodes, fragment, { types = [] } = {}, additionalParam
get: () => null,
set: () => null,
},
- getNodes: () => [],
+ getNodesByType: type => [],
...additionalParameters,
},
{
@@ -70,7 +75,13 @@ async function queryResult(nodes, fragment, { types = [] } = {}, additionalParam
return result
}
-const bootstrapTest = (label, content, query, test, additionalParameters = {}) => {
+const bootstrapTest = (
+ label,
+ content,
+ query,
+ test,
+ additionalParameters = {}
+) => {
const node = {
id: `whatever`,
children: [],
@@ -82,7 +93,7 @@ const bootstrapTest = (label, content, query, test, additionalParameters = {}) =
// Make some fake functions its expecting.
const loadNodeContent = node => Promise.resolve(node.content)
- it(label, async (done) => {
+ it(label, async done => {
node.content = content
const createNode = markdownNode => {
queryResult(
@@ -96,8 +107,7 @@ const bootstrapTest = (label, content, query, test, additionalParameters = {}) =
try {
test(result.data.listNode[0])
done()
- }
- catch(err) {
+ } catch (err) {
done.fail(err)
}
})
@@ -106,19 +116,19 @@ const bootstrapTest = (label, content, query, test, additionalParameters = {}) =
const actions = { createNode, createParentChildLink }
const createNodeId = jest.fn()
createNodeId.mockReturnValue(`uuid-from-gatsby`)
- await onCreateNode({
- node,
- loadNodeContent,
- actions,
- createNodeId,
- },
- { ...additionalParameters }
+ await onCreateNode(
+ {
+ node,
+ loadNodeContent,
+ actions,
+ createNodeId,
+ },
+ { ...additionalParameters }
)
- })
+ })
}
describe(`Excerpt is generated correctly from schema`, () => {
-
bootstrapTest(
`correctly loads an excerpt`,
`---
@@ -131,7 +141,7 @@ Where oh where is my little pony?`,
title
}
`,
- (node) => {
+ node => {
expect(node).toMatchSnapshot()
expect(node.excerpt).toMatch(`Where oh where is my little pony?`)
}
@@ -148,7 +158,7 @@ date: "2017-09-18T23:19:51.246Z"
title
}
`,
- (node) => {
+ node => {
expect(node).toMatchSnapshot()
expect(node.excerpt).toMatch(``)
}
@@ -171,7 +181,7 @@ In quis lectus sed eros efficitur luctus. Morbi tempor, nisl eget feugiat tincid
title
}
`,
- (node) => {
+ node => {
expect(node).toMatchSnapshot()
expect(node.excerpt).toMatch(`Where oh where is my little pony?`)
},
@@ -194,7 +204,7 @@ In quis lectus sed eros efficitur luctus. Morbi tempor, nisl eget feugiat tincid
title
}
`,
- (node) => {
+ node => {
expect(node).toMatchSnapshot()
expect(node.excerpt.length).toBe(139)
}
@@ -208,7 +218,7 @@ In quis lectus sed eros efficitur luctus. Morbi tempor, nisl eget feugiat tincid
title
}
`,
- (node) => {
+ node => {
expect(node).toMatchSnapshot()
expect(node.excerpt.length).toBe(46)
}
@@ -222,7 +232,7 @@ In quis lectus sed eros efficitur luctus. Morbi tempor, nisl eget feugiat tincid
title
}
`,
- (node) => {
+ node => {
expect(node).toMatchSnapshot()
expect(node.excerpt.length).toBe(50)
}
@@ -248,16 +258,15 @@ In quis lectus sed eros efficitur luctus. Morbi tempor, nisl eget feugiat tincid
frontmatter {
title
}`,
- (node) => {
+ node => {
expect(node).toMatchSnapshot()
- expect(node.wordCount).toEqual(
- {
+ expect(node.wordCount).toEqual({
paragraphs: 2,
sentences: 19,
words: 150,
- }
- )
- })
+ })
+ }
+ )
const content = `---
title: "my little pony"
@@ -276,16 +285,15 @@ date: "2017-09-18T23:19:51.246Z"
frontmatter {
title
}`,
- (node) => {
+ node => {
expect(node).toMatchSnapshot()
- expect(node.wordCount).toEqual(
- {
+ expect(node.wordCount).toEqual({
paragraphs: null,
sentences: null,
words: null,
- }
- )
- })
+ })
+ }
+ )
bootstrapTest(
`correctly uses a default value for timeToRead`,
@@ -294,10 +302,11 @@ date: "2017-09-18T23:19:51.246Z"
frontmatter {
title
}`,
- (node) => {
+ node => {
expect(node).toMatchSnapshot()
expect(node.timeToRead).toBe(1)
- })
+ }
+ )
})
describe(`Table of contents is generated correctly from schema`, () => {
@@ -322,11 +331,12 @@ some other text
frontmatter {
title
}`,
- (node) => {
+ node => {
expect(node).toMatchSnapshot()
expect(console.warn).toBeCalled()
expect(node.tableOfContents).toBe(null)
- })
+ }
+ )
bootstrapTest(
`correctly generates table of contents`,
@@ -350,9 +360,10 @@ final text
frontmatter {
title
}`,
- (node) => {
- expect(node).toMatchSnapshot()
- })
+ node => {
+ expect(node).toMatchSnapshot()
+ }
+ )
})
describe(`Links are correctly prefixed`, () => {
@@ -366,7 +377,7 @@ This is [a reference]
[a reference]: /path/to/page2
`,
`html`,
- (node) => {
+ node => {
expect(node).toMatchSnapshot()
expect(node.html).toMatch(``)
expect(node.html).toMatch(``)
diff --git a/packages/gatsby-transformer-remark/src/extend-node-type.js b/packages/gatsby-transformer-remark/src/extend-node-type.js
index fe95b3fd7bc48..07827d42b1458 100644
--- a/packages/gatsby-transformer-remark/src/extend-node-type.js
+++ b/packages/gatsby-transformer-remark/src/extend-node-type.js
@@ -62,7 +62,7 @@ const withPathPrefix = (url, pathPrefix) =>
const ASTPromiseMap = new Map()
module.exports = (
- { type, store, pathPrefix, getNode, getNodes, cache, reporter },
+ { type, store, pathPrefix, getNode, getNodesByType, cache, reporter },
pluginOptions
) => {
if (type.name !== `MarkdownRemark`) {
@@ -74,7 +74,13 @@ module.exports = (
return new Promise((resolve, reject) => {
// Setup Remark.
- const { commonmark = true, footnotes = true, pedantic = true, gfm = true, blocks } = pluginOptions
+ const {
+ commonmark = true,
+ footnotes = true,
+ pedantic = true,
+ gfm = true,
+ blocks,
+ } = pluginOptions
const remarkOptions = {
gfm,
commonmark,
@@ -113,7 +119,7 @@ module.exports = (
} else {
const ASTGenerationPromise = new Promise(async resolve => {
if (process.env.NODE_ENV !== `production` || !fileNodes) {
- fileNodes = getNodes().filter(n => n.internal.type === `File`)
+ fileNodes = getNodesByType(`File`)
}
const ast = await new Promise((resolve, reject) => {
// Use Bluebird's Promise function "each" to run remark plugins serially.
@@ -180,7 +186,7 @@ module.exports = (
// typegen plugins just modify the auto-generated types to add derived fields
// as well as computationally expensive fields.
if (process.env.NODE_ENV !== `production` || !fileNodes) {
- fileNodes = getNodes().filter(n => n.internal.type === `File`)
+ fileNodes = getNodesByType(`File`)
}
// Use Bluebird's Promise function "each" to run remark plugins serially.
Promise.each(pluginOptions.plugins, plugin => {
@@ -249,10 +255,16 @@ module.exports = (
const addSlugToUrl = function(node) {
if (node.url) {
if (_.get(markdownNode, pathToSlugField) === undefined) {
- console.warn(`Skipping TableOfContents. Field '${pathToSlugField}' missing from markdown node`)
+ console.warn(
+ `Skipping TableOfContents. Field '${pathToSlugField}' missing from markdown node`
+ )
return null
}
- node.url = [pathPrefix, _.get(markdownNode, pathToSlugField), node.url]
+ node.url = [
+ pathPrefix,
+ _.get(markdownNode, pathToSlugField),
+ node.url,
+ ]
.join(`/`)
.replace(/\/\//g, `/`)
}
diff --git a/packages/gatsby-transformer-screenshot/package.json b/packages/gatsby-transformer-screenshot/package.json
index 69bea066974ea..933cc371107dc 100644
--- a/packages/gatsby-transformer-screenshot/package.json
+++ b/packages/gatsby-transformer-screenshot/package.json
@@ -25,7 +25,7 @@
"license": "MIT",
"main": "index.js",
"peerDependencies": {
- "gatsby": ">2.0.15"
+ "gatsby": "^2.0.33"
},
"repository": "https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-transformer-screenshot",
"scripts": {
diff --git a/packages/gatsby-transformer-screenshot/src/gatsby-node.js b/packages/gatsby-transformer-screenshot/src/gatsby-node.js
index 8dfbf597d2c58..7461380add999 100644
--- a/packages/gatsby-transformer-screenshot/src/gatsby-node.js
+++ b/packages/gatsby-transformer-screenshot/src/gatsby-node.js
@@ -16,13 +16,11 @@ const screenshotQueue = new Queue(
)
exports.onPreBootstrap = (
- { store, cache, actions, createNodeId, getNodes, createContentDigest },
+ { store, cache, actions, createNodeId, getNodesByType, createContentDigest },
pluginOptions
) => {
const { createNode, touchNode } = actions
- const screenshotNodes = getNodes().filter(
- n => n.internal.type === `Screenshot`
- )
+ const screenshotNodes = getNodesByType(`Screenshot`)
if (screenshotNodes.length === 0) {
return null
diff --git a/packages/gatsby-transformer-sharp/package.json b/packages/gatsby-transformer-sharp/package.json
index d28af3123ab2c..395d2355b9530 100644
--- a/packages/gatsby-transformer-sharp/package.json
+++ b/packages/gatsby-transformer-sharp/package.json
@@ -29,7 +29,7 @@
],
"license": "MIT",
"peerDependencies": {
- "gatsby": ">2.0.0-alpha",
+ "gatsby": "^2.0.33",
"gatsby-plugin-sharp": "^2.0.0-beta.3"
},
"repository": "https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-transformer-sharp",
diff --git a/packages/gatsby-transformer-sharp/src/gatsby-node.js b/packages/gatsby-transformer-sharp/src/gatsby-node.js
index 2bb6f5ac6ce6d..3f9433c15f639 100644
--- a/packages/gatsby-transformer-sharp/src/gatsby-node.js
+++ b/packages/gatsby-transformer-sharp/src/gatsby-node.js
@@ -3,14 +3,12 @@ const fs = require(`fs-extra`)
exports.onCreateNode = require(`./on-node-create`)
exports.setFieldsOnGraphQLNodeType = require(`./extend-node-type`)
-exports.onPreExtractQueries = async ({ store, getNodes }) => {
+exports.onPreExtractQueries = async ({ store, getNodesByType }) => {
const program = store.getState().program
// Check if there are any ImageSharp nodes. If so add fragments for ImageSharp.
// The fragment will cause an error if there are no ImageSharp nodes.
- const nodes = getNodes()
-
- if (!nodes.some(n => n.internal.type === `ImageSharp`)) {
+ if (getNodesByType(`ImageSharp`).length == 0) {
return
}
diff --git a/packages/gatsby/src/bootstrap/index.js b/packages/gatsby/src/bootstrap/index.js
index 261007bd6d7a5..a302452d098fc 100644
--- a/packages/gatsby/src/bootstrap/index.js
+++ b/packages/gatsby/src/bootstrap/index.js
@@ -52,6 +52,10 @@ module.exports = async (args: BootstrapArgs) => {
const spanArgs = args.parentSpan ? { childOf: args.parentSpan } : {}
const bootstrapSpan = tracer.startSpan(`bootstrap`, spanArgs)
+ // Start plugin runner which listens to the store
+ // and invokes Gatsby API based on actions.
+ require(`../redux/plugin-runner`)
+
const program = {
...args,
// Fix program directory path for windows env.
diff --git a/packages/gatsby/src/bootstrap/load-plugins/__tests__/__snapshots__/load-plugins.js.snap b/packages/gatsby/src/bootstrap/load-plugins/__tests__/__snapshots__/load-plugins.js.snap
index b3ce0d7cae856..3a9a00fb3947b 100644
--- a/packages/gatsby/src/bootstrap/load-plugins/__tests__/__snapshots__/load-plugins.js.snap
+++ b/packages/gatsby/src/bootstrap/load-plugins/__tests__/__snapshots__/load-plugins.js.snap
@@ -4,7 +4,7 @@ exports[`Load plugins Load plugins for a site 1`] = `
Array [
Object {
"browserAPIs": Array [],
- "id": "Plugin dev-404-page",
+ "id": "d48d1c52-fe48-53cb-8f08-aa4b47dde5a5",
"name": "dev-404-page",
"nodeAPIs": Array [
"createPagesStatefully",
@@ -18,7 +18,7 @@ Array [
},
Object {
"browserAPIs": Array [],
- "id": "Plugin load-babel-config",
+ "id": "1fc32581-893a-55e8-8927-bcd667e2b700",
"name": "load-babel-config",
"nodeAPIs": Array [
"onPreBootstrap",
@@ -32,7 +32,7 @@ Array [
},
Object {
"browserAPIs": Array [],
- "id": "Plugin internal-data-bridge",
+ "id": "a5079d69-ba80-53dc-82f9-0f440bd5448c",
"name": "internal-data-bridge",
"nodeAPIs": Array [
"sourceNodes",
@@ -47,7 +47,7 @@ Array [
},
Object {
"browserAPIs": Array [],
- "id": "Plugin prod-404",
+ "id": "f795702c-a3b8-5a88-88ee-5d06019d44fa",
"name": "prod-404",
"nodeAPIs": Array [
"onCreatePage",
@@ -61,7 +61,7 @@ Array [
},
Object {
"browserAPIs": Array [],
- "id": "Plugin query-runner",
+ "id": "84dad27f-1d44-51fc-ac56-4db2e5222995",
"name": "query-runner",
"nodeAPIs": Array [
"onCreatePage",
@@ -75,7 +75,7 @@ Array [
},
Object {
"browserAPIs": Array [],
- "id": "Plugin default-site-plugin",
+ "id": "7374ebf2-d961-52ee-92a2-c25e7cb387a9",
"name": "default-site-plugin",
"nodeAPIs": Array [],
"pluginOptions": Object {
@@ -87,7 +87,7 @@ Array [
},
Object {
"browserAPIs": Array [],
- "id": "Plugin gatsby-plugin-page-creator",
+ "id": "d5fb39bc-5b13-5925-86de-f0e18549d272",
"name": "gatsby-plugin-page-creator",
"nodeAPIs": Array [
"createPagesStatefully",
@@ -108,7 +108,7 @@ exports[`Load plugins Loads plugins defined with an object but without an option
Array [
Object {
"browserAPIs": Array [],
- "id": "Plugin dev-404-page",
+ "id": "d48d1c52-fe48-53cb-8f08-aa4b47dde5a5",
"name": "dev-404-page",
"nodeAPIs": Array [
"createPagesStatefully",
@@ -122,7 +122,7 @@ Array [
},
Object {
"browserAPIs": Array [],
- "id": "Plugin load-babel-config",
+ "id": "1fc32581-893a-55e8-8927-bcd667e2b700",
"name": "load-babel-config",
"nodeAPIs": Array [
"onPreBootstrap",
@@ -136,7 +136,7 @@ Array [
},
Object {
"browserAPIs": Array [],
- "id": "Plugin internal-data-bridge",
+ "id": "a5079d69-ba80-53dc-82f9-0f440bd5448c",
"name": "internal-data-bridge",
"nodeAPIs": Array [
"sourceNodes",
@@ -151,7 +151,7 @@ Array [
},
Object {
"browserAPIs": Array [],
- "id": "Plugin prod-404",
+ "id": "f795702c-a3b8-5a88-88ee-5d06019d44fa",
"name": "prod-404",
"nodeAPIs": Array [
"onCreatePage",
@@ -165,7 +165,7 @@ Array [
},
Object {
"browserAPIs": Array [],
- "id": "Plugin query-runner",
+ "id": "84dad27f-1d44-51fc-ac56-4db2e5222995",
"name": "query-runner",
"nodeAPIs": Array [
"onCreatePage",
@@ -190,7 +190,7 @@ Array [
},
Object {
"browserAPIs": Array [],
- "id": "Plugin default-site-plugin",
+ "id": "7374ebf2-d961-52ee-92a2-c25e7cb387a9",
"name": "default-site-plugin",
"nodeAPIs": Array [],
"pluginOptions": Object {
@@ -202,7 +202,7 @@ Array [
},
Object {
"browserAPIs": Array [],
- "id": "Plugin gatsby-plugin-page-creator",
+ "id": "d5fb39bc-5b13-5925-86de-f0e18549d272",
"name": "gatsby-plugin-page-creator",
"nodeAPIs": Array [
"createPagesStatefully",
diff --git a/packages/gatsby/src/bootstrap/load-plugins/load.js b/packages/gatsby/src/bootstrap/load-plugins/load.js
index 89e745e532c04..ef79cb5e00a4a 100644
--- a/packages/gatsby/src/bootstrap/load-plugins/load.js
+++ b/packages/gatsby/src/bootstrap/load-plugins/load.js
@@ -6,6 +6,7 @@ const crypto = require(`crypto`)
const glob = require(`glob`)
const { store } = require(`../../redux`)
const existsSync = require(`fs-exists-cached`).sync
+const createNodeId = require(`../../utils/create-node-id`)
function createFileContentHash(root, globPattern) {
const hash = crypto.createHash(`md5`)
@@ -48,7 +49,7 @@ function resolvePlugin(pluginName) {
return {
resolve: resolvedPath,
name: packageJSON.name || pluginName,
- id: `Plugin ${packageJSON.name || pluginName}`,
+ id: createNodeId(packageJSON.name, `Plugin`),
version:
packageJSON.version || createFileContentHash(resolvedPath, `**`),
}
@@ -72,7 +73,7 @@ function resolvePlugin(pluginName) {
return {
resolve: resolvedPath,
- id: `Plugin ${packageJSON.name}`,
+ id: createNodeId(packageJSON.name, `Plugin`),
name: packageJSON.name,
version: packageJSON.version,
}
@@ -126,6 +127,15 @@ module.exports = (config = {}) => {
return {
...info,
+ // Make sure key is unique to plugin options. E.g there could
+ // be multiple source-filesystem plugins, with different names
+ // (docs, blogs).
+ id: createNodeId(
+ plugin.options
+ ? plugin.name + JSON.stringify(plugin.options)
+ : plugin.name,
+ `Plugin`
+ ),
pluginOptions: _.merge({ plugins: [] }, plugin.options),
}
}
@@ -154,7 +164,7 @@ module.exports = (config = {}) => {
// Add the site's default "plugin" i.e. gatsby-x files in root of site.
plugins.push({
resolve: slash(process.cwd()),
- id: `Plugin default-site-plugin`,
+ id: createNodeId(`default-site-plugin`, `Plugin`),
name: `default-site-plugin`,
version: createFileContentHash(process.cwd(), `gatsby-*`),
pluginOptions: {
diff --git a/packages/gatsby/src/commands/repl.js b/packages/gatsby/src/commands/repl.js
index 00ce79e987e31..926f9af76d873 100644
--- a/packages/gatsby/src/commands/repl.js
+++ b/packages/gatsby/src/commands/repl.js
@@ -1,7 +1,13 @@
const repl = require(`repl`)
const { graphql } = require(`graphql`)
const bootstrap = require(`../bootstrap`)
-const { store, loadNodeContent, getNodes, getNode } = require(`../redux`)
+const {
+ loadNodeContent,
+ getNodes,
+ getNode,
+ getNodesByType,
+} = require(`../db/nodes`)
+const { store } = require(`../redux`)
module.exports = async program => {
// run bootstrap
@@ -16,9 +22,10 @@ module.exports = async program => {
pages,
components,
staticQueryComponents,
- nodes,
} = store.getState()
+ const nodes = getNodes()
+
const query = async query => {
const result = await graphql(schema, query, {}, {}, {})
console.log(`query result: ${JSON.stringify(result)}`)
@@ -35,6 +42,7 @@ module.exports = async program => {
_.context.dataPaths = jsonDataPaths
_.context.getNode = getNode
_.context.getNodes = getNodes
+ _.context.getNodesByType = getNodesByType
_.context.loadNodeContent = loadNodeContent
_.context.nodes = [...nodes.entries()]
_.context.pages = [...pages.entries()]
diff --git a/packages/gatsby/src/db/loki/nodes.js b/packages/gatsby/src/db/loki/nodes.js
new file mode 100644
index 0000000000000..efe043758165c
--- /dev/null
+++ b/packages/gatsby/src/db/loki/nodes.js
@@ -0,0 +1,12 @@
+function notSupported() {
+ throw new Error(`Loki not supported yet`)
+}
+
+module.exports = {
+ getNodes: notSupported(),
+ getNode: notSupported(),
+ getNodesByType: notSupported(),
+ hasNodeChanged: notSupported(),
+ loadNodeContent: notSupported(),
+ getNodeAndSavePathDependency: notSupported(),
+}
diff --git a/packages/gatsby/src/db/nodes.js b/packages/gatsby/src/db/nodes.js
new file mode 100644
index 0000000000000..ac4b8fbe394c4
--- /dev/null
+++ b/packages/gatsby/src/db/nodes.js
@@ -0,0 +1,16 @@
+const backend = process.env.GATSBY_DB_NODES || `redux`
+let nodesDb
+switch (backend) {
+ case `redux`:
+ nodesDb = require(`../redux/nodes`)
+ break
+ case `loki`:
+ nodesDb = require(`./loki/nodes`)
+ break
+ default:
+ throw new Error(
+ `Unsupported DB nodes backend (value of env var GATSBY_DB_NODES)`
+ )
+}
+
+module.exports = nodesDb
diff --git a/packages/gatsby/src/internal-plugins/internal-data-bridge/gatsby-node.js b/packages/gatsby/src/internal-plugins/internal-data-bridge/gatsby-node.js
index a5af127a384de..ce88d751b67b5 100644
--- a/packages/gatsby/src/internal-plugins/internal-data-bridge/gatsby-node.js
+++ b/packages/gatsby/src/internal-plugins/internal-data-bridge/gatsby-node.js
@@ -6,7 +6,7 @@ const _ = require(`lodash`)
const { emitter } = require(`../../redux`)
const { boundActionCreators } = require(`../../redux/actions`)
-const { getNode } = require(`../../redux`)
+const { getNode } = require(`../../db/nodes`)
function transformPackageJson(json) {
const transformDeps = deps =>
diff --git a/packages/gatsby/src/redux/__tests__/nodes.js b/packages/gatsby/src/redux/__tests__/nodes.js
index 3ce2ac9efbd74..95e380749d1ed 100644
--- a/packages/gatsby/src/redux/__tests__/nodes.js
+++ b/packages/gatsby/src/redux/__tests__/nodes.js
@@ -1,5 +1,6 @@
const { actions } = require(`../actions`)
-const { store, getNode } = require(`../index`)
+const { store } = require(`../index`)
+const { getNode } = require(`../nodes`)
const nodeReducer = require(`../reducers/nodes`)
const nodeTouchedReducer = require(`../reducers/nodes-touched`)
diff --git a/packages/gatsby/src/redux/actions.js b/packages/gatsby/src/redux/actions.js
index b54e66a61ffe6..bae7afc761f5e 100644
--- a/packages/gatsby/src/redux/actions.js
+++ b/packages/gatsby/src/redux/actions.js
@@ -9,7 +9,7 @@ const path = require(`path`)
const fs = require(`fs`)
const url = require(`url`)
const kebabHash = require(`kebab-hash`)
-const { hasNodeChanged, getNode } = require(`./index`)
+const { hasNodeChanged, getNode } = require(`../db/nodes`)
const { trackInlineObjectsInRootNode } = require(`../schema/node-tracking`)
const { store } = require(`./index`)
const fileExistsSync = require(`fs-exists-cached`).sync
@@ -1093,7 +1093,8 @@ actions.createRedirect = ({
// url.parse will not cover protocol-relative urls so do a separate check for those
const parsed = url.parse(toPath)
const isRelativeProtocol = toPath.startsWith(`//`)
- const toPathPrefix = parsed.protocol != null || isRelativeProtocol ? `` : pathPrefix
+ const toPathPrefix =
+ parsed.protocol != null || isRelativeProtocol ? `` : pathPrefix
return {
type: `CREATE_REDIRECT`,
diff --git a/packages/gatsby/src/redux/index.js b/packages/gatsby/src/redux/index.js
index 0198062671108..203b0438aac81 100644
--- a/packages/gatsby/src/redux/index.js
+++ b/packages/gatsby/src/redux/index.js
@@ -1,5 +1,4 @@
const Redux = require(`redux`)
-const Promise = require(`bluebird`)
const _ = require(`lodash`)
const fs = require(`fs`)
const mitt = require(`mitt`)
@@ -119,89 +118,3 @@ exports.emitter = emitter
/** Redux store */
exports.store = store
-
-/**
- * Get all nodes from redux store.
- *
- * @returns {Array}
- */
-exports.getNodes = () => {
- const nodes = store.getState().nodes
- if (nodes) {
- return Array.from(nodes.values())
- } else {
- return []
- }
-}
-const getNode = id => store.getState().nodes.get(id)
-
-/** Get node by id from store.
- *
- * @param {string} id
- * @returns {Object}
- */
-exports.getNode = getNode
-
-/**
- * Determine if node has changed.
- *
- * @param {string} id
- * @param {string} digest
- * @returns {boolean}
- */
-exports.hasNodeChanged = (id, digest) => {
- const node = store.getState().nodes.get(id)
- if (!node) {
- return true
- } else {
- return node.internal.contentDigest !== digest
- }
-}
-
-/**
- * Get content for a node from the plugin that created it.
- *
- * @param {Object} node
- * @returns {promise}
- */
-exports.loadNodeContent = node => {
- if (_.isString(node.internal.content)) {
- return Promise.resolve(node.internal.content)
- } else {
- return new Promise(resolve => {
- // Load plugin's loader function
- const plugin = store
- .getState()
- .flattenedPlugins.find(plug => plug.name === node.internal.owner)
- const { loadNodeContent } = require(plugin.resolve)
- if (!loadNodeContent) {
- throw new Error(
- `Could not find function loadNodeContent for plugin ${plugin.name}`
- )
- }
-
- return loadNodeContent(node).then(content => {
- // TODO update node's content field here.
- resolve(content)
- })
- })
- }
-}
-
-/**
- * Get node and save path dependency.
- *
- * @param {string} id
- * @param {string} path
- * @returns {Object} node
- */
-exports.getNodeAndSavePathDependency = (id, path) => {
- const { createPageDependency } = require(`./actions/add-page-dependency`)
- const node = getNode(id)
- createPageDependency({ path, nodeId: id })
- return node
-}
-
-// Start plugin runner which listens to the store
-// and invokes Gatsby API based on actions.
-require(`./plugin-runner`)
diff --git a/packages/gatsby/src/redux/nodes.js b/packages/gatsby/src/redux/nodes.js
new file mode 100644
index 0000000000000..ad182cb8d406d
--- /dev/null
+++ b/packages/gatsby/src/redux/nodes.js
@@ -0,0 +1,91 @@
+const _ = require(`lodash`)
+const Promise = require(`bluebird`)
+const { store } = require(`./index`)
+
+/**
+ * Get all nodes from redux store.
+ *
+ * @returns {Array}
+ */
+const getNodes = () => {
+ const nodes = store.getState().nodes
+ if (nodes) {
+ return Array.from(nodes.values())
+ } else {
+ return []
+ }
+}
+
+exports.getNodes = getNodes
+
+const getNode = id => store.getState().nodes.get(id)
+
+/** Get node by id from store.
+ *
+ * @param {string} id
+ * @returns {Object}
+ */
+exports.getNode = getNode
+
+exports.getNodesByType = type =>
+ getNodes().filter(node => node.internal.type === type)
+
+/**
+ * Determine if node has changed.
+ *
+ * @param {string} id
+ * @param {string} digest
+ * @returns {boolean}
+ */
+exports.hasNodeChanged = (id, digest) => {
+ const node = store.getState().nodes.get(id)
+ if (!node) {
+ return true
+ } else {
+ return node.internal.contentDigest !== digest
+ }
+}
+
+/**
+ * Get content for a node from the plugin that created it.
+ *
+ * @param {Object} node
+ * @returns {promise}
+ */
+exports.loadNodeContent = node => {
+ if (_.isString(node.internal.content)) {
+ return Promise.resolve(node.internal.content)
+ } else {
+ return new Promise(resolve => {
+ // Load plugin's loader function
+ const plugin = store
+ .getState()
+ .flattenedPlugins.find(plug => plug.name === node.internal.owner)
+ const { loadNodeContent } = require(plugin.resolve)
+ if (!loadNodeContent) {
+ throw new Error(
+ `Could not find function loadNodeContent for plugin ${plugin.name}`
+ )
+ }
+
+ return loadNodeContent(node).then(content => {
+ // TODO update node's content field here.
+ resolve(content)
+ })
+ })
+ }
+}
+
+/**
+ * Get node and save path dependency.
+ *
+ * @param {string} id
+ * @param {string} path
+ * @returns {Object} node
+ */
+exports.getNodeAndSavePathDependency = (id, path) => {
+ const { createPageDependency } = require(`./actions/add-page-dependency`)
+ const node = getNode(id)
+ createPageDependency({ path, nodeId: id })
+ return node
+}
diff --git a/packages/gatsby/src/redux/plugin-runner.js b/packages/gatsby/src/redux/plugin-runner.js
index a12a197a8995a..fb19f43cf3448 100644
--- a/packages/gatsby/src/redux/plugin-runner.js
+++ b/packages/gatsby/src/redux/plugin-runner.js
@@ -1,10 +1,11 @@
// Invoke plugins for certain actions.
-const { store, emitter } = require(`./index`)
+const { emitter } = require(`./index`)
+const { getNode } = require(`../db/nodes`)
const apiRunnerNode = require(`../utils/api-runner-node`)
emitter.on(`CREATE_NODE`, action => {
- const node = store.getState().nodes.get(action.payload.id)
+ const node = getNode(action.payload.id)
const traceTags = { nodeId: node.id, nodeType: node.internal.type }
apiRunnerNode(`onCreateNode`, {
node,
diff --git a/packages/gatsby/src/schema/__tests__/node-tracking-test.js b/packages/gatsby/src/schema/__tests__/node-tracking-test.js
index 9df62557ad2a6..480b7d622e9be 100644
--- a/packages/gatsby/src/schema/__tests__/node-tracking-test.js
+++ b/packages/gatsby/src/schema/__tests__/node-tracking-test.js
@@ -40,7 +40,7 @@ describe(`Track root nodes`, () => {
`
require(`fs`).__setMockFiles(MOCK_FILE_INFO)
- const { getNode, getNodes } = require(`../../redux`)
+ const { getNode, getNodes } = require(`../../db/nodes`)
const { findRootNodeAncestor } = require(`../node-tracking`)
const runSift = require(`../run-sift`)
const buildNodeTypes = require(`../build-node-types`)
diff --git a/packages/gatsby/src/schema/__tests__/run-sift.js b/packages/gatsby/src/schema/__tests__/run-sift.js
index 4e6050b64b32a..a253412718bb8 100644
--- a/packages/gatsby/src/schema/__tests__/run-sift.js
+++ b/packages/gatsby/src/schema/__tests__/run-sift.js
@@ -34,7 +34,7 @@ const mockNodes = [
},
]
-jest.mock(`../../redux`, () => {
+jest.mock(`../../db/nodes`, () => {
return {
getNode: id => mockNodes.find(node => node.id === id),
}
diff --git a/packages/gatsby/src/schema/build-node-connections.js b/packages/gatsby/src/schema/build-node-connections.js
index 0ec2825e2bd3f..8b90fa3d59bd8 100644
--- a/packages/gatsby/src/schema/build-node-connections.js
+++ b/packages/gatsby/src/schema/build-node-connections.js
@@ -10,7 +10,7 @@ const {
} = require(`./infer-graphql-input-fields-from-fields`)
const createSortField = require(`./create-sort-field`)
const buildConnectionFields = require(`./build-connection-fields`)
-const { getNodes } = require(`../redux`)
+const { getNodesByType } = require(`../db/nodes`)
module.exports = (types: any) => {
const connections = {}
@@ -68,10 +68,7 @@ module.exports = (types: any) => {
path = rootValue.path
}
const runSift = require(`./run-sift`)
- const latestNodes = _.filter(
- getNodes(),
- n => n.internal.type === type.name
- )
+ const latestNodes = getNodesByType(type.name)
return runSift({
args: resolveArgs,
nodes: latestNodes,
diff --git a/packages/gatsby/src/schema/build-node-types.js b/packages/gatsby/src/schema/build-node-types.js
index 7b2e8874b602b..eb92a6915cd67 100644
--- a/packages/gatsby/src/schema/build-node-types.js
+++ b/packages/gatsby/src/schema/build-node-types.js
@@ -17,7 +17,12 @@ const {
inferInputObjectStructureFromNodes,
} = require(`./infer-graphql-input-fields`)
const { nodeInterface } = require(`./node-interface`)
-const { getNodes, getNode, getNodeAndSavePathDependency } = require(`../redux`)
+const {
+ getNodes,
+ getNodesByType,
+ getNode,
+ getNodeAndSavePathDependency,
+} = require(`../db/nodes`)
const { createPageDependency } = require(`../redux/actions/add-page-dependency`)
const { setFileNodeRootType } = require(`./types/type-file`)
const { clearTypeExampleValues } = require(`./data-tree-utils`)
@@ -196,10 +201,7 @@ module.exports = async ({ parentSpan }) => {
) {
latestNodes = nodesCache.get(typeName)
} else {
- latestNodes = _.filter(
- getNodes(),
- n => n.internal.type === typeName
- )
+ latestNodes = getNodesByType(typeName)
nodesCache.set(typeName, latestNodes)
}
if (!_.isObject(args)) {
diff --git a/packages/gatsby/src/schema/infer-graphql-input-fields.js b/packages/gatsby/src/schema/infer-graphql-input-fields.js
index 1fc0184d40cea..a7c4c9fb89725 100644
--- a/packages/gatsby/src/schema/infer-graphql-input-fields.js
+++ b/packages/gatsby/src/schema/infer-graphql-input-fields.js
@@ -21,7 +21,7 @@ const {
} = require(`./data-tree-utils`)
const { findLinkedNode } = require(`./infer-graphql-type`)
-const { getNodes } = require(`../redux`)
+const { getNodesByType } = require(`../db/nodes`)
const is32BitInteger = require(`../utils/is-32-bit-integer`)
import type {
@@ -277,9 +277,7 @@ export function inferInputObjectStructureFromNodes({
if (linkedNodeCache[linkedNode.internal.type]) {
value = linkedNodeCache[linkedNode.internal.type]
} else {
- const relatedNodes = getNodes().filter(
- node => node.internal.type === linkedNode.internal.type
- )
+ const relatedNodes = getNodesByType(linkedNode.internal.type)
value = getExampleValues({
nodes: relatedNodes,
typeName: linkedNode.internal.type,
diff --git a/packages/gatsby/src/schema/infer-graphql-type.js b/packages/gatsby/src/schema/infer-graphql-type.js
index 87e30304c66c9..955df13c4db26 100644
--- a/packages/gatsby/src/schema/infer-graphql-type.js
+++ b/packages/gatsby/src/schema/infer-graphql-type.js
@@ -12,7 +12,8 @@ const _ = require(`lodash`)
const invariant = require(`invariant`)
const { oneLine } = require(`common-tags`)
-const { store, getNode, getNodes } = require(`../redux`)
+const { store } = require(`../redux`)
+const { getNode, getNodes, getNodesByType } = require(`../db/nodes`)
const { createPageDependency } = require(`../redux/actions/add-page-dependency`)
const createTypeName = require(`./create-type-name`)
const createKey = require(`./create-key`)
@@ -154,9 +155,8 @@ function inferFromMapping(
const findNode = (fieldValue, path) => {
const linkedNode = _.find(
- getNodes(),
- n =>
- n.internal.type === linkedType && _.get(n, linkedField) === fieldValue
+ getNodesByType(linkedType),
+ n => _.get(n, linkedField) === fieldValue
)
if (linkedNode) {
createPageDependency({ path, nodeId: linkedNode.id })
@@ -257,7 +257,10 @@ function inferFromFieldName(value, selector, types): GraphQLFieldConfig<*, *> {
let type
// If there's more than one type, we'll create a union type.
if (fields.length > 1) {
- const typeName = `Union_${key}_${fields.map(f => f.name).sort().join(`__`)}`
+ const typeName = `Union_${key}_${fields
+ .map(f => f.name)
+ .sort()
+ .join(`__`)}`
if (unionTypes.has(typeName)) {
type = unionTypes.get(typeName)
diff --git a/packages/gatsby/src/schema/node-tracking.js b/packages/gatsby/src/schema/node-tracking.js
index 495e720d44bab..8d9905cbbfe5c 100644
--- a/packages/gatsby/src/schema/node-tracking.js
+++ b/packages/gatsby/src/schema/node-tracking.js
@@ -1,5 +1,5 @@
const _ = require(`lodash`)
-const { getNode, getNodes } = require(`../redux`)
+const { getNode, getNodes } = require(`../db/nodes`)
/**
* Map containing links between inline objects or arrays
diff --git a/packages/gatsby/src/schema/run-sift.js b/packages/gatsby/src/schema/run-sift.js
index 76de76e85b73e..2206751b34041 100644
--- a/packages/gatsby/src/schema/run-sift.js
+++ b/packages/gatsby/src/schema/run-sift.js
@@ -6,7 +6,7 @@ const { createPageDependency } = require(`../redux/actions/add-page-dependency`)
const prepareRegex = require(`./prepare-regex`)
const Promise = require(`bluebird`)
const { trackInlineObjectsInRootNode } = require(`./node-tracking`)
-const { getNode } = require(`../redux`)
+const { getNode } = require(`../db/nodes`)
const resolvedNodesCache = new Map()
const enhancedNodeCache = new Map()
diff --git a/packages/gatsby/src/schema/types/type-file.js b/packages/gatsby/src/schema/types/type-file.js
index 301db11b6fce5..fa40ac1abadfa 100644
--- a/packages/gatsby/src/schema/types/type-file.js
+++ b/packages/gatsby/src/schema/types/type-file.js
@@ -6,7 +6,7 @@ const isRelativeUrl = require(`is-relative-url`)
const normalize = require(`normalize-path`)
const systemPath = require(`path`)
-const { getNodes } = require(`../../redux`)
+const { getNodesByType } = require(`../../db/nodes`)
const { findRootNodeAncestor } = require(`../node-tracking`)
const {
createPageDependency,
@@ -108,7 +108,7 @@ function pointsToFile(nodes, key, value) {
}
const pathToOtherNode = normalize(joinPath(rootNode.dir, value))
- const otherFileExists = getNodes().some(
+ const otherFileExists = getNodesByType(`File`).some(
n => n.absolutePath === pathToOtherNode
)
return otherFileExists
@@ -148,8 +148,8 @@ function createType(fileNodeRootType, isArray) {
// Use that path to find the linked File node.
const linkedFileNode = _.find(
- getNodes(),
- n => n.internal.type === `File` && n.absolutePath === fileLinkPath
+ getNodesByType(`File`),
+ n => n.absolutePath === fileLinkPath
)
if (linkedFileNode) {
createPageDependency({
diff --git a/packages/gatsby/src/utils/api-runner-node.js b/packages/gatsby/src/utils/api-runner-node.js
index 906b3393d1025..bfc2fa7574e4e 100644
--- a/packages/gatsby/src/utils/api-runner-node.js
+++ b/packages/gatsby/src/utils/api-runner-node.js
@@ -68,15 +68,15 @@ const runAPI = (plugin, api, args) => {
pluginSpan.setTag(`plugin`, plugin.name)
let pathPrefix = ``
+ const { store, emitter } = require(`../redux`)
const {
- store,
- emitter,
loadNodeContent,
getNodes,
getNode,
+ getNodesByType,
hasNodeChanged,
getNodeAndSavePathDependency,
- } = require(`../redux`)
+ } = require(`../db/nodes`)
const { boundActionCreators } = require(`../redux/actions`)
const doubleBoundActionCreators = doubleBind(
@@ -111,6 +111,7 @@ const runAPI = (plugin, api, args) => {
emitter,
getNodes,
getNode,
+ getNodesByType,
hasNodeChanged,
reporter,
getNodeAndSavePathDependency,
diff --git a/packages/gatsby/src/utils/source-nodes.js b/packages/gatsby/src/utils/source-nodes.js
index a90fb7e132fb9..ec544feba284b 100644
--- a/packages/gatsby/src/utils/source-nodes.js
+++ b/packages/gatsby/src/utils/source-nodes.js
@@ -2,7 +2,8 @@ const _ = require(`lodash`)
const report = require(`gatsby-cli/lib/reporter`)
const apiRunner = require(`./api-runner-node`)
-const { store, getNode } = require(`../redux`)
+const { store } = require(`../redux`)
+const { getNode, getNodes } = require(`../db/nodes`)
const { boundActionCreators } = require(`../redux/actions`)
const { deleteNode } = boundActionCreators
@@ -18,7 +19,7 @@ function discoverPluginsWithoutNodes(storeState) {
)
// Find out which plugins own already created nodes
const nodeOwners = _.uniq(
- Array.from(storeState.nodes.values()).reduce((acc, node) => {
+ Array.from(getNodes()).reduce((acc, node) => {
acc.push(node.internal.owner)
return acc
}, [])
@@ -45,7 +46,7 @@ module.exports = async ({ parentSpan } = {}) => {
// Garbage collect stale data nodes
const touchedNodes = Object.keys(state.nodesTouched)
- const staleNodes = Array.from(state.nodes.values()).filter(node => {
+ const staleNodes = Array.from(getNodes()).filter(node => {
// Find the root node.
let rootNode = node
let whileCount = 0