Skip to content

Commit 809ea1a

Browse files
committed
Transform className on the fly
1 parent ef14ca5 commit 809ea1a

File tree

7 files changed

+232
-182
lines changed

7 files changed

+232
-182
lines changed

src/GraphQL/loaders/objectsMutations.js

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,14 @@
11
import { GraphQLNonNull, GraphQLBoolean, GraphQLObjectType } from 'graphql';
22
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
33
import rest from '../../rest';
4-
5-
const parseMap = {
6-
_op: '__op',
7-
};
8-
9-
const transformToParse = fields => {
10-
if (!fields || typeof fields !== 'object') {
11-
return;
12-
}
13-
Object.keys(fields).forEach(fieldName => {
14-
const fieldValue = fields[fieldName];
15-
if (parseMap[fieldName]) {
16-
delete fields[fieldName];
17-
fields[parseMap[fieldName]] = fieldValue;
18-
}
19-
if (typeof fieldValue === 'object') {
20-
transformToParse(fieldValue);
21-
}
22-
});
23-
};
4+
import { transformMutationInputToParse } from '../transformes/mutation';
5+
import { transformClassNameToParse } from '../transformers/className';
246

257
const createObject = async (className, fields, config, auth, info) => {
268
if (!fields) {
279
fields = {};
2810
}
2911

30-
transformToParse(fields);
31-
3212
return (await rest.create(config, auth, className, fields, info.clientSDK))
3313
.response;
3414
};
@@ -45,7 +25,7 @@ const updateObject = async (
4525
fields = {};
4626
}
4727

48-
transformToParse(fields);
28+
transformMutationInputToParse(fields);
4929

