UNPKG

@directus/api

Version:

Directus is a real-time API and App dashboard for managing SQL database content

88 lines (87 loc) 3.72 kB
import { parseFilterFunctionPath } from '@directus/utils'; import { omit } from 'lodash-es'; import { mergeVersionsRaw, mergeVersionsRecursive } from '../../../utils/merge-version-data.js'; import { VersionsService } from '../../versions.js'; import { parseArgs } from '../schema/parse-args.js'; import { getQuery } from '../schema/parse-query.js'; import { getAggregateQuery } from '../utils/aggregate-query.js'; import { replaceFragmentsInSelections } from '../utils/replace-fragments.js'; /** * Generic resolver that's used for every "regular" items/system query. Converts the incoming GraphQL AST / fragments into * Directus' query structure which is then executed by the services. */ export async function resolveQuery(gql, info) { let collection = info.fieldName; if (gql.scope === 'system') collection = `directus_${collection}`; const selections = replaceFragmentsInSelections(info.fieldNodes[0]?.selectionSet?.selections, info.fragments); if (!selections) return null; const args = parseArgs(info.fieldNodes[0].arguments || [], info.variableValues); let query; let versionRaw = false; const isAggregate = collection.endsWith('_aggregated') && collection in gql.schema.collections === false; if (isAggregate) { query = await getAggregateQuery(args, selections, gql.schema, gql.accountability); collection = collection.slice(0, -11); } else { query = await getQuery(args, selections, info.variableValues, gql.schema, gql.accountability); if (collection.endsWith('_by_id') && collection in gql.schema.collections === false) { collection = collection.slice(0, -6); } if (collection.endsWith('_by_version') && collection in gql.schema.collections === false) { collection = collection.slice(0, -11); versionRaw = true; } } if (args['id']) { query.filter = { _and: [ query.filter || {}, { [gql.schema.collections[collection].primary]: { _eq: args['id'], }, }, ], }; query.limit = 1; } // Transform count(a.b.c) into a.b.count(c) if (query.fields?.length) { for (let fieldIndex = 0; fieldIndex < query.fields.length; fieldIndex++) { query.fields[fieldIndex] = parseFilterFunctionPath(query.fields[fieldIndex]); } } const result = await gql.read(collection, query); if (args['version']) { const versionsService = new VersionsService({ accountability: gql.accountability, schema: gql.schema }); const saves = await versionsService.getVersionSaves(args['version'], collection, args['id']); if (saves) { if (gql.schema.collections[collection].singleton) { return versionRaw ? mergeVersionsRaw(result, saves) : mergeVersionsRecursive(result, saves, collection, gql.schema); } else { if (result?.[0] === undefined) return null; return versionRaw ? mergeVersionsRaw(result[0], saves) : mergeVersionsRecursive(result[0], saves, collection, gql.schema); } } } if (args['id']) { return result?.[0] || null; } if (query.group) { // for every entry in result add a group field based on query.group; const aggregateKeys = Object.keys(query.aggregate ?? {}); result['map']((field) => { field['group'] = omit(field, aggregateKeys); }); } return result; }