Skip to content
This repository has been archived by the owner on Dec 27, 2022. It is now read-only.

Commit

Permalink
Merge pull request #106 from strapi/gatsby-cloud-compatibility
Browse files Browse the repository at this point in the history
Add Gatsby cloud compatibility
  • Loading branch information
alexandrebodin authored Mar 13, 2020
2 parents eada801 + a6ac83b commit b50a965
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 130 deletions.
9 changes: 5 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
*.log
/yarn.lock
node_modules
.idea
/authentication.js
/fetch.js
/normalize.js
/gatsby-node.js
/nodes.js
/normalize.js
/yarn.lock
node_modules
.idea
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 34 additions & 0 deletions src/authentication.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import axios from 'axios'

module.exports = async ({ loginData, reporter, apiURL }) => {
let jwtToken = null

// Check if loginData is set.
if (
loginData.hasOwnProperty('identifier') &&
loginData.identifier.length !== 0 &&
loginData.hasOwnProperty('password') &&
loginData.password.length !== 0
) {
const authenticationActivity = reporter.activityTimer(
`Authenticate Strapi User`
)
authenticationActivity.start()

// Define API endpoint.
const loginEndpoint = `${apiURL}/auth/local`

// Make API request.
try {
const loginResponse = await axios.post(loginEndpoint, loginData)

if (loginResponse.hasOwnProperty('data')) {
jwtToken = loginResponse.data.jwt
}
} catch (e) {
reporter.panic('Strapi authentication error: ' + e)
}
authenticationActivity.end()
}
return jwtToken
}
68 changes: 36 additions & 32 deletions src/gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,23 @@ import fetchData from './fetch'
import { Node } from './nodes'
import { capitalize } from 'lodash'
import normalize from './normalize'
import authentication from './authentication'

exports.sourceNodes = async (
{ store, boundActionCreators, cache, reporter },
{ store, actions, cache, reporter, getNode, getNodes },
{
apiURL = 'http://localhost:1337',
contentTypes = [],
loginData = {},
queryLimit = 100,
}
) => {
const { createNode, touchNode } = boundActionCreators
let jwtToken = null
const { createNode, deleteNode, touchNode } = actions

// Check if loginData is set.
if (
loginData.hasOwnProperty('identifier') &&
loginData.identifier.length !== 0 &&
loginData.hasOwnProperty('password') &&
loginData.password.length !== 0
) {
const authenticationActivity = reporter.activityTimer(
`Authenticate Strapi User`
)
authenticationActivity.start()

// Define API endpoint.
const loginEndpoint = `${apiURL}/auth/local`

// Make API request.
try {
const loginResponse = await axios.post(loginEndpoint, loginData)

if (loginResponse.hasOwnProperty('data')) {
jwtToken = loginResponse.data.jwt
}
} catch (e) {
reporter.panic('Strapi authentication error: ' + e)
}

authenticationActivity.end()
}
// Authentication function
let jwtToken = await authentication({ loginData, reporter, apiURL })

// Start activity, Strapi data fetching
const fetchActivity = reporter.activityTimer(`Fetched Strapi Data`)
fetchActivity.start()

Expand All @@ -59,9 +34,10 @@ exports.sourceNodes = async (
})
)

// Execute the promises.
// Execute the promises
let entities = await Promise.all(promises)

// Creating files
entities = await normalize.downloadMediaFiles({
entities,
apiURL,
Expand All @@ -72,13 +48,41 @@ exports.sourceNodes = async (
jwtToken,
})

// new created nodes
let newNodes = []

// Fetch existing strapi nodes
const existingNodes = getNodes().filter(
n => n.internal.owner === `gatsby-source-strapi`
)

// Touch each one of them
existingNodes.forEach(n => {
touchNode({ nodeId: n.id })
})

// Create/update nodes
contentTypes.forEach((contentType, i) => {
const items = entities[i]
items.forEach((item, i) => {
const node = Node(capitalize(contentType), item)
// Adding new created nodes in an Array
newNodes.push(node)

// Create nodes
createNode(node)
})
})

// Make a diff array between existing nodes and new ones
const diff = existingNodes.filter(
({ id: id1 }) => !newNodes.some(({ id: id2 }) => id2 === id1)
)

// Delete diff nodes
diff.forEach(data => {
deleteNode({ node: getNode(data.id) })
})

fetchActivity.end()
}
8 changes: 0 additions & 8 deletions src/nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,6 @@ const { createNodeFactory } = createNodeHelpers({
typePrefix: 'Strapi',
})