5030
return (await rest.update(
5131
config,
@@ -73,8 +53,9 @@ const load = parseGraphQLSchema => {
7353
type: new GraphQLNonNull(defaultGraphQLTypes.CREATE_RESULT),
7454
async resolve(_source, args, context) {
7555
try {
76-
const { className, fields } = args;
56+
const { className: graphQLClassName, fields } = args;
7757
const { config, auth, info } = context;
58+
const className = transformClassNameToParse(graphQLClassName);
7859

7960
return await createObject(className, fields, config, auth, info);
8061
} catch (e) {
@@ -94,8 +75,9 @@ const load = parseGraphQLSchema => {
9475
type: new GraphQLNonNull(defaultGraphQLTypes.UPDATE_RESULT),
9576
async resolve(_source, args, context) {
9677
try {
97-
const { className, objectId, fields } = args;
78+
const { className: graphQLClassName, objectId, fields } = args;
9879
const { config, auth, info } = context;
80+
const className = transformClassNameToParse(graphQLClassName);
9981

10082
return await updateObject(
10183
className,
@@ -121,8 +103,9 @@ const load = parseGraphQLSchema => {
121103
type: new GraphQLNonNull(GraphQLBoolean),
122104
async resolve(_source, args, context) {
123105
try {
124-
const { className, objectId } = args;
106+
const { className: graphQLClassName, objectId } = args;
125107
const { config, auth, info } = context;
108+
const className = transformClassNameToParse(graphQLClassName);
126109

127110
return await deleteObject(className, objectId, config, auth, info);
128111
} catch (e) {

src/GraphQL/loaders/objectsQueries.js

Lines changed: 10 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import getFieldNames from 'graphql-list-fields';
88
import Parse from 'parse/node';
99
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
1010
import rest from '../../rest';
11+
import { transformQueryInputToParse } from '../transformers/query';
12+
import { transformClassNameToParse } from '../transformers/className';
1113

1214
const getObject = async (
1315
className,
@@ -54,155 +56,6 @@ const getObject = async (
5456
return response.results[0];
5557
};
5658

57-
const parseMap = {
58-
_or: '$or',
59-
_and: '$and',
60-
_nor: '$nor',
61-
_relatedTo: '$relatedTo',
62-
_eq: '$eq',
63-
_ne: '$ne',
64-
_lt: '$lt',
65-
_lte: '$lte',
66-
_gt: '$gt',
67-
_gte: '$gte',
68-
_in: '$in',
69-
_nin: '$nin',
70-
_exists: '$exists',
71-
_select: '$select',
72-
_dontSelect: '$dontSelect',
73-
_inQuery: '$inQuery',
74-
_notInQuery: '$notInQuery',
75-
_containedBy: '$containedBy',
76-
_all: '$all',
77-
_regex: '$regex',
78-
_options: '$options',
79-
_text: '$text',
80-
_search: '$search',
81-
_term: '$term',
82-
_language: '$language',
83-
_caseSensitive: '$caseSensitive',
84-
_diacriticSensitive: '$diacriticSensitive',
85-
_nearSphere: '$nearSphere',
86-
_maxDistance: '$maxDistance',
87-
_maxDistanceInRadians: '$maxDistanceInRadians',
88-
_maxDistanceInMiles: '$maxDistanceInMiles',
89-
_maxDistanceInKilometers: '$maxDistanceInKilometers',
90-
_within: '$within',
91-
_box: '$box',
92-
_geoWithin: '$geoWithin',
93-
_polygon: '$polygon',
94-
_centerSphere: '$centerSphere',
95-
_geoIntersects: '$geoIntersects',
96-
_point: '$point',
97-
};
98-
99-
const transformToParse = (constraints, parentFieldName, parentConstraints) => {
100-
if (!constraints || typeof constraints !== 'object') {
101-
return;
102-
}
103-
Object.keys(constraints).forEach(fieldName => {
104-
let fieldValue = constraints[fieldName];
105-
106-
/**
107-
* If we have a key-value pair, we need to change the way the constraint is structured.
108-
*
109-
* Example:
110-
* From:
111-
* {
112-
* "someField": {
113-
* "_lt": {
114-
* "_key":"foo.bar",
115-
* "_value": 100
116-
* },
117-
* "_gt": {
118-
* "_key":"foo.bar",
119-
* "_value": 10
120-
* }
121-
* }
122-
* }
123-
*
124-
* To:
125-
* {
126-
* "someField.foo.bar": {
127-
* "$lt": 100,
128-
* "$gt": 10
129-
* }
130-
* }
131-
*/
132-
if (
133-
fieldValue._key &&
134-
fieldValue._value &&
135-
parentConstraints &&
136-
parentFieldName
137-
) {
138-
delete parentConstraints[parentFieldName];
139-
parentConstraints[`${parentFieldName}.${fieldValue._key}`] = {
140-
...parentConstraints[`${parentFieldName}.${fieldValue._key}`],
141-
[parseMap[fieldName]]: fieldValue._value,
142-
};
143-
} else if (parseMap[fieldName]) {
144-
delete constraints[fieldName];
145-
fieldName = parseMap[fieldName];
146-
constraints[fieldName] = fieldValue;
147-
}
148-
switch (fieldName) {
149-
case '$point':
150-
case '$nearSphere':
151-
if (typeof fieldValue === 'object' && !fieldValue.__type) {
152-
fieldValue.__type = 'GeoPoint';
153-
}
154-
break;
155-
case '$box':
156-
if (
157-
typeof fieldValue === 'object' &&
158-
fieldValue.bottomLeft &&
159-
fieldValue.upperRight
160-
) {
161-
fieldValue = [
162-
{
163-
__type: 'GeoPoint',
164-
...fieldValue.bottomLeft,
165-
},
166-
{
167-
__type: 'GeoPoint',
168-
...fieldValue.upperRight,
169-
},
170-
];
171-
constraints[fieldName] = fieldValue;
172-
}
173-
break;
174-
case '$polygon':
175-
if (fieldValue instanceof Array) {
176-
fieldValue.forEach(geoPoint => {
177-
if (typeof geoPoint === 'object' && !geoPoint.__type) {
178-
geoPoint.__type = 'GeoPoint';
179-
}
180-
});
181-
}
182-
break;
183-
case '$centerSphere':
184-
if (
185-
typeof fieldValue === 'object' &&
186-
fieldValue.center &&
187-
fieldValue.distance
188-
) {
189-
fieldValue = [
190-
{
191-
__type: 'GeoPoint',
192-
...fieldValue.center,
193-
},
194-
fieldValue.distance,
195-
];
196-
constraints[fieldName] = fieldValue;
197-
}
198-
break;
199-
}
200-
if (typeof fieldValue === 'object') {
201-
transformToParse(fieldValue, fieldName, constraints);
202-
}
203-
});
204-
};
205-
20659
const findObjects = async (
20760
className,
20861
where,
@@ -220,11 +73,12 @@ const findObjects = async (
22073
info,
22174
selectedFields
22275
) => {
76+
className = transformClassNameToParse(className);
22377
if (!where) {
22478
where = {};
22579
}
22680

227-
transformToParse(where);
81+
transformQueryInputToParse(where);
22882

22983
const options = {};
23084

@@ -297,13 +151,15 @@ const load = parseGraphQLSchema => {
297151
async resolve(_source, args, context) {
298152
try {
299153
const {
300-
className,
154+
className: graphQLClassName,
301155
objectId,
302156
keys,
303157
include,
304158
readPreference,
305159
includeReadPreference,
306160
} = args;
161+
162+
const className = transformClassNameToParse(graphQLClassName);
307163
const { config, auth, info } = context;
308164

309165
return await getObject(
@@ -350,7 +206,7 @@ const load = parseGraphQLSchema => {
350206
async resolve(_source, args, context, queryInfo) {
351207
try {
352208
const {
353-
className,
209+
className: graphQLClassName,
354210
where,
355211
order,
356212
skip,
@@ -362,6 +218,8 @@ const load = parseGraphQLSchema => {
362218
includeReadPreference,
363219
subqueryReadPreference,
364220
} = args;
221+
222+
const className = transformClassNameToParse(graphQLClassName);
365223
const { config, auth, info } = context;
366224
const selectedFields = getFieldNames(queryInfo);
367225

src/GraphQL/loaders/parseClassMutations.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { GraphQLNonNull, GraphQLBoolean } from 'graphql';
22
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
33
import * as objectsMutations from './objectsMutations';
44
import { ParseGraphQLClassConfig } from '../../Controllers/ParseGraphQLController';
5+
import { transformClassNameToGraphQL } from '../transformers/className';
56

67
const getParseClassMutationConfig = function(
78
parseClassConfig: ?ParseGraphQLClassConfig
@@ -14,7 +15,8 @@ const load = function(
1415
parseClass,
1516
parseClassConfig: ?ParseGraphQLClassConfig
1617
) {
17-
const { className } = parseClass;
18+
const className = transformClassNameToGraphQL(parseClass.className);
19+
1820
const {
1921
create: isCreateEnabled = true,
2022
update: isUpdateEnabled = true,

src/GraphQL/loaders/parseClassQueries.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as defaultGraphQLTypes from './defaultGraphQLTypes';
44
import * as objectsQueries from './objectsQueries';
55
import * as parseClassTypes from './parseClassTypes';
66
import { ParseGraphQLClassConfig } from '../../Controllers/ParseGraphQLController';
7+
import { transformClassNameToGraphQL } from '../transformers/className';
78

89
const getParseClassQueryConfig = function(
910
parseClassConfig: ?ParseGraphQLClassConfig
@@ -16,7 +17,8 @@ const load = function(
1617
parseClass,
1718
parseClassConfig: ?ParseGraphQLClassConfig
1819
) {
19-
const { className } = parseClass;
20+
const className = transformClassNameToGraphQL(parseClass.className);
21+
2022
const {
2123
get: isGetEnabled = true,
2224
find: isFindEnabled = true,
@@ -29,7 +31,8 @@ const load = function(
2931
} = parseGraphQLSchema.parseClassTypes[className];
3032

3133
if (isGetEnabled) {
32-
const getGraphQLQueryName = `get${className}`;
34+
const getGraphQLQueryName =
35+
className.charAt(0).toUpperCase() + className.slice(1);
3336
parseGraphQLSchema.graphQLObjectsQueries[getGraphQLQueryName] = {
3437
description: `The ${getGraphQLQueryName} query can be used to get an object of the ${className} class by its id.`,
3538
args: {
@@ -67,7 +70,8 @@ const load = function(
6770
}
6871

6972
if (isFindEnabled) {
70-
const findGraphQLQueryName = `find${className}`;
73+
const findGraphQLQueryName =
74+
className.charAt(0).toUpperCase() + className.slice(1) + 's';
7175
parseGraphQLSchema.graphQLObjectsQueries[findGraphQLQueryName] = {
7276
description: `The ${findGraphQLQueryName} query can be used to find objects of the ${className} class.`,
7377
args: classGraphQLFindArgs,

src/GraphQL/tranformers/className.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import logger from '../logger';
2+
3+
const parseMap = {
4+
Role: '_Role',
5+
User: '_User',
6+
Files: 'Files',
7+
};
8+
const reverseParseMap = {};
9+
// Dynamically fill reverseParseMap based on parseMap
10+
Object.keys(parseMap).forEach(key => (reverseParseMap[parseMap[key]] = key));
11+
12+
const transformClassNameToParse = className => {
13+
if (reverseParseMap[className])
14+
logger.error(
15+
`Native Parse Class collision detected, please change the name of your class ${className}`
16+
);
17+
parseMap[className] ? parseMap[className] : className;
18+
};
19+
20+
const transformClassNameToGraphQL = className => {
21+
if (parseMap[className])
22+
logger.error(
23+
`Native Parse Class collision detected, please change the name of your class ${className}`
24+
);
25+
reverseParseMap[className] ? reverseParseMap[className] : className;
26+
};
27+
28+
export { transformClassNameToGraphQL, transformClassNameToParse };

src/GraphQL/tranformers/mutation.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const parseMap = {
2+
_op: '__op',
3+
};
4+
5+
const transformMutationInputToParse = fields => {
6+
if (!fields || typeof fields !== 'object') {
7+
return;
8+
}
9+
Object.keys(fields).forEach(fieldName => {
10+
const fieldValue = fields[fieldName];
11+
if (parseMap[fieldName]) {
12+
delete fields[fieldName];
13+
fields[parseMap[fieldName]] = fieldValue;
14+
}
15+
if (typeof fieldValue === 'object') {
16+
transformMutationInputToParse(fieldValue);
17+
}
18+
});
19+
};
20+
21+
export { transformMutationInputToParse };

0 commit comments

Comments
 (0)