gatsby-source-sanity
Version:
Gatsby source plugin for building websites using Sanity.io as a backend.
119 lines • 4.76 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = require("lodash");
const graphql_1 = require("gatsby/graphql");
const normalize_1 = require("./normalize");
const getExampleValues_1 = require("./getExampleValues");
const debug_1 = require("../debug");
class RequestError extends Error {
constructor(message, isWarning) {
super(message);
this.isWarning = isWarning;
}
}
exports.defaultTypeMap = {
scalars: [],
unions: {},
objects: {},
exampleValues: {}
};
async function getRemoteGraphQLSchema(client, config) {
const { graphqlApi } = config;
const { dataset } = client.config();
try {
const api = await client.request({
url: `/apis/graphql/${dataset}/${graphqlApi}`,
headers: { Accept: 'application/graphql' }
});
return api;
}
catch (err) {
const code = lodash_1.get(err, 'response.statusCode');
const message = lodash_1.get(err, 'response.body.message', lodash_1.get(err, 'response.statusMessage') || err.message);
const gqlBenefits = [
'Schemas will be much cleaner, and you will have less problems with missing fields',
'See https://github.com/sanity-io/gatsby-source-sanity#missing-fields for more info'
].join('\n');
const is404 = code === 404 || /schema not found/i.test(message);
const hint = is404 ? ' - have you run `sanity graphql deploy` yet?\n' + gqlBenefits : '';
throw new RequestError(`${message}${hint}`, is404);
}
}
exports.getRemoteGraphQLSchema = getRemoteGraphQLSchema;
function getTypeMapFromGraphQLSchema(sdl, config) {
const typeMap = { objects: {}, unions: {}, scalars: [], exampleValues: {} };
const remoteSchema = graphql_1.parse(sdl);
const groups = Object.assign({ ObjectTypeDefinition: [], UnionTypeDefinition: [], ScalarTypeDefinition: [] }, lodash_1.groupBy(remoteSchema.definitions, 'kind'));
const objects = {};
typeMap.objects = groups.ObjectTypeDefinition.reduce((acc, typeDef) => {
const name = normalize_1.getTypeName(typeDef.name.value);
acc[name] = {
name,
kind: 'Object',
isDocument: Boolean((typeDef.interfaces || []).find(iface => iface.name.value === 'Document')),
fields: (typeDef.fields || []).reduce((fields, fieldDef) => (Object.assign({}, fields, { [fieldDef.name.value]: {
type: fieldDef.type,
isList: isListType(fieldDef.type),
namedType: unwrapType(fieldDef.type),
aliasFor: getAliasDirective(fieldDef),
isReference: Boolean(getReferenceDirective(fieldDef))
} })), {})
};
return acc;
}, objects);
const unions = {};
typeMap.unions = groups.UnionTypeDefinition.reduce((acc, typeDef) => {
const name = normalize_1.getTypeName(typeDef.name.value);
acc[name] = {
name,
kind: 'Union',
types: (typeDef.types || []).map(type => type.name.value)
};
return acc;
}, unions);
typeMap.scalars = graphql_1.specifiedScalarTypes
.map(scalar => scalar.name)
.concat(groups.ScalarTypeDefinition.map((typeDef) => typeDef.name.value));
try {
typeMap.exampleValues = getExampleValues_1.getExampleValues(remoteSchema, config, typeMap);
}
catch (err) {
debug_1.default('Failed to mock values:\n%s', err.stack);
debug_1.default('Failed to transform GraphQL schema AST: %s', err.stack);
debug_1.default('Original schema:\n\n', remoteSchema);
}
return typeMap;
}
exports.getTypeMapFromGraphQLSchema = getTypeMapFromGraphQLSchema;
function unwrapType(typeNode) {
if (['NonNullType', 'ListType'].includes(typeNode.kind)) {
const wrappedType = typeNode;
return unwrapType(wrappedType.type);
}
return typeNode;
}
function isListType(typeNode) {
if (typeNode.kind === 'ListType') {
return true;
}
if (typeNode.kind === 'NonNullType') {
const node = typeNode;
return isListType(node.type);
}
return false;
}
function getAliasDirective(field) {
const alias = (field.directives || []).find(dir => dir.name.value === 'jsonAlias');
if (!alias) {
return null;
}
const forArg = (alias.arguments || []).find(arg => arg.name.value === 'for');
if (!forArg) {
return null;
}
return graphql_1.valueFromAST(forArg.value, graphql_1.GraphQLString, {});
}
function getReferenceDirective(field) {
return (field.directives || []).find(dir => dir.name.value === 'reference');
}
//# sourceMappingURL=remoteGraphQLSchema.js.map