GraphQL: Renaming Types/Inputs (#5883)
* Renaming GraphQL Types/Inputs * Add Native Type to avoid collision * Use pluralize for renaming * Fixing tests * Improve name collision management - tests passsing * Renaming few more default types * Rename file input * Reverting fields types to not collide with the relay spec types Improver users mutations * Adding ArrayResult to the reserved list * Fixing tests * Add more unit tests to ParseGraphQLSchema * Test transformClassNameToGraphQL * Name collision tests
This commit is contained in:
committed by
Antonio Davi Macedo Coelho de Castro
parent
cf6e79ee75
commit
59b0221fec
@@ -8,6 +8,7 @@ import getFieldNames from 'graphql-list-fields';
|
||||
import Parse from 'parse/node';
|
||||
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
|
||||
import rest from '../../rest';
|
||||
import { transformQueryInputToParse } from '../transformers/query';
|
||||
|
||||
const getObject = async (
|
||||
className,
|
||||
@@ -54,155 +55,6 @@ const getObject = async (
|
||||
return response.results[0];
|
||||
};
|
||||
|
||||
const parseMap = {
|
||||
_or: '$or',
|
||||
_and: '$and',
|
||||
_nor: '$nor',
|
||||
_relatedTo: '$relatedTo',
|
||||
_eq: '$eq',
|
||||
_ne: '$ne',
|
||||
_lt: '$lt',
|
||||
_lte: '$lte',
|
||||
_gt: '$gt',
|
||||
_gte: '$gte',
|
||||
_in: '$in',
|
||||
_nin: '$nin',
|
||||
_exists: '$exists',
|
||||
_select: '$select',
|
||||
_dontSelect: '$dontSelect',
|
||||
_inQuery: '$inQuery',
|
||||
_notInQuery: '$notInQuery',
|
||||
_containedBy: '$containedBy',
|
||||
_all: '$all',
|
||||
_regex: '$regex',
|
||||
_options: '$options',
|
||||
_text: '$text',
|
||||
_search: '$search',
|
||||
_term: '$term',
|
||||
_language: '$language',
|
||||
_caseSensitive: '$caseSensitive',
|
||||
_diacriticSensitive: '$diacriticSensitive',
|
||||
_nearSphere: '$nearSphere',
|
||||
_maxDistance: '$maxDistance',
|
||||
_maxDistanceInRadians: '$maxDistanceInRadians',
|
||||
_maxDistanceInMiles: '$maxDistanceInMiles',
|
||||
_maxDistanceInKilometers: '$maxDistanceInKilometers',
|
||||
_within: '$within',
|
||||
_box: '$box',
|
||||
_geoWithin: '$geoWithin',
|
||||
_polygon: '$polygon',
|
||||
_centerSphere: '$centerSphere',
|
||||
_geoIntersects: '$geoIntersects',
|
||||
_point: '$point',
|
||||
};
|
||||
|
||||
const transformToParse = (constraints, parentFieldName, parentConstraints) => {
|
||||
if (!constraints || typeof constraints !== 'object') {
|
||||
return;
|
||||
}
|
||||
Object.keys(constraints).forEach(fieldName => {
|
||||
let fieldValue = constraints[fieldName];
|
||||
|
||||
/**
|
||||
* If we have a key-value pair, we need to change the way the constraint is structured.
|
||||
*
|
||||
* Example:
|
||||
* From:
|
||||
* {
|
||||
* "someField": {
|
||||
* "_lt": {
|
||||
* "_key":"foo.bar",
|
||||
* "_value": 100
|
||||
* },
|
||||
* "_gt": {
|
||||
* "_key":"foo.bar",
|
||||
* "_value": 10
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* To:
|
||||
* {
|
||||
* "someField.foo.bar": {
|
||||
* "$lt": 100,
|
||||
* "$gt": 10
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
if (
|
||||
fieldValue._key &&
|
||||
fieldValue._value &&
|
||||
parentConstraints &&
|
||||
parentFieldName
|
||||
) {
|
||||
delete parentConstraints[parentFieldName];
|
||||
parentConstraints[`${parentFieldName}.${fieldValue._key}`] = {
|
||||
...parentConstraints[`${parentFieldName}.${fieldValue._key}`],
|
||||
[parseMap[fieldName]]: fieldValue._value,
|
||||
};
|
||||
} else if (parseMap[fieldName]) {
|
||||
delete constraints[fieldName];
|
||||
fieldName = parseMap[fieldName];
|
||||
constraints[fieldName] = fieldValue;
|
||||
}
|
||||
switch (fieldName) {
|
||||
case '$point':
|
||||
case '$nearSphere':
|
||||
if (typeof fieldValue === 'object' && !fieldValue.__type) {
|
||||
fieldValue.__type = 'GeoPoint';
|
||||
}
|
||||
break;
|
||||
case '$box':
|
||||
if (
|
||||
typeof fieldValue === 'object' &&
|
||||
fieldValue.bottomLeft &&
|
||||
fieldValue.upperRight
|
||||
) {
|
||||
fieldValue = [
|
||||
{
|
||||
__type: 'GeoPoint',
|
||||
...fieldValue.bottomLeft,
|
||||
},
|
||||
{
|
||||
__type: 'GeoPoint',
|
||||
...fieldValue.upperRight,
|
||||
},
|
||||
];
|
||||
constraints[fieldName] = fieldValue;
|
||||
}
|
||||
break;
|
||||
case '$polygon':
|
||||
if (fieldValue instanceof Array) {
|
||||
fieldValue.forEach(geoPoint => {
|
||||
if (typeof geoPoint === 'object' && !geoPoint.__type) {
|
||||
geoPoint.__type = 'GeoPoint';
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
case '$centerSphere':
|
||||
if (
|
||||
typeof fieldValue === 'object' &&
|
||||
fieldValue.center &&
|
||||
fieldValue.distance
|
||||
) {
|
||||
fieldValue = [
|
||||
{
|
||||
__type: 'GeoPoint',
|
||||
...fieldValue.center,
|
||||
},
|
||||
fieldValue.distance,
|
||||
];
|
||||
constraints[fieldName] = fieldValue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (typeof fieldValue === 'object') {
|
||||
transformToParse(fieldValue, fieldName, constraints);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const findObjects = async (
|
||||
className,
|
||||
where,
|
||||
@@ -224,7 +76,7 @@ const findObjects = async (
|
||||
where = {};
|
||||
}
|
||||
|
||||
transformToParse(where);
|
||||
transformQueryInputToParse(where);
|
||||
|
||||
const options = {};
|
||||
|
||||
@@ -282,118 +134,131 @@ const findObjects = async (
|
||||
};
|
||||
|
||||
const load = parseGraphQLSchema => {
|
||||
parseGraphQLSchema.graphQLObjectsQueries.get = {
|
||||
description:
|
||||
'The get query can be used to get an object of a certain class by its objectId.',
|
||||
args: {
|
||||
className: defaultGraphQLTypes.CLASS_NAME_ATT,
|
||||
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
||||
keys: defaultGraphQLTypes.KEYS_ATT,
|
||||
include: defaultGraphQLTypes.INCLUDE_ATT,
|
||||
readPreference: defaultGraphQLTypes.READ_PREFERENCE_ATT,
|
||||
includeReadPreference: defaultGraphQLTypes.INCLUDE_READ_PREFERENCE_ATT,
|
||||
},
|
||||
type: new GraphQLNonNull(defaultGraphQLTypes.OBJECT),
|
||||
async resolve(_source, args, context) {
|
||||
try {
|
||||
const {
|
||||
className,
|
||||
objectId,
|
||||
keys,
|
||||
include,
|
||||
readPreference,
|
||||
includeReadPreference,
|
||||
} = args;
|
||||
const { config, auth, info } = context;
|
||||
|
||||
return await getObject(
|
||||
className,
|
||||
objectId,
|
||||
keys,
|
||||
include,
|
||||
readPreference,
|
||||
includeReadPreference,
|
||||
config,
|
||||
auth,
|
||||
info
|
||||
);
|
||||
} catch (e) {
|
||||
parseGraphQLSchema.handleError(e);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
parseGraphQLSchema.graphQLObjectsQueries.find = {
|
||||
description:
|
||||
'The find query can be used to find objects of a certain class.',
|
||||
args: {
|
||||
className: defaultGraphQLTypes.CLASS_NAME_ATT,
|
||||
where: defaultGraphQLTypes.WHERE_ATT,
|
||||
order: {
|
||||
description:
|
||||
'This is the order in which the objects should be returned',
|
||||
type: GraphQLString,
|
||||
parseGraphQLSchema.addGraphQLObjectQuery(
|
||||
'get',
|
||||
{
|
||||
description:
|
||||
'The get query can be used to get an object of a certain class by its objectId.',
|
||||
args: {
|
||||
className: defaultGraphQLTypes.CLASS_NAME_ATT,
|
||||
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
||||
keys: defaultGraphQLTypes.KEYS_ATT,
|
||||
include: defaultGraphQLTypes.INCLUDE_ATT,
|
||||
readPreference: defaultGraphQLTypes.READ_PREFERENCE_ATT,
|
||||
includeReadPreference: defaultGraphQLTypes.INCLUDE_READ_PREFERENCE_ATT,
|
||||
},
|
||||
skip: defaultGraphQLTypes.SKIP_ATT,
|
||||
limit: defaultGraphQLTypes.LIMIT_ATT,
|
||||
keys: defaultGraphQLTypes.KEYS_ATT,
|
||||
include: defaultGraphQLTypes.INCLUDE_ATT,
|
||||
includeAll: {
|
||||
description: 'All pointers will be returned',
|
||||
type: GraphQLBoolean,
|
||||
},
|
||||
readPreference: defaultGraphQLTypes.READ_PREFERENCE_ATT,
|
||||
includeReadPreference: defaultGraphQLTypes.INCLUDE_READ_PREFERENCE_ATT,
|
||||
subqueryReadPreference: defaultGraphQLTypes.SUBQUERY_READ_PREFERENCE_ATT,
|
||||
},
|
||||
type: new GraphQLNonNull(defaultGraphQLTypes.FIND_RESULT),
|
||||
async resolve(_source, args, context, queryInfo) {
|
||||
try {
|
||||
const {
|
||||
className,
|
||||
where,
|
||||
order,
|
||||
skip,
|
||||
limit,
|
||||
keys,
|
||||
include,
|
||||
includeAll,
|
||||
readPreference,
|
||||
includeReadPreference,
|
||||
subqueryReadPreference,
|
||||
} = args;
|
||||
const { config, auth, info } = context;
|
||||
const selectedFields = getFieldNames(queryInfo);
|
||||
type: new GraphQLNonNull(defaultGraphQLTypes.OBJECT),
|
||||
async resolve(_source, args, context) {
|
||||
try {
|
||||
const {
|
||||
className,
|
||||
objectId,
|
||||
keys,
|
||||
include,
|
||||
readPreference,
|
||||
includeReadPreference,
|
||||
} = args;
|
||||
|
||||
return await findObjects(
|
||||
className,
|
||||
where,
|
||||
order,
|
||||
skip,
|
||||
limit,
|
||||
keys,
|
||||
include,
|
||||
includeAll,
|
||||
readPreference,
|
||||
includeReadPreference,
|
||||
subqueryReadPreference,
|
||||
config,
|
||||
auth,
|
||||
info,
|
||||
selectedFields
|
||||
);
|
||||
} catch (e) {
|
||||
parseGraphQLSchema.handleError(e);
|
||||
}
|
||||
const { config, auth, info } = context;
|
||||
|
||||
return await getObject(
|
||||
className,
|
||||
objectId,
|
||||
keys,
|
||||
include,
|
||||
readPreference,
|
||||
includeReadPreference,
|
||||
config,
|
||||
auth,
|
||||
info
|
||||
);
|
||||
} catch (e) {
|
||||
parseGraphQLSchema.handleError(e);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
true,
|
||||
true
|
||||
);
|
||||
|
||||
parseGraphQLSchema.addGraphQLObjectQuery(
|
||||
'find',
|
||||
{
|
||||
description:
|
||||
'The find query can be used to find objects of a certain class.',
|
||||
args: {
|
||||
className: defaultGraphQLTypes.CLASS_NAME_ATT,
|
||||
where: defaultGraphQLTypes.WHERE_ATT,
|
||||
order: {
|
||||
description:
|
||||
'This is the order in which the objects should be returned',
|
||||
type: GraphQLString,
|
||||
},
|
||||
skip: defaultGraphQLTypes.SKIP_ATT,
|
||||
limit: defaultGraphQLTypes.LIMIT_ATT,
|
||||
keys: defaultGraphQLTypes.KEYS_ATT,
|
||||
include: defaultGraphQLTypes.INCLUDE_ATT,
|
||||
includeAll: {
|
||||
description: 'All pointers will be returned',
|
||||
type: GraphQLBoolean,
|
||||
},
|
||||
readPreference: defaultGraphQLTypes.READ_PREFERENCE_ATT,
|
||||
includeReadPreference: defaultGraphQLTypes.INCLUDE_READ_PREFERENCE_ATT,
|
||||
subqueryReadPreference:
|
||||
defaultGraphQLTypes.SUBQUERY_READ_PREFERENCE_ATT,
|
||||
},
|
||||
type: new GraphQLNonNull(defaultGraphQLTypes.FIND_RESULT),
|
||||
async resolve(_source, args, context, queryInfo) {
|
||||
try {
|
||||
const {
|
||||
className,
|
||||
where,
|
||||
order,
|
||||
skip,
|
||||
limit,
|
||||
keys,
|
||||
include,
|
||||
includeAll,
|
||||
readPreference,
|
||||
includeReadPreference,
|
||||
subqueryReadPreference,
|
||||
} = args;
|
||||
|
||||
const { config, auth, info } = context;
|
||||
const selectedFields = getFieldNames(queryInfo);
|
||||
|
||||
return await findObjects(
|
||||
className,
|
||||
where,
|
||||
order,
|
||||
skip,
|
||||
limit,
|
||||
keys,
|
||||
include,
|
||||
includeAll,
|
||||
readPreference,
|
||||
includeReadPreference,
|
||||
subqueryReadPreference,
|
||||
config,
|
||||
auth,
|
||||
info,
|
||||
selectedFields
|
||||
);
|
||||
} catch (e) {
|
||||
parseGraphQLSchema.handleError(e);
|
||||
}
|
||||
},
|
||||
},
|
||||
true,
|
||||
true
|
||||
);
|
||||
|
||||
const objectsQuery = new GraphQLObjectType({
|
||||
name: 'ObjectsQuery',
|
||||
description: 'ObjectsQuery is the top level type for objects queries.',
|
||||
fields: parseGraphQLSchema.graphQLObjectsQueries,
|
||||
});
|
||||
parseGraphQLSchema.graphQLTypes.push(objectsQuery);
|
||||
parseGraphQLSchema.addGraphQLType(objectsQuery, true, true);
|
||||
|
||||
parseGraphQLSchema.graphQLQueries.objects = {
|
||||
description: 'This is the top level for objects queries.',
|
||||
|
||||
Reference in New Issue
Block a user