/**
* Node factory with `type` option based on
* original `createNodeFactory`.
*
* @param {string} type - Node type
* @param {object} node - Node
* @constructor
*/
export const Node = (type, node) =>
createNodeFactory(type, node => {
node.id = `${type}_${node.strapiId}`
Expand Down
137 changes: 52 additions & 85 deletions src/normalize.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,97 +5,66 @@ const extractFields = async (
store,
cache,
createNode,
createNodeId,
touchNode,
auth,
item,
key = 'localFile'
item
) => {
// image fields have a mime property among other
// maybe should find a better test
if (item && item.hasOwnProperty('mime')) {
let fileNodeID
// using field on the cache key for multiple image field
const mediaDataCacheKey = `strapi-media-${item.id}-${key}`
const cacheMediaData = await cache.get(mediaDataCacheKey)

// If we have cached media data and it wasn't modified, reuse
// previously created file node to not try to redownload
if (cacheMediaData && item.updatedAt === cacheMediaData.updatedAt) {
fileNodeID = cacheMediaData.fileNodeID
touchNode({ nodeId: cacheMediaData.fileNodeID })
}

// If we don't have cached data, download the file
if (!fileNodeID) {
try {
// full media url
const source_url = `${item.url.startsWith('http') ? '' : apiURL}${
item.url
}`
const fileNode = await createRemoteFileNode({
url: source_url,
store,
cache,
createNode,
createNodeId,
auth,
})

// If we don't have cached data, download the file
if (fileNode) {
fileNodeID = fileNode.id
for (const key of Object.keys(item)) {
const field = item[key]
if (Array.isArray(field)) {
// add recursion to fetch nested strapi references
await Promise.all(
field.map(async f =>
extractFields(apiURL, store, cache, createNode, touchNode, auth, f)
)
)
} else {
// image fields have a mime property among other
// maybe should find a better test
if (field !== null && field.hasOwnProperty('mime')) {
let fileNodeID
// using field on the cache key for multiple image field
const mediaDataCacheKey = `strapi-media-${item.id}-${key}`
const cacheMediaData = await cache.get(mediaDataCacheKey)

await cache.set(mediaDataCacheKey, {
fileNodeID,
updatedAt: item.updatedAt,
})
// If we have cached media data and it wasn't modified, reuse
// previously created file node to not try to redownload
if (cacheMediaData && field.updated_at === cacheMediaData.updated_at) {
fileNodeID = cacheMediaData.fileNodeID
touchNode({ nodeId: cacheMediaData.fileNodeID })
}
} catch (e) {
// Ignore
}
}

if (fileNodeID) {
if (key !== 'localFile') {
return fileNodeID
}

item.localFile___NODE = fileNodeID
}
} else if (Array.isArray(item)) {
await Promise.all(
item.map(async f =>
extractFields(
apiURL,
store,
cache,
createNode,
createNodeId,
touchNode,
auth,
f
)
)
)
} else if (item && typeof item === 'object') {
for (const key of Object.keys(item)) {
const field = item[key]
// If we don't have cached data, download the file
if (!fileNodeID) {
try {
// full media url
const source_url = `${field.url.startsWith('http') ? '' : apiURL}${
field.url
}`
const fileNode = await createRemoteFileNode({
url: source_url,
store,
cache,
createNode,
auth,
})

const fileNodeID = await extractFields(
apiURL,
store,
cache,
createNode,
createNodeId,
touchNode,
auth,
field,
key
)
// If we don't have cached data, download the file
if (fileNode) {
fileNodeID = fileNode.id

if (fileNodeID) {
item[`${key}___NODE`] = fileNodeID
await cache.set(mediaDataCacheKey, {
fileNodeID,
updated_at: field.updated_at,
})
}
} catch (e) {
// Ignore
}
}
if (fileNodeID) {
item[`${key}___NODE`] = fileNodeID
}
}
}
}
Expand All @@ -108,7 +77,6 @@ exports.downloadMediaFiles = async ({
store,
cache,
createNode,
createNodeId,
touchNode,
jwtToken: auth,
}) =>
Expand All @@ -121,7 +89,6 @@ exports.downloadMediaFiles = async ({
store,
cache,
createNode,
createNodeId,
touchNode,
auth,
item
Expand Down

0 comments on commit b50a965

Please sign in to comment.