UNPKG

gatsby-source-sanity

Version:

Gatsby source plugin for building websites using Sanity.io as a backend.

151 lines 6.45 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const graphql_1 = require("gatsby/graphql"); const normalize_1 = require("./normalize"); const builtins = ['ID', 'String', 'Boolean', 'Int', 'Float', 'JSON', 'DateTime', 'Date']; const wantedNodeTypes = ['ObjectTypeDefinition', 'UnionTypeDefinition', 'InterfaceTypeDefinition']; exports.rewriteGraphQLSchema = (schemaSdl, context) => { const ast = graphql_1.parse(schemaSdl); const transformedAst = transformAst(ast, context); const transformed = graphql_1.print(transformedAst); return transformed; }; function transformAst(ast, context) { return Object.assign(Object.assign({}, ast), { definitions: ast.definitions .filter(isWantedAstNode) .map(node => transformDefinitionNode(node, context)) }); } function isWantedAstNode(astNode) { const node = astNode; return wantedNodeTypes.includes(node.kind) && node.name.value !== 'RootQuery'; } function transformDefinitionNode(node, context) { switch (node.kind) { case 'ObjectTypeDefinition': return transformObjectTypeDefinition(node, context); case 'UnionTypeDefinition': return transformUnionTypeDefinition(node, context); case 'InterfaceTypeDefinition': return transformInterfaceTypeDefinition(node, context); default: return node; } } function transformObjectTypeDefinition(node, context) { const fields = node.fields || []; const jsonTargets = fields.map(getJsonAliasTargets).filter(Boolean); const blockFields = jsonTargets.map(makeBlockField); const interfaces = (node.interfaces || []).map(maybeRewriteType); const isDocumentType = interfaces.some(item => item.kind === 'NamedType' && item.name.value === 'SanityDocument'); // Implement Gatsby node interface if it is a document if (isDocumentType) { interfaces.push({ kind: 'NamedType', name: { kind: 'Name', value: 'Node' } }); } return Object.assign(Object.assign({}, node), { name: Object.assign(Object.assign({}, node.name), { value: getTypeName(node.name.value) }), interfaces, directives: [{ kind: 'Directive', name: { kind: 'Name', value: 'dontInfer' } }], fields: [ ...fields .filter(field => !getJsonAliasTargets(field)) .map(field => transformFieldNodeAst(field, node, context)), ...blockFields, ] }); } function transformUnionTypeDefinition(node, context) { return Object.assign(Object.assign({}, node), { types: (node.types || []).map(maybeRewriteType), name: Object.assign(Object.assign({}, node.name), { value: getTypeName(node.name.value) }) }); } function transformInterfaceTypeDefinition(node, context) { const fields = node.fields || []; return Object.assign(Object.assign({}, node), { fields: fields.map(field => transformFieldNodeAst(field, node, context)), name: Object.assign(Object.assign({}, node.name), { value: getTypeName(node.name.value) }) }); } function unwrapType(typeNode) { if (['NonNullType', 'ListType'].includes(typeNode.kind)) { const wrappedType = typeNode; return unwrapType(wrappedType.type); } return typeNode; } function getJsonAliasTargets(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 makeBlockField(name) { return { kind: 'FieldDefinition', name: { kind: 'Name', value: name, }, arguments: [], directives: [], type: { kind: 'ListType', type: { kind: 'NamedType', name: { kind: 'Name', value: 'SanityBlock', }, }, }, }; } function makeNullable(nodeType) { if (nodeType.kind === 'NamedType') { return maybeRewriteType(nodeType); } if (nodeType.kind === 'ListType') { const unwrapped = maybeRewriteType(unwrapType(nodeType)); return { kind: 'ListType', type: makeNullable(unwrapped), }; } return maybeRewriteType(nodeType.type); } function transformFieldNodeAst(node, parent, context) { const field = Object.assign(Object.assign({}, node), { name: maybeRewriteFieldName(node, parent, context), type: rewireIdType(makeNullable(node.type)), description: undefined, directives: [] }); if (field.type.kind === 'NamedType' && field.type.name.value === 'Date') { field.directives.push({ kind: 'Directive', name: { kind: 'Name', value: 'dateformat' } }); } return field; } function rewireIdType(nodeType) { if (nodeType.kind === 'NamedType' && nodeType.name.value === 'ID') { return Object.assign(Object.assign({}, nodeType), { name: { kind: 'Name', value: 'String' } }); } return nodeType; } function maybeRewriteType(nodeType) { const type = nodeType; if (typeof type.name === 'undefined') { return nodeType; } // Gatsby has a date type, but not a datetime, so rewire it if (type.name.value === 'DateTime') { return Object.assign(Object.assign({}, type), { name: { kind: 'Name', value: 'Date' } }); } if (builtins.includes(type.name.value)) { return type; } return Object.assign(Object.assign({}, type), { name: { kind: 'Name', value: getTypeName(type.name.value) } }); } function maybeRewriteFieldName(field, parent, context) { if (!normalize_1.RESTRICTED_NODE_FIELDS.includes(field.name.value)) { return field.name; } const parentTypeName = parent.name.value; const newFieldName = normalize_1.getConflictFreeFieldName(field.name.value); if (parentTypeName !== 'Block') { context.reporter.warn(`[sanity] Type \`${parentTypeName}\` has field with name \`${field.name.value}\`, which conflicts with Gatsby's internal properties. Renaming to \`${newFieldName}\``); } return Object.assign(Object.assign({}, field.name), { value: newFieldName }); } function getTypeName(name) { return name.startsWith('Sanity') ? name : `Sanity${name}`; } //# sourceMappingURL=rewriteGraphQLSchema.js.map