working flexible field with all locales

This commit is contained in:
James
2020-04-07 14:40:01 -04:00
parent 057bb631c8
commit b5bf45ce9c
12 changed files with 162 additions and 138 deletions

View File

@@ -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);
}

View File

@@ -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;

View 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;
};
};

View File

@@ -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;
};
};

View 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;
};

View File

@@ -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;
};

View File

@@ -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;
};

View File

@@ -0,0 +1,6 @@
module.exports = (localization) => {
return (value) => {
return typeof value === 'object'
&& Object.keys(value).some(key => localization.locales.indexOf(key) > -1);
};
};

View File

@@ -1,4 +0,0 @@
module.exports = (localization, value) => {
return typeof value === 'object'
&& Object.keys(value).every(key => localization.locales.indexOf(key) > -1);
};