working flexible field with all locales
This commit is contained in:
@@ -4,8 +4,6 @@ const findByIDQuery = require('../../queries/findByID');
|
||||
const findByID = ({ config, model }) => withPolicy(
|
||||
config.policies.read,
|
||||
async (parent, { id }, context) => {
|
||||
console.log(parent);
|
||||
|
||||
const options = {
|
||||
depth: 0,
|
||||
model,
|
||||
|
||||
@@ -15,21 +15,23 @@ const find = async (options) => {
|
||||
|
||||
const mongooseQuery = await model.buildQuery(query, locale);
|
||||
|
||||
const paginateQuery = {
|
||||
const mongooseOptions = {
|
||||
options: {},
|
||||
};
|
||||
|
||||
if (paginate.page) paginateQuery.page = paginate.page;
|
||||
if (paginate.limit) paginateQuery.limit = paginate.limit;
|
||||
if (paginate.sort) paginateQuery.sort = paginate.sort;
|
||||
if (paginate.page) mongooseOptions.page = paginate.page;
|
||||
if (paginate.limit) mongooseOptions.limit = paginate.limit;
|
||||
if (paginate.sort) mongooseOptions.sort = paginate.sort;
|
||||
|
||||
if (depth) {
|
||||
paginateQuery.options.autopopulate = {
|
||||
maxDepth: depth,
|
||||
if (depth && depth !== '0') {
|
||||
mongooseOptions.options.autopopulate = {
|
||||
maxDepth: parseInt(depth, 10),
|
||||
};
|
||||
} else {
|
||||
mongooseOptions.options.autopopulate = false;
|
||||
}
|
||||
|
||||
const result = await model.paginate(mongooseQuery, paginateQuery);
|
||||
const result = await model.paginate(mongooseQuery, mongooseOptions);
|
||||
|
||||
// await post find hook here
|
||||
|
||||
|
||||
@@ -9,10 +9,12 @@ const findByID = async (options) => {
|
||||
|
||||
const hasMultipleIDs = Array.isArray(id);
|
||||
|
||||
if (depth) {
|
||||
mongooseOptions.autopopulate = {
|
||||
maxDepth: depth,
|
||||
if (depth && depth !== '0') {
|
||||
mongooseOptions.options.autopopulate = {
|
||||
maxDepth: parseInt(depth, 10),
|
||||
};
|
||||
} else {
|
||||
mongooseOptions.options.autopopulate = false;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -23,7 +25,7 @@ const findByID = async (options) => {
|
||||
if (hasMultipleIDs) {
|
||||
result = await model.find({
|
||||
_id: {
|
||||
$in: id.map(id => mongoose.Types.ObjectId(id)),
|
||||
$in: id.map(docId => mongoose.Types.ObjectId(docId)),
|
||||
},
|
||||
}, {}, mongooseOptions);
|
||||
} else {
|
||||
|
||||
@@ -13,18 +13,21 @@ const buildWhereInputType = require('./schema/buildWhereInputType');
|
||||
const formatName = require('./utilities/formatName');
|
||||
const getLocaleStringType = require('./types/getLocaleStringType');
|
||||
const getLocaleFloatType = require('./types/getLocaleFloatType');
|
||||
const getBuildLocaleObjectType = require('./types/getBuildLocaleObjectType');
|
||||
const getLocaleBooleanType = require('./types/getLocaleBooleanType');
|
||||
const getBuildLocaleCustomType = require('./types/getBuildLocaleCustomType');
|
||||
const getCheckIfLocaleObject = require('./utilities/getCheckIfLocaleObject');
|
||||
const { getFind, getFindByID } = require('../collections/graphql/resolvers');
|
||||
|
||||
class GraphQL {
|
||||
constructor(config, collections) {
|
||||
this.config = config;
|
||||
this.collections = collections;
|
||||
|
||||
this.init = this.init.bind(this);
|
||||
this.registerUser = this.registerUser.bind(this);
|
||||
this.registerCollections = this.registerCollections.bind(this);
|
||||
this.buildBlockTypeIfMissing = this.buildBlockTypeIfMissing.bind(this);
|
||||
|
||||
this.config = config;
|
||||
this.collections = collections;
|
||||
this.checkIfLocaleObject = getCheckIfLocaleObject(this.config.localization);
|
||||
|
||||
this.Query = {
|
||||
name: 'Query',
|
||||
@@ -37,12 +40,13 @@ class GraphQL {
|
||||
};
|
||||
|
||||
this.types = {
|
||||
LocaleStringType: getLocaleStringType(this.config.localization),
|
||||
LocaleFloatType: getLocaleFloatType(this.config.localization),
|
||||
LocaleStringType: getLocaleStringType(this),
|
||||
LocaleFloatType: getLocaleFloatType(this),
|
||||
LocaleBooleanType: getLocaleBooleanType(this),
|
||||
blockTypes: {},
|
||||
};
|
||||
|
||||
this.buildLocaleObjectType = getBuildLocaleObjectType(this);
|
||||
this.buildLocaleCustomType = getBuildLocaleCustomType(this);
|
||||
this.buildObjectType = getBuildObjectType(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-use-before-define */
|
||||
const {
|
||||
GraphQLString,
|
||||
GraphQLFloat,
|
||||
@@ -14,90 +15,76 @@ const combineParentName = require('../utilities/combineParentName');
|
||||
const withNullableType = require('./withNullableType');
|
||||
|
||||
function getBuildObjectType(context) {
|
||||
const withLocalizedType = (field, type) => {
|
||||
if (context.config.localization && field.localized) {
|
||||
if (type instanceof GraphQLObjectType) {
|
||||
const LocaleObjectType = context.buildLocaleObjectType(field, type);
|
||||
return LocaleObjectType;
|
||||
}
|
||||
|
||||
if (type === GraphQLString) {
|
||||
return context.types.LocaleStringType;
|
||||
}
|
||||
|
||||
if (type === GraphQLFloat) {
|
||||
return context.types.LocaleFloatType;
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
};
|
||||
|
||||
const buildObjectType = (name, fields, parent, resolver) => {
|
||||
const fieldToSchemaMap = {
|
||||
number: (field) => {
|
||||
return {
|
||||
type: withLocalizedType(field, withNullableType(field, GraphQLFloat)),
|
||||
type: withNullableType(
|
||||
field,
|
||||
field.localized ? context.types.LocaleFloatType : GraphQLFloat,
|
||||
),
|
||||
};
|
||||
},
|
||||
text: (field) => {
|
||||
return {
|
||||
type: withLocalizedType(field, withNullableType(field, GraphQLString)),
|
||||
type: withNullableType(
|
||||
field,
|
||||
field.localized ? context.types.LocaleStringType : GraphQLString,
|
||||
),
|
||||
};
|
||||
},
|
||||
email: (field) => {
|
||||
return {
|
||||
type: withLocalizedType(
|
||||
type: withNullableType(
|
||||
field,
|
||||
withNullableType(field, GraphQLString),
|
||||
field.localized ? context.types.LocaleStringType : GraphQLString,
|
||||
),
|
||||
};
|
||||
},
|
||||
textarea: (field) => {
|
||||
return {
|
||||
type: withLocalizedType(
|
||||
type: withNullableType(
|
||||
field,
|
||||
withNullableType(field, GraphQLString),
|
||||
field.localized ? context.types.LocaleStringType : GraphQLString,
|
||||
),
|
||||
};
|
||||
},
|
||||
WYSIWYG: (field) => {
|
||||
return {
|
||||
type: withLocalizedType(
|
||||
type: withNullableType(
|
||||
field,
|
||||
withNullableType(field, GraphQLString),
|
||||
field.localized ? context.types.LocaleStringType : GraphQLString,
|
||||
),
|
||||
};
|
||||
},
|
||||
code: (field) => {
|
||||
return {
|
||||
type: withLocalizedType(
|
||||
type: withNullableType(
|
||||
field,
|
||||
withNullableType(field, GraphQLString),
|
||||
field.localized ? context.types.LocaleStringType : GraphQLString,
|
||||
),
|
||||
};
|
||||
},
|
||||
date: (field) => {
|
||||
return {
|
||||
type: withLocalizedType(
|
||||
type: withNullableType(
|
||||
field,
|
||||
withNullableType(field, GraphQLString),
|
||||
field.localized ? context.types.LocaleStringType : GraphQLString,
|
||||
),
|
||||
};
|
||||
},
|
||||
upload: (field) => {
|
||||
const type = GraphQLString;
|
||||
return {
|
||||
type: withLocalizedType(
|
||||
type: withNullableType(
|
||||
field,
|
||||
withNullableType(field, type),
|
||||
field.localized ? context.types.LocaleStringType : GraphQLString,
|
||||
),
|
||||
};
|
||||
},
|
||||
checkbox: field => ({
|
||||
type: withLocalizedType(
|
||||
type: withNullableType(
|
||||
field,
|
||||
new GraphQLNonNull(GraphQLBoolean),
|
||||
field.localized ? context.types.LocaleBooleanType : GraphQLBoolean,
|
||||
),
|
||||
}),
|
||||
select: (field) => {
|
||||
@@ -132,10 +119,7 @@ function getBuildObjectType(context) {
|
||||
const typeWithNullable = withNullableType(field, typeWithList);
|
||||
|
||||
return {
|
||||
type: withLocalizedType(
|
||||
field,
|
||||
typeWithNullable,
|
||||
),
|
||||
type: field.localized ? context.buildLocaleCustomType(field, typeWithNullable, parent) : typeWithNullable,
|
||||
};
|
||||
},
|
||||
relationship: (field) => {
|
||||
@@ -158,16 +142,17 @@ function getBuildObjectType(context) {
|
||||
relationshipType = context.collections[relationTo].graphQLType;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
relationshipType = relationshipType || blockType;
|
||||
// If the relationshipType is undefined at this point,
|
||||
// it can be assumed that this blockType can have a relationship
|
||||
// to itself. Therefore, we set the relationshipType equal to the blockType
|
||||
// that is currently being created.
|
||||
|
||||
const typeWithLocale = withLocalizedType(
|
||||
field,
|
||||
withNullableType(field, relationshipType),
|
||||
);
|
||||
relationshipType = relationshipType || newlyCreatedBlockType;
|
||||
|
||||
const localizedType = field.localized ? context.buildLocaleCustomType(field, relationshipType, parent) : relationshipType;
|
||||
|
||||
return {
|
||||
type: field.hasMany ? new GraphQLList(typeWithLocale) : typeWithLocale,
|
||||
type: field.hasMany ? new GraphQLList(localizedType) : localizedType,
|
||||
};
|
||||
},
|
||||
repeater: (field) => {
|
||||
@@ -176,10 +161,7 @@ function getBuildObjectType(context) {
|
||||
const typeWithNullable = new GraphQLList(withNullableType(field, type));
|
||||
|
||||
return {
|
||||
type: withLocalizedType(
|
||||
field,
|
||||
typeWithNullable,
|
||||
),
|
||||
type: field.localized ? context.buildLocaleCustomType(field, typeWithNullable, parent) : typeWithNullable,
|
||||
};
|
||||
},
|
||||
group: (field) => {
|
||||
@@ -191,25 +173,35 @@ function getBuildObjectType(context) {
|
||||
};
|
||||
},
|
||||
flexible: (field) => {
|
||||
const types = field.blocks.map((block) => {
|
||||
const blockTypes = field.blocks.map((block) => {
|
||||
context.buildBlockTypeIfMissing(block);
|
||||
return context.types.blockTypes[block.slug];
|
||||
});
|
||||
|
||||
return {
|
||||
type: withLocalizedType(
|
||||
field,
|
||||
new GraphQLList(
|
||||
new GraphQLUnionType({
|
||||
name: combineParentName(parent, field.label),
|
||||
types,
|
||||
resolveType(data) {
|
||||
return context.types.blockTypes[data.blockType];
|
||||
},
|
||||
}),
|
||||
),
|
||||
),
|
||||
};
|
||||
const flexibleType = new GraphQLList(
|
||||
new GraphQLUnionType({
|
||||
name: combineParentName(parent, field.label),
|
||||
blockTypes,
|
||||
resolveType(data) {
|
||||
// If the field contains all locales, it's a locale object
|
||||
// Send back the locale object type
|
||||
// Otherwise, grab the appropriate block type and send that
|
||||
if (context.checkIfLocaleObject(data)) {
|
||||
return flexibleLocaleObjectType;
|
||||
}
|
||||
return context.types.blockTypes[data.blockType];
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const flexibleLocaleObjectType = context.buildLocaleCustomType(field, flexibleType, parent);
|
||||
|
||||
if (field.localized) {
|
||||
blockTypes.push(flexibleLocaleObjectType);
|
||||
return { type: flexibleLocaleObjectType };
|
||||
}
|
||||
|
||||
return flexibleType;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -232,9 +224,9 @@ function getBuildObjectType(context) {
|
||||
objectSchema.resolve = resolver;
|
||||
}
|
||||
|
||||
const blockType = new GraphQLObjectType(objectSchema);
|
||||
const newlyCreatedBlockType = new GraphQLObjectType(objectSchema);
|
||||
|
||||
return blockType;
|
||||
return newlyCreatedBlockType;
|
||||
};
|
||||
|
||||
return buildObjectType;
|
||||
|
||||
34
src/graphql/types/getBuildLocaleCustomType.js
Normal file
34
src/graphql/types/getBuildLocaleCustomType.js
Normal file
@@ -0,0 +1,34 @@
|
||||
const { GraphQLScalarType } = require('graphql');
|
||||
const combineParentName = require('../utilities/combineParentName');
|
||||
|
||||
module.exports = (context) => {
|
||||
return (field, type, parent) => {
|
||||
const fullName = combineParentName(parent, field.label);
|
||||
|
||||
const coerceType = (value) => {
|
||||
const isLocaleObject = context.checkIfLocaleObject(value);
|
||||
|
||||
if (isLocaleObject) {
|
||||
// const allKeysValid = Object.values(value).every(locale => isValidJSValue(locale, type));
|
||||
|
||||
// if (allKeysValid) {
|
||||
return value;
|
||||
// }
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
// throw new Error(`${fullName}LocaleType can only represent an object containing locales or a matchiing ${fullName} type.`);
|
||||
};
|
||||
|
||||
const LocaleCustomType = new GraphQLScalarType({
|
||||
name: `${fullName}LocaleType`,
|
||||
description: `Handles locale values that can either be an object containing locales or a matching ${fullName} type.`,
|
||||
serialize: coerceType,
|
||||
parseValue: coerceType,
|
||||
parseLiteral: ast => ast.value,
|
||||
});
|
||||
|
||||
return LocaleCustomType;
|
||||
};
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
const { GraphQLScalarType } = require('graphql');
|
||||
const getIsLocaleObject = require('../utilities/getIsLocaleObject');
|
||||
const combineParentName = require('../utilities/combineParentName');
|
||||
|
||||
module.exports = (config) => {
|
||||
return (field, type, parent) => {
|
||||
const fullName = combineParentName(parent, field.label);
|
||||
|
||||
const coerceType = (value) => {
|
||||
const isLocaleObject = getIsLocaleObject(config, value);
|
||||
|
||||
if (value instanceof type || isLocaleObject) {
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new Error(`LocaleFloatType can only represent an object containing locales or ${fullName} properties.`);
|
||||
};
|
||||
|
||||
const LocaleObjectType = new GraphQLScalarType({
|
||||
name: `${fullName}LocaleType`,
|
||||
description: `Handles locale values that can either be an object containing all locales or an object containing ${fullName} properties.`,
|
||||
serialize: coerceType,
|
||||
parseValue: coerceType,
|
||||
parseLiteral: ast => ast.value,
|
||||
});
|
||||
|
||||
return LocaleObjectType;
|
||||
};
|
||||
};
|
||||
23
src/graphql/types/getLocaleBooleanType.js
Normal file
23
src/graphql/types/getLocaleBooleanType.js
Normal file
@@ -0,0 +1,23 @@
|
||||
const { GraphQLScalarType } = require('graphql');
|
||||
|
||||
module.exports = (context) => {
|
||||
const coerceType = (value) => {
|
||||
const isLocaleObject = context.checkIfLocaleObject(value);
|
||||
|
||||
if (typeof value === 'boolean' || isLocaleObject) {
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new Error('LocaleBooleanType can only represent a boolean or an object containing all locales.');
|
||||
};
|
||||
|
||||
const LocaleBooleanType = new GraphQLScalarType({
|
||||
name: 'LocaleBooleanType',
|
||||
description: 'Handles locale values that can either be an object containing all locales or a boolean of a single locale.',
|
||||
serialize: coerceType,
|
||||
parseValue: coerceType,
|
||||
parseLiteral: ast => ast.value,
|
||||
});
|
||||
|
||||
return LocaleBooleanType;
|
||||
};
|
||||
@@ -1,25 +1,23 @@
|
||||
const { GraphQLScalarType } = require('graphql');
|
||||
const getIsLocaleObject = require('../utilities/getIsLocaleObject');
|
||||
|
||||
module.exports = (localization) => {
|
||||
module.exports = (context) => {
|
||||
const coerceType = (value) => {
|
||||
const isLocaleObject = getIsLocaleObject(localization, value);
|
||||
const isLocaleObject = context.checkIfLocaleObject(value);
|
||||
|
||||
if (typeof value === 'number'
|
||||
|| isLocaleObject) {
|
||||
if (typeof value === 'number' || isLocaleObject) {
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new Error('LocaleFloatType can only represent a float or an object containing all locales.');
|
||||
};
|
||||
|
||||
const LocaleString = new GraphQLScalarType({
|
||||
name: 'LocaleType',
|
||||
const LocaleFloatType = new GraphQLScalarType({
|
||||
name: 'LocaleFloatType',
|
||||
description: 'Handles locale values that can either be an object containing all locales or a float of a single locale.',
|
||||
serialize: coerceType,
|
||||
parseValue: coerceType,
|
||||
parseLiteral: ast => ast.value,
|
||||
});
|
||||
|
||||
return LocaleString;
|
||||
return LocaleFloatType;
|
||||
};
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
const { GraphQLScalarType } = require('graphql');
|
||||
const getIsLocaleObject = require('../utilities/getIsLocaleObject');
|
||||
|
||||
module.exports = (localization) => {
|
||||
module.exports = (context) => {
|
||||
const coerceType = (value) => {
|
||||
const isLocaleObject = getIsLocaleObject(localization, value);
|
||||
const isLocaleObject = context.checkIfLocaleObject(value);
|
||||
|
||||
if (typeof value === 'string'
|
||||
|| isLocaleObject) {
|
||||
if (typeof value === 'string' || isLocaleObject) {
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new Error('LocaleString can only represent a string or an object containing all locales.');
|
||||
};
|
||||
|
||||
const LocaleString = new GraphQLScalarType({
|
||||
name: 'LocaleType',
|
||||
const LocaleStringType = new GraphQLScalarType({
|
||||
name: 'LocaleStringType',
|
||||
description: 'Handles locale values that can either be an object containing all locales or a string of a single locale.',
|
||||
serialize: coerceType,
|
||||
parseValue: coerceType,
|
||||
parseLiteral: ast => ast.value,
|
||||
});
|
||||
|
||||
return LocaleString;
|
||||
return LocaleStringType;
|
||||
};
|
||||
|
||||
6
src/graphql/utilities/getCheckIfLocaleObject.js
Normal file
6
src/graphql/utilities/getCheckIfLocaleObject.js
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = (localization) => {
|
||||
return (value) => {
|
||||
return typeof value === 'object'
|
||||
&& Object.keys(value).some(key => localization.locales.indexOf(key) > -1);
|
||||
};
|
||||
};
|
||||
@@ -1,4 +0,0 @@
|
||||
module.exports = (localization, value) => {
|
||||
return typeof value === 'object'
|
||||
&& Object.keys(value).every(key => localization.locales.indexOf(key) > -1);
|
||||
};
|
||||
Reference in New Issue
Block a user