gatsby-source-sanity
Version:
Gatsby source plugin for building websites using Sanity.io as a backend.
176 lines • 7.74 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const split = require("split2");
const through = require("through2");
const fs_extra_1 = require("fs-extra");
const lodash_1 = require("lodash");
const operators_1 = require("rxjs/operators");
const graphql_1 = require("gatsby/graphql");
const SanityClient = require("@sanity/client");
const pump_1 = require("./util/pump");
const rejectOnApiError_1 = require("./util/rejectOnApiError");
const normalize_1 = require("./util/normalize");
const getDocumentStream_1 = require("./util/getDocumentStream");
const cache_1 = require("./util/cache");
const removeSystemDocuments_1 = require("./util/removeSystemDocuments");
const handleDrafts_1 = require("./util/handleDrafts");
const handleListenerEvent_1 = require("./util/handleListenerEvent");
const createTemporaryMockNodes_1 = require("./util/createTemporaryMockNodes");
const remoteGraphQLSchema_1 = require("./util/remoteGraphQLSchema");
const debug_1 = require("./debug");
const extendImageNode_1 = require("./images/extendImageNode");
const defaultConfig = {
version: '1',
overlayDrafts: false,
graphqlApi: 'default'
};
const stateCache = {};
exports.onPreBootstrap = async (context, pluginConfig) => {
const config = Object.assign({}, defaultConfig, pluginConfig);
const { reporter } = context;
validateConfig(config, reporter);
try {
reporter.info('[sanity] Fetching remote GraphQL schema');
const client = getClient(config);
const api = await remoteGraphQLSchema_1.getRemoteGraphQLSchema(client, config);
reporter.info('[sanity] Stitching GraphQL schemas from SDL');
const typeMap = remoteGraphQLSchema_1.getTypeMapFromGraphQLSchema(api, pluginConfig);
if (Object.keys(typeMap.exampleValues).length === 0) {
reporter.error('[sanity] Failed to create example values, fields might be missing!');
reporter.error('[sanity] Run the build again with DEBUG=sanity to debug issues.');
}
const typeMapKey = cache_1.getCacheKey(pluginConfig, cache_1.CACHE_KEYS.TYPE_MAP);
stateCache[typeMapKey] = typeMap;
}
catch (err) {
if (err.isWarning) {
err.message.split('\n').forEach((line) => reporter.warn(line));
}
else {
reporter.panic(err.stack);
}
}
};
exports.sourceNodes = async (context, pluginConfig) => {
const config = Object.assign({}, defaultConfig, pluginConfig);
const { dataset, overlayDrafts, watchMode } = config;
const { actions, getNode, createNodeId, createContentDigest, reporter } = context;
const { createNode, createParentChildLink } = actions;
const typeMapKey = cache_1.getCacheKey(pluginConfig, cache_1.CACHE_KEYS.TYPE_MAP);
const typeMap = (stateCache[typeMapKey] || remoteGraphQLSchema_1.defaultTypeMap);
createTemporaryMockNodes_1.createTemporaryMockNodes(context, pluginConfig, stateCache);
const client = getClient(config);
const url = client.getUrl(`/data/export/${dataset}`);
reporter.info('[sanity] Fetching export stream for dataset');
const inputStream = await getDocumentStream_1.getDocumentStream(url, config.token);
const processingOptions = {
typeMap,
createNodeId,
createNode,
createContentDigest,
createParentChildLink,
overlayDrafts
};
const draftDocs = [];
const publishedNodes = new Map();
await pump_1.pump([
inputStream,
split(JSON.parse),
rejectOnApiError_1.rejectOnApiError(),
overlayDrafts ? handleDrafts_1.extractDrafts(draftDocs) : handleDrafts_1.removeDrafts(),
removeSystemDocuments_1.removeSystemDocuments(),
through.obj((doc, enc, cb) => {
debug_1.default('Got document with ID %s', doc._id);
normalize_1.processDocument(doc, processingOptions);
cb();
})
]);
if (draftDocs.length > 0) {
reporter.info('[sanity] Overlaying drafts');
draftDocs.forEach(draft => {
normalize_1.processDocument(draft, processingOptions);
const published = getNode(draft.id);
if (published) {
publishedNodes.set(handleDrafts_1.unprefixId(draft._id), published);
}
});
}
if (watchMode) {
reporter.info('[sanity] Watch mode enabled, starting a listener');
client
.listen('*')
.pipe(operators_1.filter(event => overlayDrafts || !event.documentId.startsWith('drafts.')), operators_1.filter(event => !event.documentId.startsWith('_.')))
.subscribe(event => handleListenerEvent_1.handleListenerEvent(event, publishedNodes, context, processingOptions));
}
reporter.info('[sanity] Done exporting!');
};
exports.onPreExtractQueries = async (context, pluginConfig) => {
const { getNodes, store } = context;
const program = store.getState().program;
const hasImages = getNodes().some(node => Boolean(node.internal && node.internal.type === 'SanityImageAsset'));
if (hasImages) {
await fs_extra_1.copy(path.join(__dirname, '..', 'fragments', 'imageFragments.js'), `${program.directory}/.cache/fragments/sanity-image-fragments.js`);
}
await createTemporaryMockNodes_1.createTemporaryMockNodes(context, pluginConfig, stateCache);
};
exports.setFieldsOnGraphQLNodeType = async (context, pluginConfig) => {
const { type } = context;
const typeMapKey = cache_1.getCacheKey(pluginConfig, cache_1.CACHE_KEYS.TYPE_MAP);
const typeMap = (stateCache[typeMapKey] || remoteGraphQLSchema_1.defaultTypeMap);
const schemaType = typeMap.objects[type.name];
let fields = {};
if (type.name === 'SanityImageAsset') {
fields = Object.assign({}, fields, extendImageNode_1.extendImageNode(context, pluginConfig));
}
if (!schemaType) {
debug_1.default('[%s] Not in type map', type.name);
return fields;
}
return Object.keys(schemaType.fields).reduce((acc, fieldName) => {
const field = schemaType.fields[fieldName];
const aliasFor = field.aliasFor;
if (field.namedType.name.value === 'JSON' && aliasFor) {
const aliasName = '_' + lodash_1.camelCase(`raw ${field.aliasFor}`);
acc[aliasName] = {
type: graphql_1.GraphQLJSON,
resolve: obj => obj[aliasName] || obj[fieldName] || obj[aliasFor]
};
return acc;
}
if (typeMap.scalars.includes(field.namedType.name.value)) {
return acc;
}
const aliasName = '_' + lodash_1.camelCase(`raw ${fieldName}`);
acc[aliasName] = {
type: graphql_1.GraphQLJSON,
resolve: obj => obj[aliasName] || obj[fieldName]
};
return acc;
}, fields);
};
function validateConfig(config, reporter) {
if (!config.projectId) {
throw new Error('[sanity] `projectId` must be specified');
}
if (!config.dataset) {
throw new Error('[sanity] `dataset` must be specified');
}
if (config.overlayDrafts && !config.token) {
reporter.warn('[sanity] `overlayDrafts` is set to `true`, but no token is given');
}
const inDevelopMode = process.env.gatsby_executing_command === 'develop';
if (config.watchMode && !inDevelopMode) {
reporter.warn('[sanity] Using `watchMode` when not in develop mode might prevent your build from completing');
}
}
function getClient(config) {
const { projectId, dataset, token } = config;
return new SanityClient({
projectId,
dataset,
token,
useCdn: false
});
}
//# sourceMappingURL=gatsby-node.js.map