Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 8c67fc1
Showing
8 changed files
with
328 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"sourceMaps": true, | ||
"presets": [ | ||
[ | ||
"env", | ||
{ | ||
"targets": { | ||
"node": 4.0, | ||
"uglify": true, | ||
} | ||
} | ||
] | ||
], | ||
"plugins": [ | ||
"transform-runtime", | ||
"transform-object-rest-spread", | ||
"transform-async-to-generator" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/gatsby-node.js | ||
/normalize.js | ||
/nodes.js | ||
/fetch.js | ||
/yarn.lock | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Logs | ||
logs | ||
*.log | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (http://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directory | ||
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git | ||
node_modules | ||
*.un~ | ||
yarn.lock | ||
src | ||
flow-typed | ||
coverage | ||
decls | ||
examples |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
// no-op |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"name": "gatsby-source-prismic", | ||
"version": "0.1.0", | ||
"description": "Gatsby source plugin for building websites using prismic.io as a data source", | ||
"scripts": { | ||
"build": "babel src --out-dir .", | ||
"watch": "babel -w src --out-dir ." | ||
}, | ||
"keywords": [ | ||
"gatsby", | ||
"gatsby-plugin", | ||
"gatsby-source-plugin" | ||
], | ||
"author": "Angelo Ashmore <angelo.ashmore@walltowall.com>", | ||
"license": "MIT", | ||
"dependencies": { | ||
"crypto": "^0.0.3", | ||
"json-stringify-safe": "^5.0.1", | ||
"lodash": "^4.17.4", | ||
"prismic-javascript": "^1.1.5" | ||
}, | ||
"devDependencies": { | ||
"babel-cli": "^6.24.1", | ||
"babel-plugin-transform-async-to-generator": "^6.24.1", | ||
"babel-plugin-transform-object-rest-spread": "^6.23.0", | ||
"babel-plugin-transform-runtime": "^6.23.0", | ||
"babel-preset-env": "^1.6.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import Prismic from 'prismic-javascript' | ||
|
||
module.exports = async ({ repositoryName, accessToken }) => { | ||
console.time(`Fetch Prismic data`) | ||
console.log(`Starting to fetch data from Prismic`) | ||
|
||
const apiEndpoint = `https://${repositoryName}.prismic.io/api/v2` | ||
const client = await Prismic.getApi(apiEndpoint) | ||
|
||
// Query all documents from client | ||
const documents = await pagedGet(client) | ||
|
||
console.timeEnd(`Fetch Prismic data`) | ||
|
||
return { | ||
documents | ||
} | ||
} | ||
|
||
async function pagedGet( | ||
client, | ||
query = [], | ||
options = {}, | ||
page = 1, | ||
pageSize = 100, | ||
aggregatedResponse = null | ||
) { | ||
const mergedOptions = Object.assign({ | ||
lang: '*' | ||
}, options) | ||
|
||
const response = await client.query(query, { | ||
...mergedOptions, | ||
page, | ||
pageSize | ||
}) | ||
|
||
if (!aggregatedResponse) { | ||
aggregatedResponse = response.results | ||
} else { | ||
aggregatedResponse = aggregatedResponse.concat( | ||
response.results | ||
) | ||
} | ||
|
||
if (page * pageSize < response.total_results_size) { | ||
return pagedGet(client, query, options, page + 1, aggregatedResponse) | ||
} | ||
|
||
return aggregatedResponse | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { uniq } from 'lodash' | ||
import { createHash } from 'crypto' | ||
import stringify from 'json-stringify-safe' | ||
import fetchData from './fetch' | ||
import { | ||
TypeNode, | ||
DocumentNode, | ||
DatumNode | ||
} from './nodes' | ||
|
||
const digest = str => createHash(`md5`).update(str).digest(`hex`) | ||
|
||
exports.sourceNodes = async ( | ||
{ boundActionCreators, getNodes, hasNodeChanged, store }, | ||
{ repositoryName, accessToken } | ||
) => { | ||
const { | ||
createNode, | ||
deleteNodes, | ||
touchNode, | ||
setPluginStatus, | ||
} = boundActionCreators | ||
|
||
const { | ||
documents | ||
} = await fetchData({ | ||
repositoryName, | ||
accessToken | ||
}) | ||
|
||
// Get list of custom types | ||
const customTypeNames = uniq(documents.map( | ||
doc => doc.type | ||
)) | ||
|
||
// Custom types do not have IDs, so generate a reproducable one based on the | ||
// name. The MD5 hash of the name is used here. | ||
const customTypeItems = customTypeNames.map( | ||
customTypeName => ({ | ||
id: digest(customTypeName), | ||
name: customTypeName | ||
}) | ||
) | ||
|
||
// Level 1: CustomType nodes | ||
customTypeItems.forEach(customTypeItem => { | ||
const customTypeNode = TypeNode({ | ||
customTypeItem | ||
}) | ||
|
||
const customTypeDocuments = documents.filter( | ||
doc => doc.type === customTypeItem.name | ||
) | ||
|
||
// Level 2: CustomTypeDocument nodes | ||
customTypeDocuments.forEach(customTypeDocumentItem => { | ||
const customTypeDocumentNode = DocumentNode({ | ||
customTypeItem, | ||
customTypeDocumentItem | ||
}) | ||
|
||
const customTypeDocumentData = customTypeDocumentItem.data | ||
|
||
// Remove slice data | ||
// TODO: Add this functionality | ||
delete customTypeDocumentData.body | ||
|
||
// Level 3: CustomTypeDocumentDatum nodes | ||
Object.keys(customTypeDocumentData).forEach(customTypeDocumentDatumKey => { | ||
const customTypeDocumentDatumItem = customTypeDocumentData[customTypeDocumentDatumKey] | ||
|
||
// Data do not have IDs, so generate a reproducable one based on the | ||
// content. The MD5 hash of the content is used here. | ||
customTypeDocumentDatumItem.id = digest(stringify(customTypeDocumentDatumItem)) | ||
|
||
const customTypeDocumentDatumNode = DatumNode({ | ||
customTypeDocumentItem, | ||
customTypeDocumentDatumItem | ||
}) | ||
|
||
createNode(customTypeDocumentDatumNode) | ||
customTypeDocumentNode.children = customTypeDocumentNode.children.concat([customTypeDocumentDatumNode.id]) | ||
}) | ||
|
||
createNode(customTypeDocumentNode) | ||
customTypeNode.children = customTypeNode.children.concat([customTypeDocumentNode.id]) | ||
}) | ||
|
||
createNode(customTypeNode) | ||
}) | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import { camelCase, upperFirst } from 'lodash' | ||
import { createHash } from 'crypto' | ||
import stringify from 'json-stringify-safe' | ||
|
||
const sourceId = `__SOURCE__` | ||
const typePrefix = `Prismic` | ||
const conflictFieldPrefix = `prismic` | ||
const prismicMediaType = `application/x-prismic-v2` | ||
const restrictedNodeFields = [`id`, `children`, `parent`, `fields`, `internal`] | ||
|
||
const makeTypeName = type => upperFirst(camelCase(`${typePrefix} ${type}`)) | ||
const digest = str => createHash(`md5`).update(str).digest(`hex`) | ||
|
||
// TypeNode | ||
// | ||
// Each custom type is a TypeNode. Documents using the custom type are child | ||
// nodes. | ||
export const TypeNode = ({ | ||
customTypeItem | ||
}) => { | ||
const node = { | ||
id: customTypeItem.id, | ||
parent: sourceId, | ||
children: [], | ||
name: customTypeItem.name, | ||
internal: { | ||
type: makeTypeName(`${upperFirst(customTypeItem.name)}Type`) | ||
} | ||
} | ||
|
||
node.internal.contentDigest = digest(stringify(node)) | ||
|
||
return node | ||
} | ||
|
||
// DocumentNode | ||
// | ||
// Each document is a DocumentNode. Non-content fields (e.g. lang, | ||
// first_puglication_date, slugs) are added as fields on the node. Content | ||
// fields are to be processed into child nodes. | ||
export const DocumentNode = ({ | ||
customTypeItem, | ||
customTypeDocumentItem: customTypeDocumentItemOrig | ||
}) => { | ||
const customTypeDocumentItem = Object.assign({}, customTypeDocumentItemOrig) | ||
|
||
// Prefix conflicting keys. | ||
Object.keys(customTypeDocumentItem).forEach(key => { | ||
if (restrictedNodeFields.includes(key)) { | ||
customTypeDocumentItem[`${conflictFieldPrefix}${upperFirst(key)}`] = customTypeDocumentItem[key] | ||
delete customTypeDocumentItem[key] | ||
} | ||
}) | ||
|
||
// Need to use prismicId since the original id key conflicts with Gatsby. | ||
const node = { | ||
id: customTypeDocumentItem.prismicId, | ||
parent: customTypeItem.id, | ||
children: [], | ||
internal: { | ||
type: makeTypeName(`Document`) | ||
}, | ||
...customTypeDocumentItem | ||
} | ||
|
||
node.internal.contentDigest = digest(stringify(node)) | ||
|
||
return node | ||
} | ||
|
||
// DatumNode | ||
// | ||
// Each document data item is a DatumNode. Prismic's custom JSON content format | ||
// is stringified as the node's content. This will later be parsed again by a | ||
// transformer. | ||
export const DatumNode = ({ | ||
customTypeDocumentItem, | ||
customTypeDocumentDatumItem | ||
}) => { | ||
const str = stringify(customTypeDocumentDatumItem) | ||
|
||
const node = { | ||
id: customTypeDocumentDatumItem.id, | ||
parent: customTypeDocumentItem.id, | ||
children: [], | ||
internal: { | ||
mediaType: 'application/x-prismic-v2', | ||
type: makeTypeName(`Datum`), | ||
content: str, | ||
contentDigest: digest(str) | ||
} | ||
} | ||
|
||
return node | ||
} |