@ehp/gatsby-source-drupal
Version:
Gatsby source plugin for building websites using the Drupal CMS as a data source
247 lines (198 loc) • 6.84 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
const axios = require(`axios`);
const axiosRetry = require(`axios-retry`);
const crypto = require(`crypto`);
const _ = require(`lodash`);
const _require = require(`gatsby-source-filesystem`),
createRemoteFileNode = _require.createRemoteFileNode;
const _require2 = require(`url`),
URL = _require2.URL;
const _require3 = require(`./normalize`),
nodeFromData = _require3.nodeFromData,
normalizeTypeName = _require3.normalizeTypeName;
axiosRetry(axios, {
retries: 999,
retryDelay: retryCount => {
return retryCount * 1000;
}
}); // Get content digest of node.
const createContentDigest = obj => crypto.createHash(`md5`).update(JSON.stringify(obj)).digest(`hex`);
exports.sourceNodes =
/*#__PURE__*/
function () {
var _ref = (0, _asyncToGenerator2.default)(function* ({
actions,
getNode,
hasNodeChanged,
store,
cache,
createNodeId
}, {
baseUrl,
apiBase
}) {
const createNode = actions.createNode; // Default apiBase to `jsonapi`
apiBase = apiBase || `jsonapi`; // Touch existing Drupal nodes so Gatsby doesn't garbage collect them.
// _.values(store.getState().nodes)
// .filter(n => n.internal.type.slice(0, 8) === `drupal__`)
// .forEach(n => touchNode({ nodeId: n.id }))
// Fetch articles.
// console.time(`fetch Drupal data`)
console.log(`Starting to fetch data from Drupal`); // TODO restore this
// let lastFetched
// if (
// store.getState().status.plugins &&
// store.getState().status.plugins[`gatsby-source-drupal`]
// ) {
// lastFetched = store.getState().status.plugins[`gatsby-source-drupal`].status
// .lastFetched
// }
const data = yield axios.get(`${baseUrl}/${apiBase}`);
const allData = yield Promise.all(_.map(data.data.links,
/*#__PURE__*/
function () {
var _ref2 = (0, _asyncToGenerator2.default)(function* (url, type) {
if (type === `self`) return;
if (!url) return;
if (!type) return;
const getNext =
/*#__PURE__*/
function () {
var _ref3 = (0, _asyncToGenerator2.default)(function* (url, data = []) {
const d = yield axios.get(url);
data = data.concat(d.data.data);
if (d.data.links.next) {
data = yield getNext(d.data.links.next, data);
}
return data;
});
return function getNext(_x5) {
return _ref3.apply(this, arguments);
};
}();
const data = yield getNext(url);
const result = {
type,
data // eslint-disable-next-line consistent-return
};
return result;
});
return function (_x3, _x4) {
return _ref2.apply(this, arguments);
};
}())); // Make list of all IDs so we can check against that when creating
// relationships.
const ids = {};
_.each(allData, contentType => {
if (!contentType) return;
_.each(contentType.data, datum => {
ids[datum.id] = true;
});
}); // Create back references
var backRefs = {};
const addBackRef = function addBackRef(sourceId, linkedId, relationshipName, type) {
if (ids[linkedId]) {
if (typeof backRefs[linkedId] === `undefined`) {
backRefs[linkedId] = [];
}
backRefs[linkedId].push({
id: sourceId,
type: normalizeTypeName(`backref_${relationshipName}`)
});
backRefs[linkedId].push({
id: sourceId,
type: normalizeTypeName(`backref_${relationshipName}_${type}`)
});
}
};
_.each(allData, function (contentType) {
if (!contentType) return;
_.each(contentType.data, function (datum) {
if (datum.relationships) {
_.each(datum.relationships, function (v, k) {
if (!v.data) {
return;
}
if (_.isArray(v.data)) {
v.data.forEach(function (data) {
addBackRef(datum.id, data.id, k, contentType.type);
});
} else {
addBackRef(datum.id, v.data.id, k, contentType.type);
}
});
}
});
}); // Process nodes
const nodes = [];
_.each(allData, contentType => {
if (!contentType) return;
_.each(contentType.data, datum => {
const node = nodeFromData(datum); // Add relationships
if (datum.relationships) {
var addedRelationships = false;
node.relationships = {};
_.each(datum.relationships, (v, k) => {
if (!v.data) return;
if (_.isArray(v.data) && v.data.length > 0) {
node.relationships[`${normalizeTypeName(k)}___NODE`] = v.data.map(function (data) {
return data.id;
});
addedRelationships = true;
} else if (ids[v.data.id]) {
node.relationships[`${normalizeTypeName(k)}___NODE`] = v.data.id;
addedRelationships = true;
}
});
if (backRefs[datum.id]) {
backRefs[datum.id].forEach(function (ref) {
if (!node.relationships[`${ref.type}___NODE`]) {
node.relationships[`${ref.type}___NODE`] = [];
}
node.relationships[`${ref.type}___NODE`].push(ref.id);
addedRelationships = true;
});
}
if (!addedRelationships) {
delete node.relationships;
}
}
node.internal.contentDigest = createContentDigest(node);
nodes.push(node);
});
}); // Download all files.
yield Promise.all(nodes.map(
/*#__PURE__*/
function () {
var _ref4 = (0, _asyncToGenerator2.default)(function* (node) {
let fileNode;
if (node.internal.type === `files` || node.internal.type === `file__file`) {
try {
// Resolve w/ baseUrl if node.uri isn't absolute.
const url = new URL(node.url, baseUrl);
fileNode = yield createRemoteFileNode({
url: url.href,
store,
cache,
createNode,
createNodeId
});
} catch (e) {// Ignore
}
if (fileNode) {
node.localFile___NODE = fileNode.id;
}
}
});
return function (_x6) {
return _ref4.apply(this, arguments);
};
}()));
nodes.forEach(n => createNode(n));
});
return function (_x, _x2) {
return _ref.apply(this, arguments);
};
}();
;