recycles findByID mongoose query within GraphQL relationship queries

This commit is contained in:
James
2020-04-07 19:42:52 -04:00
parent f20f16d7d3
commit 39a77db9bd
5 changed files with 116 additions and 33 deletions

View File

@@ -1,18 +1,35 @@
/* eslint-disable no-param-reassign */
const withPolicy = require('../../../graphql/resolvers/withPolicy');
const findQuery = require('../../queries/find');
const find = ({ config, model }) => {
return withPolicy(
config.policies.read,
async (_, args) => {
async (_, args, context) => {
const options = {
depth: 0,
model,
query: args,
locale: args.locale,
query: Object.keys(args).reduce((query, arg) => {
if (arg === 'where') {
return {
...query,
arg: args[arg],
};
}
return query;
}),
};
if (args.fallbackLocale) options.fallbackLocale = args.fallbackLocale;
if (args.locale) {
context.locale = args.locale;
options.locale = args.locale;
}
if (args.fallbackLocale) {
context.fallbackLocale = args.fallbackLocale;
options.fallbackLocale = args.fallbackLocale;
}
const results = await findQuery(options);

View File

@@ -1,17 +1,25 @@
/* eslint-disable no-param-reassign */
const withPolicy = require('../../../graphql/resolvers/withPolicy');
const findByIDQuery = require('../../queries/findByID');
const findByID = ({ config, model }) => withPolicy(
config.policies.read,
async (parent, { id }, context) => {
async (_, args, context) => {
const options = {
depth: 0,
model,
id,
locale: context.locale,
id: args.id,
};
if (context.query['fallback-locale']) options.fallbackLocale = context.query['fallback-locale'];
if (args.locale) {
context.locale = args.locale;
options.locale = args.locale;
}
if (args.fallbackLocale) {
context.fallbackLocale = args.fallbackLocale;
options.fallbackLocale = args.fallbackLocale;
}
const result = await findByIDQuery(options);

View File

@@ -46,6 +46,7 @@ const find = async (options) => {
}),
};
} catch (err) {
console.log(err);
throw new APIError();
}
};

View File

@@ -2,7 +2,10 @@ const mongoose = require('mongoose');
const { NotFound } = require('../../errors');
const findByID = async (options) => {
const mongooseOptions = {};
const mongooseOptions = {
options: {},
};
const {
depth, locale, fallbackLocale, model, id,
} = options;
@@ -17,11 +20,11 @@ const findByID = async (options) => {
mongooseOptions.options.autopopulate = false;
}
let result;
try {
// Await pre find hook here
let result;
if (hasMultipleIDs) {
result = await model.find({
_id: {
@@ -32,14 +35,18 @@ const findByID = async (options) => {
result = await model.findOne({ _id: id }, {}, mongooseOptions);
}
if (result.length === 0) throw new NotFound();
if (!result || (result && result.length === 0)) throw new NotFound();
if (hasMultipleIDs) {
result = result.map((doc) => {
return result.map((doc) => {
if (locale && doc.setLocale) doc.setLocale(locale, fallbackLocale);
return doc.toJSON({ virtuals: true });
});
} else if (locale && result.setLocale) result = result.setLocale(locale, fallbackLocale);
}
if (locale && result.setLocale) {
result.setLocale(locale, fallbackLocale);
}
// Await post find hook here

View File

@@ -1,3 +1,5 @@
/* eslint-disable no-await-in-loop */
/* eslint-disable no-restricted-syntax */
/* eslint-disable no-use-before-define */
const {
GraphQLString,
@@ -12,9 +14,10 @@ const {
const formatName = require('../utilities/formatName');
const combineParentName = require('../utilities/combineParentName');
const withNullableType = require('./withNullableType');
const findByID = require('../../collections/queries/findByID');
function getBuildObjectType(context) {
const buildObjectType = (name, fields, parent, resolver) => {
function getBuildObjectType(graphQLContext) {
const buildObjectType = (name, fields, parentName) => {
const fieldToSchemaMap = {
number: field => ({ type: withNullableType(field, GraphQLFloat) }),
text: field => ({ type: withNullableType(field, GraphQLString) }),
@@ -26,7 +29,7 @@ function getBuildObjectType(context) {
upload: field => ({ type: withNullableType(field, GraphQLString) }),
checkbox: field => ({ type: withNullableType(field, GraphQLBoolean) }),
select: (field) => {
const fullName = combineParentName(parent, field.name);
const fullName = combineParentName(parentName, field.name);
let type = new GraphQLEnumType({
name: fullName,
@@ -60,22 +63,25 @@ function getBuildObjectType(context) {
},
relationship: (field) => {
const { relationTo, label } = field;
const isRelatedToManyCollections = Array.isArray(relationTo);
const hasManyValues = field.hasMany;
let type;
if (Array.isArray(relationTo)) {
if (isRelatedToManyCollections) {
const types = relationTo.map((relation) => {
return context.collections[relation].graphQLType;
return graphQLContext.collections[relation].graphQLType;
});
type = new GraphQLUnionType({
name: combineParentName(parent, label),
name: combineParentName(parentName, label),
types,
resolveType(data) {
return context.types.blockTypes[data.blockType];
return graphQLContext.types.blockTypes[data.blockType];
},
});
} else {
type = context.collections[relationTo].graphQLType;
type = graphQLContext.collections[relationTo].graphQLType;
}
// If the relationshipType is undefined at this point,
@@ -86,33 +92,81 @@ function getBuildObjectType(context) {
type = type || newlyCreatedBlockType;
return {
type: field.hasMany ? new GraphQLList(type) : type,
type: hasManyValues ? new GraphQLList(type) : type,
async resolve(parent, args, context) {
const value = parent[field.name];
const locale = args.locale || context.locale;
const fallbackLocale = args.fallbackLocale || context.fallbackLocale;
let relatedCollectionSlug = field.relationTo;
if (hasManyValues) {
const results = [];
if (value) {
for (const relatedDoc of value) {
let id = relatedDoc;
if (isRelatedToManyCollections) {
relatedCollectionSlug = relatedDoc.relationTo;
id = relatedDoc.value;
}
const result = await findByID({
model: graphQLContext.collections[relatedCollectionSlug].model,
id,
locale,
fallbackLocale,
});
results.push(result);
}
}
return results;
}
let id = value;
if (isRelatedToManyCollections && value) id = value.value;
if (id) {
id = id.toString();
const relatedDocument = await findByID({
model: graphQLContext.collections[relatedCollectionSlug].model,
id,
locale,
fallbackLocale,
});
return relatedDocument;
}
},
};
},
repeater: (field) => {
const fullName = combineParentName(parent, field.label);
const fullName = combineParentName(parentName, field.label);
let type = buildObjectType(fullName, field.fields, fullName);
type = new GraphQLList(withNullableType(field, type));
return { type };
},
group: (field) => {
const fullName = combineParentName(parent, field.label);
const fullName = combineParentName(parentName, field.label);
const type = buildObjectType(fullName, field.fields, fullName);
return { type };
},
flexible: (field) => {
const blockTypes = field.blocks.map((block) => {
context.buildBlockTypeIfMissing(block);
return context.types.blockTypes[block.slug];
graphQLContext.buildBlockTypeIfMissing(block);
return graphQLContext.types.blockTypes[block.slug];
});
const type = new GraphQLList(new GraphQLUnionType({
name: combineParentName(parent, field.label),
name: combineParentName(parentName, field.label),
types: blockTypes,
resolveType(data) {
return context.types.blockTypes[data.blockType];
return graphQLContext.types.blockTypes[data.blockType];
},
}));
@@ -135,10 +189,6 @@ function getBuildObjectType(context) {
}, {}),
};
if (resolver) {
objectSchema.resolve = resolver;
}
const newlyCreatedBlockType = new GraphQLObjectType(objectSchema);
return newlyCreatedBlockType;