Skip to content

Commit

Permalink
[core] GraphQL: Dynamically generate GraphQL type sortings
Browse files Browse the repository at this point in the history
  • Loading branch information
saasen committed Feb 27, 2020
1 parent 0b824d8 commit 844eb50
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 26 deletions.
8 changes: 5 additions & 3 deletions packages/@sanity/core/src/actions/graphql/deployApiAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const getSanitySchema = require('./getSanitySchema')
const extractFromSanitySchema = require('./extractFromSanitySchema')
const generateTypeQueries = require('./generateTypeQueries')
const generateTypeFilters = require('./generateTypeFilters')
const generateTypeSortings = require('./generateTypeSortings')
const SchemaError = require('./SchemaError')

module.exports = async function deployApiActions(args, context) {
Expand Down Expand Up @@ -36,9 +37,10 @@ module.exports = async function deployApiActions(args, context) {
const sanitySchema = getSanitySchema(workDir)
const extracted = extractFromSanitySchema(sanitySchema)
const filters = generateTypeFilters(extracted.types)
const queries = generateTypeQueries(extracted.types, filters)
const types = extracted.types.concat(filters)
schema = {types, queries, interfaces: extracted.interfaces}
const sortings = generateTypeSortings(extracted.types)
const queries = generateTypeQueries(extracted.types, filters, sortings)
const types = extracted.types.concat(filters).concat(sortings)
schema = {types, queries, interfaces: extracted.interfaces, generation: 'v2'}
} catch (err) {
spinner.fail()

Expand Down
54 changes: 31 additions & 23 deletions packages/@sanity/core/src/actions/graphql/generateTypeQueries.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ function pluralizeTypeName(name) {
return words.join('')
}

function generateTypeQueries(types, filters) {
function generateTypeQueries(types) {
const queries = []
const queryable = types.filter(
type => type.type === 'Object' && type.interfaces && type.interfaces.includes('Document')
Expand Down Expand Up @@ -40,8 +40,6 @@ function generateTypeQueries(types, filters) {

// Fetch all of type
queryable.forEach(type => {
const filterName = `${type.name}Filter`
const hasFilter = filters.find(filter => filter.name === filterName)
queries.push({
fieldName: `all${pluralizeTypeName(type.name)}`,
filter: `_type == "${type.originalName || type.name}"`,
Expand All @@ -50,30 +48,40 @@ function generateTypeQueries(types, filters) {
isNullable: false,
children: {type: type.name, isNullable: false}
},
args: hasFilter
? [{name: 'where', type: filterName, isFieldFilter: true}].concat(getLimitOffsetArgs())
: getLimitOffsetArgs()
args: [
{
name: 'where',
type: `${type.name}Filter`,
isFieldFilter: true
},
{
name: 'sort',
type: {
kind: 'List',
isNullable: true,
children: {
type: `${type.name}Sorting`,
isNullable: false
}
}
},
{
name: 'limit',
type: 'Int',
description: 'Max documents to return',
isFieldFilter: false
},
{
name: 'offset',
type: 'Int',
description: 'Offset at which to start returning documents from',
isFieldFilter: false
}
]
})
})

return queries
}

function getLimitOffsetArgs() {
return [
{
name: 'limit',
type: 'Int',
description: 'Max documents to return',
isFieldFilter: false
},
{
name: 'offset',
type: 'Int',
description: 'Offset at which to start returning documents from',
isFieldFilter: false
}
]
}

module.exports = generateTypeQueries
69 changes: 69 additions & 0 deletions packages/@sanity/core/src/actions/graphql/generateTypeSortings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
const builtInTypes = ['ID', 'String', 'Url', 'Float', 'Integer', 'Boolean', 'Datetime', 'Date']

const builtInSortingEnum = {
name: 'SortOrder',
kind: 'Enum',
values: [
{
name: 'ASC',
description: 'Sorts on the value in ascending order.',
value: 1
},
{
name: 'DESC',
description: 'Sorts on the value in descending order.',
value: 2
}
]
}

function generateTypeSortings(types) {
const objectTypes = types.filter(
type =>
type.type === 'Object' &&
!['Block', 'Span'].includes(type.name) && // TODO: What do we do with blocks?
!type.interfaces &&
!builtInTypes.includes(type.name)
)
const documentTypes = types.filter(
type => type.type === 'Object' && type.interfaces && type.interfaces.includes('Document')
)

const objectTypeSortings = createObjectTypeSortings(objectTypes)
const documentTypeSortings = createDocumentTypeSortings(documentTypes)

return objectTypeSortings.concat(documentTypeSortings).concat(builtInSortingEnum)
}

function createObjectTypeSortings(objectTypes) {
return objectTypes.map(objectType => {
return {
name: `${objectType.name}Sorting`,
kind: 'InputObject',
fields: objectType.fields
.filter(field => field.type !== 'JSON' && field.kind !== 'List')
.map(field => ({
fieldName: field.fieldName,
type: builtInTypes.includes(field.type) ? builtInSortingEnum.name : `${field.type}Sorting`
}))
}
})
}

function createDocumentTypeSortings(documentTypes) {
return documentTypes.map(documentType => {
const fields = documentType.fields
.filter(field => field.type !== 'JSON' && field.kind !== 'List')
.map(field => ({
fieldName: field.fieldName,
type: builtInTypes.includes(field.type) ? builtInSortingEnum.name : `${field.type}Sorting`
}))
return {
name: `${documentType.name}Sorting`,
kind: 'InputObject',
fields
}
})
}

module.exports = generateTypeSortings

0 comments on commit 844eb50

Please sign in to comment.