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
27
package-lock.json
generated
27
package-lock.json
generated
@@ -1214,11 +1214,21 @@
|
|||||||
"integrity": "sha512-J+YW09/vZRuK2/04SykW31xgMTtA/XTm4mSaLoJ79EW31SWstNUzfti9seu0MdWRafgdmRzUn+qCJ/MqXvQZRg==",
|
"integrity": "sha512-J+YW09/vZRuK2/04SykW31xgMTtA/XTm4mSaLoJ79EW31SWstNUzfti9seu0MdWRafgdmRzUn+qCJ/MqXvQZRg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@parse/node-gcm": "^1.0.0",
|
"@parse/node-gcm": "^1.0.0",
|
||||||
"apn": "github:parse-community/node-apn#semver:^v3.0.2-parse",
|
"apn": "github:parse-community/node-apn#3bc4fb20b68d53d3f3b7057cadf5a37ba6a45dc0",
|
||||||
"npmlog": "^4.0.2",
|
"npmlog": "^4.0.2",
|
||||||
"parse": "^1.11.1"
|
"parse": "^1.11.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"apn": {
|
||||||
|
"version": "github:parse-community/node-apn#3bc4fb20b68d53d3f3b7057cadf5a37ba6a45dc0",
|
||||||
|
"from": "github:parse-community/node-apn#3bc4fb20b68d53d3f3b7057cadf5a37ba6a45dc0",
|
||||||
|
"requires": {
|
||||||
|
"debug": "^3.1.0",
|
||||||
|
"jsonwebtoken": "^8.1.0",
|
||||||
|
"node-forge": "^0.7.1",
|
||||||
|
"verror": "^1.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"parse": {
|
"parse": {
|
||||||
"version": "1.11.1",
|
"version": "1.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/parse/-/parse-1.11.1.tgz",
|
"resolved": "https://registry.npmjs.org/parse/-/parse-1.11.1.tgz",
|
||||||
@@ -1668,16 +1678,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"apn": {
|
|
||||||
"version": "github:parse-community/node-apn#3bc4fb20b68d53d3f3b7057cadf5a37ba6a45dc0",
|
|
||||||
"from": "github:parse-community/node-apn#semver:^v3.0.2-parse",
|
|
||||||
"requires": {
|
|
||||||
"debug": "^3.1.0",
|
|
||||||
"jsonwebtoken": "^8.1.0",
|
|
||||||
"node-forge": "^0.7.1",
|
|
||||||
"verror": "^1.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"apollo-cache": {
|
"apollo-cache": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.3.2.tgz",
|
||||||
@@ -9075,6 +9075,11 @@
|
|||||||
"semver-compare": "^1.0.0"
|
"semver-compare": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"pluralize": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="
|
||||||
|
},
|
||||||
"posix-character-classes": {
|
"posix-character-classes": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
"node-rsa": "1.0.5",
|
"node-rsa": "1.0.5",
|
||||||
"parse": "2.6.0",
|
"parse": "2.6.0",
|
||||||
"pg-promise": "9.0.1",
|
"pg-promise": "9.0.1",
|
||||||
|
"pluralize": "^8.0.0",
|
||||||
"redis": "2.8.0",
|
"redis": "2.8.0",
|
||||||
"semver": "6.3.0",
|
"semver": "6.3.0",
|
||||||
"subscriptions-transport-ws": "0.9.16",
|
"subscriptions-transport-ws": "0.9.16",
|
||||||
|
|||||||
11
spec/ParseGraphQLClassNameTransformer.spec.js
Normal file
11
spec/ParseGraphQLClassNameTransformer.spec.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
const {
|
||||||
|
transformClassNameToGraphQL,
|
||||||
|
} = require('../lib/GraphQL/transformers/className');
|
||||||
|
|
||||||
|
describe('transformClassNameToGraphQL', () => {
|
||||||
|
it('should remove starting _ and tansform first letter to upper case', () => {
|
||||||
|
expect(
|
||||||
|
['_User', '_user', 'User', 'user'].map(transformClassNameToGraphQL)
|
||||||
|
).toEqual(['User', 'User', 'User', 'User']);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
const { GraphQLObjectType } = require('graphql');
|
||||||
const defaultLogger = require('../lib/logger').default;
|
const defaultLogger = require('../lib/logger').default;
|
||||||
const { ParseGraphQLSchema } = require('../lib/GraphQL/ParseGraphQLSchema');
|
const { ParseGraphQLSchema } = require('../lib/GraphQL/ParseGraphQLSchema');
|
||||||
|
|
||||||
@@ -118,4 +119,428 @@ describe('ParseGraphQLSchema', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('addGraphQLType', () => {
|
||||||
|
it('should not load and warn duplicated types', async () => {
|
||||||
|
let logged = false;
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: {
|
||||||
|
warn: message => {
|
||||||
|
logged = true;
|
||||||
|
expect(message).toEqual(
|
||||||
|
'Type SomeClass could not be added to the auto schema because it collided with an existing type.'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await parseGraphQLSchema.load();
|
||||||
|
const type = new GraphQLObjectType({ name: 'SomeClass' });
|
||||||
|
expect(parseGraphQLSchema.addGraphQLType(type)).toBe(type);
|
||||||
|
expect(parseGraphQLSchema.graphQLTypes).toContain(type);
|
||||||
|
expect(
|
||||||
|
parseGraphQLSchema.addGraphQLType(
|
||||||
|
new GraphQLObjectType({ name: 'SomeClass' })
|
||||||
|
)
|
||||||
|
).toBeUndefined();
|
||||||
|
expect(logged).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error when required', async () => {
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: {
|
||||||
|
warn: () => {
|
||||||
|
fail('Should not warn');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await parseGraphQLSchema.load();
|
||||||
|
const type = new GraphQLObjectType({ name: 'SomeClass' });
|
||||||
|
expect(parseGraphQLSchema.addGraphQLType(type, true)).toBe(type);
|
||||||
|
expect(parseGraphQLSchema.graphQLTypes).toContain(type);
|
||||||
|
expect(() =>
|
||||||
|
parseGraphQLSchema.addGraphQLType(
|
||||||
|
new GraphQLObjectType({ name: 'SomeClass' }),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
).toThrowError(
|
||||||
|
'Type SomeClass could not be added to the auto schema because it collided with an existing type.'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should warn reserved name collision', async () => {
|
||||||
|
let logged = false;
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: {
|
||||||
|
warn: message => {
|
||||||
|
logged = true;
|
||||||
|
expect(message).toEqual(
|
||||||
|
'Type String could not be added to the auto schema because it collided with an existing type.'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await parseGraphQLSchema.load();
|
||||||
|
expect(
|
||||||
|
parseGraphQLSchema.addGraphQLType(
|
||||||
|
new GraphQLObjectType({ name: 'String' })
|
||||||
|
)
|
||||||
|
).toBeUndefined();
|
||||||
|
expect(logged).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should ignore collision when necessary', async () => {
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: {
|
||||||
|
warn: () => {
|
||||||
|
fail('Should not warn');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await parseGraphQLSchema.load();
|
||||||
|
const type = new GraphQLObjectType({ name: 'String' });
|
||||||
|
expect(parseGraphQLSchema.addGraphQLType(type, true, true)).toBe(type);
|
||||||
|
expect(parseGraphQLSchema.graphQLTypes).toContain(type);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('addGraphQLObjectQuery', () => {
|
||||||
|
it('should not load and warn duplicated queries', async () => {
|
||||||
|
let logged = false;
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: {
|
||||||
|
warn: message => {
|
||||||
|
logged = true;
|
||||||
|
expect(message).toEqual(
|
||||||
|
'Object query someClasses could not be added to the auto schema because it collided with an existing field.'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await parseGraphQLSchema.load();
|
||||||
|
const field = {};
|
||||||
|
expect(
|
||||||
|
parseGraphQLSchema.addGraphQLObjectQuery('someClasses', field)
|
||||||
|
).toBe(field);
|
||||||
|
expect(parseGraphQLSchema.graphQLObjectsQueries['someClasses']).toBe(
|
||||||
|
field
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
parseGraphQLSchema.addGraphQLObjectQuery('someClasses', {})
|
||||||
|
).toBeUndefined();
|
||||||
|
expect(logged).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error when required', async () => {
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: {
|
||||||
|
warn: () => {
|
||||||
|
fail('Should not warn');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await parseGraphQLSchema.load();
|
||||||
|
const field = {};
|
||||||
|
expect(
|
||||||
|
parseGraphQLSchema.addGraphQLObjectQuery('someClasses', field)
|
||||||
|
).toBe(field);
|
||||||
|
expect(parseGraphQLSchema.graphQLObjectsQueries['someClasses']).toBe(
|
||||||
|
field
|
||||||
|
);
|
||||||
|
expect(() =>
|
||||||
|
parseGraphQLSchema.addGraphQLObjectQuery('someClasses', {}, true)
|
||||||
|
).toThrowError(
|
||||||
|
'Object query someClasses could not be added to the auto schema because it collided with an existing field.'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should warn reserved name collision', async () => {
|
||||||
|
let logged = false;
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: {
|
||||||
|
warn: message => {
|
||||||
|
logged = true;
|
||||||
|
expect(message).toEqual(
|
||||||
|
'Object query get could not be added to the auto schema because it collided with an existing field.'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await parseGraphQLSchema.load();
|
||||||
|
expect(
|
||||||
|
parseGraphQLSchema.addGraphQLObjectQuery('get', {})
|
||||||
|
).toBeUndefined();
|
||||||
|
expect(logged).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should ignore collision when necessary', async () => {
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: {
|
||||||
|
warn: () => {
|
||||||
|
fail('Should not warn');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await parseGraphQLSchema.load();
|
||||||
|
delete parseGraphQLSchema.graphQLObjectsQueries.get;
|
||||||
|
const field = {};
|
||||||
|
expect(
|
||||||
|
parseGraphQLSchema.addGraphQLObjectQuery('get', field, true, true)
|
||||||
|
).toBe(field);
|
||||||
|
expect(parseGraphQLSchema.graphQLObjectsQueries['get']).toBe(field);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('addGraphQLObjectMutation', () => {
|
||||||
|
it('should not load and warn duplicated mutations', async () => {
|
||||||
|
let logged = false;
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: {
|
||||||
|
warn: message => {
|
||||||
|
logged = true;
|
||||||
|
expect(message).toEqual(
|
||||||
|
'Object mutation createSomeClass could not be added to the auto schema because it collided with an existing field.'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await parseGraphQLSchema.load();
|
||||||
|
const field = {};
|
||||||
|
expect(
|
||||||
|
parseGraphQLSchema.addGraphQLObjectMutation('createSomeClass', field)
|
||||||
|
).toBe(field);
|
||||||
|
expect(
|
||||||
|
parseGraphQLSchema.graphQLObjectsMutations['createSomeClass']
|
||||||
|
).toBe(field);
|
||||||
|
expect(
|
||||||
|
parseGraphQLSchema.addGraphQLObjectMutation('createSomeClass', {})
|
||||||
|
).toBeUndefined();
|
||||||
|
expect(logged).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error when required', async () => {
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: {
|
||||||
|
warn: () => {
|
||||||
|
fail('Should not warn');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await parseGraphQLSchema.load();
|
||||||
|
const field = {};
|
||||||
|
expect(
|
||||||
|
parseGraphQLSchema.addGraphQLObjectMutation('createSomeClass', field)
|
||||||
|
).toBe(field);
|
||||||
|
expect(
|
||||||
|
parseGraphQLSchema.graphQLObjectsMutations['createSomeClass']
|
||||||
|
).toBe(field);
|
||||||
|
expect(() =>
|
||||||
|
parseGraphQLSchema.addGraphQLObjectMutation('createSomeClass', {}, true)
|
||||||
|
).toThrowError(
|
||||||
|
'Object mutation createSomeClass could not be added to the auto schema because it collided with an existing field.'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should warn reserved name collision', async () => {
|
||||||
|
let logged = false;
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: {
|
||||||
|
warn: message => {
|
||||||
|
logged = true;
|
||||||
|
expect(message).toEqual(
|
||||||
|
'Object mutation create could not be added to the auto schema because it collided with an existing field.'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await parseGraphQLSchema.load();
|
||||||
|
expect(
|
||||||
|
parseGraphQLSchema.addGraphQLObjectMutation('create', {})
|
||||||
|
).toBeUndefined();
|
||||||
|
expect(logged).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should ignore collision when necessary', async () => {
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: {
|
||||||
|
warn: () => {
|
||||||
|
fail('Should not warn');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await parseGraphQLSchema.load();
|
||||||
|
delete parseGraphQLSchema.graphQLObjectsMutations.create;
|
||||||
|
const field = {};
|
||||||
|
expect(
|
||||||
|
parseGraphQLSchema.addGraphQLObjectMutation('create', field, true, true)
|
||||||
|
).toBe(field);
|
||||||
|
expect(parseGraphQLSchema.graphQLObjectsMutations['create']).toBe(field);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_getParseClassesWithConfig', () => {
|
||||||
|
it('should sort classes', () => {
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: {
|
||||||
|
warn: () => {
|
||||||
|
fail('Should not warn');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
parseGraphQLSchema
|
||||||
|
._getParseClassesWithConfig(
|
||||||
|
[
|
||||||
|
{ className: 'b' },
|
||||||
|
{ className: '_b' },
|
||||||
|
{ className: 'B' },
|
||||||
|
{ className: '_B' },
|
||||||
|
{ className: 'a' },
|
||||||
|
{ className: '_a' },
|
||||||
|
{ className: 'A' },
|
||||||
|
{ className: '_A' },
|
||||||
|
],
|
||||||
|
{
|
||||||
|
classConfigs: [],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.map(item => item[0])
|
||||||
|
).toEqual([
|
||||||
|
{ className: '_A' },
|
||||||
|
{ className: '_B' },
|
||||||
|
{ className: '_a' },
|
||||||
|
{ className: '_b' },
|
||||||
|
{ className: 'A' },
|
||||||
|
{ className: 'B' },
|
||||||
|
{ className: 'a' },
|
||||||
|
{ className: 'b' },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('name collision', () => {
|
||||||
|
it('should not generate duplicate types when colliding to default classes', async () => {
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: defaultLogger,
|
||||||
|
});
|
||||||
|
await parseGraphQLSchema.databaseController.schemaCache.clear();
|
||||||
|
const schema1 = await parseGraphQLSchema.load();
|
||||||
|
const types1 = parseGraphQLSchema.graphQLTypes;
|
||||||
|
const objectQueries1 = parseGraphQLSchema.graphQLObjectsQueries;
|
||||||
|
const objectMutations1 = parseGraphQLSchema.graphQLObjectsMutations;
|
||||||
|
const user = new Parse.Object('User');
|
||||||
|
await user.save();
|
||||||
|
await parseGraphQLSchema.databaseController.schemaCache.clear();
|
||||||
|
const schema2 = await parseGraphQLSchema.load();
|
||||||
|
const types2 = parseGraphQLSchema.graphQLTypes;
|
||||||
|
const objectQueries2 = parseGraphQLSchema.graphQLObjectsQueries;
|
||||||
|
const objectMutations2 = parseGraphQLSchema.graphQLObjectsMutations;
|
||||||
|
expect(schema1).not.toBe(schema2);
|
||||||
|
expect(types1).not.toBe(types2);
|
||||||
|
expect(types1.map(type => type.name).sort()).toEqual(
|
||||||
|
types2.map(type => type.name).sort()
|
||||||
|
);
|
||||||
|
expect(objectQueries1).not.toBe(objectQueries2);
|
||||||
|
expect(Object.keys(objectQueries1).sort()).toEqual(
|
||||||
|
Object.keys(objectQueries2).sort()
|
||||||
|
);
|
||||||
|
expect(objectMutations1).not.toBe(objectMutations2);
|
||||||
|
expect(Object.keys(objectMutations1).sort()).toEqual(
|
||||||
|
Object.keys(objectMutations2).sort()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not generate duplicate types when colliding the same name', async () => {
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: defaultLogger,
|
||||||
|
});
|
||||||
|
const car1 = new Parse.Object('Car');
|
||||||
|
await car1.save();
|
||||||
|
await parseGraphQLSchema.databaseController.schemaCache.clear();
|
||||||
|
const schema1 = await parseGraphQLSchema.load();
|
||||||
|
const types1 = parseGraphQLSchema.graphQLTypes;
|
||||||
|
const objectQueries1 = parseGraphQLSchema.graphQLObjectsQueries;
|
||||||
|
const objectMutations1 = parseGraphQLSchema.graphQLObjectsMutations;
|
||||||
|
const car2 = new Parse.Object('car');
|
||||||
|
await car2.save();
|
||||||
|
await parseGraphQLSchema.databaseController.schemaCache.clear();
|
||||||
|
const schema2 = await parseGraphQLSchema.load();
|
||||||
|
const types2 = parseGraphQLSchema.graphQLTypes;
|
||||||
|
const objectQueries2 = parseGraphQLSchema.graphQLObjectsQueries;
|
||||||
|
const objectMutations2 = parseGraphQLSchema.graphQLObjectsMutations;
|
||||||
|
expect(schema1).not.toBe(schema2);
|
||||||
|
expect(types1).not.toBe(types2);
|
||||||
|
expect(types1.map(type => type.name).sort()).toEqual(
|
||||||
|
types2.map(type => type.name).sort()
|
||||||
|
);
|
||||||
|
expect(objectQueries1).not.toBe(objectQueries2);
|
||||||
|
expect(Object.keys(objectQueries1).sort()).toEqual(
|
||||||
|
Object.keys(objectQueries2).sort()
|
||||||
|
);
|
||||||
|
expect(objectMutations1).not.toBe(objectMutations2);
|
||||||
|
expect(Object.keys(objectMutations1).sort()).toEqual(
|
||||||
|
Object.keys(objectMutations2).sort()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not generate duplicate queries when query name collide', async () => {
|
||||||
|
const parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
|
databaseController,
|
||||||
|
parseGraphQLController,
|
||||||
|
log: defaultLogger,
|
||||||
|
});
|
||||||
|
const car = new Parse.Object('Car');
|
||||||
|
await car.save();
|
||||||
|
await parseGraphQLSchema.databaseController.schemaCache.clear();
|
||||||
|
const schema1 = await parseGraphQLSchema.load();
|
||||||
|
const objectQueries1 = parseGraphQLSchema.graphQLObjectsQueries;
|
||||||
|
const objectMutations1 = parseGraphQLSchema.graphQLObjectsMutations;
|
||||||
|
const cars = new Parse.Object('cars');
|
||||||
|
await cars.save();
|
||||||
|
await parseGraphQLSchema.databaseController.schemaCache.clear();
|
||||||
|
const schema2 = await parseGraphQLSchema.load();
|
||||||
|
const objectQueries2 = parseGraphQLSchema.graphQLObjectsQueries;
|
||||||
|
const objectMutations2 = parseGraphQLSchema.graphQLObjectsMutations;
|
||||||
|
expect(schema1).not.toBe(schema2);
|
||||||
|
expect(objectQueries1).not.toBe(objectQueries2);
|
||||||
|
expect(Object.keys(objectQueries1).sort()).toEqual(
|
||||||
|
Object.keys(objectQueries2).sort()
|
||||||
|
);
|
||||||
|
expect(objectMutations1).not.toBe(objectMutations2);
|
||||||
|
expect(
|
||||||
|
Object.keys(objectMutations1)
|
||||||
|
.concat('createCars', 'updateCars', 'deleteCars')
|
||||||
|
.sort()
|
||||||
|
).toEqual(Object.keys(objectMutations2).sort());
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,29 @@ import DatabaseController from '../Controllers/DatabaseController';
|
|||||||
import { toGraphQLError } from './parseGraphQLUtils';
|
import { toGraphQLError } from './parseGraphQLUtils';
|
||||||
import * as schemaDirectives from './loaders/schemaDirectives';
|
import * as schemaDirectives from './loaders/schemaDirectives';
|
||||||
|
|
||||||
|
const RESERVED_GRAPHQL_TYPE_NAMES = [
|
||||||
|
'String',
|
||||||
|
'Boolean',
|
||||||
|
'Int',
|
||||||
|
'Float',
|
||||||
|
'ID',
|
||||||
|
'ArrayResult',
|
||||||
|
'Query',
|
||||||
|
'Mutation',
|
||||||
|
'Subscription',
|
||||||
|
'ObjectsQuery',
|
||||||
|
'UsersQuery',
|
||||||
|
'ObjectsMutation',
|
||||||
|
'FilesMutation',
|
||||||
|
'UsersMutation',
|
||||||
|
'FunctionsMutation',
|
||||||
|
'Viewer',
|
||||||
|
'SignUpFieldsInput',
|
||||||
|
'LogInFieldsInput',
|
||||||
|
];
|
||||||
|
const RESERVED_GRAPHQL_OBJECT_QUERY_NAMES = ['get', 'find'];
|
||||||
|
const RESERVED_GRAPHQL_OBJECT_MUTATION_NAMES = ['create', 'update', 'delete'];
|
||||||
|
|
||||||
class ParseGraphQLSchema {
|
class ParseGraphQLSchema {
|
||||||
databaseController: DatabaseController;
|
databaseController: DatabaseController;
|
||||||
parseGraphQLController: ParseGraphQLController;
|
parseGraphQLController: ParseGraphQLController;
|
||||||
@@ -60,7 +83,7 @@ class ParseGraphQLSchema {
|
|||||||
this.parseClassesString = parseClassesString;
|
this.parseClassesString = parseClassesString;
|
||||||
this.parseGraphQLConfig = parseGraphQLConfig;
|
this.parseGraphQLConfig = parseGraphQLConfig;
|
||||||
this.parseClassTypes = {};
|
this.parseClassTypes = {};
|
||||||
this.meType = null;
|
this.viewerType = null;
|
||||||
this.graphQLAutoSchema = null;
|
this.graphQLAutoSchema = null;
|
||||||
this.graphQLSchema = null;
|
this.graphQLSchema = null;
|
||||||
this.graphQLTypes = [];
|
this.graphQLTypes = [];
|
||||||
@@ -92,7 +115,7 @@ class ParseGraphQLSchema {
|
|||||||
description: 'Query is the top level type for queries.',
|
description: 'Query is the top level type for queries.',
|
||||||
fields: this.graphQLQueries,
|
fields: this.graphQLQueries,
|
||||||
});
|
});
|
||||||
this.graphQLTypes.push(graphQLQuery);
|
this.addGraphQLType(graphQLQuery, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
let graphQLMutation = undefined;
|
let graphQLMutation = undefined;
|
||||||
@@ -102,7 +125,7 @@ class ParseGraphQLSchema {
|
|||||||
description: 'Mutation is the top level type for mutations.',
|
description: 'Mutation is the top level type for mutations.',
|
||||||
fields: this.graphQLMutations,
|
fields: this.graphQLMutations,
|
||||||
});
|
});
|
||||||
this.graphQLTypes.push(graphQLMutation);
|
this.addGraphQLType(graphQLMutation, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
let graphQLSubscription = undefined;
|
let graphQLSubscription = undefined;
|
||||||
@@ -112,7 +135,7 @@ class ParseGraphQLSchema {
|
|||||||
description: 'Subscription is the top level type for subscriptions.',
|
description: 'Subscription is the top level type for subscriptions.',
|
||||||
fields: this.graphQLSubscriptions,
|
fields: this.graphQLSubscriptions,
|
||||||
});
|
});
|
||||||
this.graphQLTypes.push(graphQLSubscription);
|
this.addGraphQLType(graphQLSubscription, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.graphQLAutoSchema = new GraphQLSchema({
|
this.graphQLAutoSchema = new GraphQLSchema({
|
||||||
@@ -172,6 +195,66 @@ class ParseGraphQLSchema {
|
|||||||
return this.graphQLSchema;
|
return this.graphQLSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addGraphQLType(type, throwError = false, ignoreReserved = false) {
|
||||||
|
if (
|
||||||
|
(!ignoreReserved && RESERVED_GRAPHQL_TYPE_NAMES.includes(type.name)) ||
|
||||||
|
this.graphQLTypes.find(existingType => existingType.name === type.name)
|
||||||
|
) {
|
||||||
|
const message = `Type ${type.name} could not be added to the auto schema because it collided with an existing type.`;
|
||||||
|
if (throwError) {
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
this.log.warn(message);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
this.graphQLTypes.push(type);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
addGraphQLObjectQuery(
|
||||||
|
fieldName,
|
||||||
|
field,
|
||||||
|
throwError = false,
|
||||||
|
ignoreReserved = false
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
(!ignoreReserved &&
|
||||||
|
RESERVED_GRAPHQL_OBJECT_QUERY_NAMES.includes(fieldName)) ||
|
||||||
|
this.graphQLObjectsQueries[fieldName]
|
||||||
|
) {
|
||||||
|
const message = `Object query ${fieldName} could not be added to the auto schema because it collided with an existing field.`;
|
||||||
|
if (throwError) {
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
this.log.warn(message);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
this.graphQLObjectsQueries[fieldName] = field;
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
addGraphQLObjectMutation(
|
||||||
|
fieldName,
|
||||||
|
field,
|
||||||
|
throwError = false,
|
||||||
|
ignoreReserved = false
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
(!ignoreReserved &&
|
||||||
|
RESERVED_GRAPHQL_OBJECT_MUTATION_NAMES.includes(fieldName)) ||
|
||||||
|
this.graphQLObjectsMutations[fieldName]
|
||||||
|
) {
|
||||||
|
const message = `Object mutation ${fieldName} could not be added to the auto schema because it collided with an existing field.`;
|
||||||
|
if (throwError) {
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
this.log.warn(message);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
this.graphQLObjectsMutations[fieldName] = field;
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
handleError(error) {
|
handleError(error) {
|
||||||
if (error instanceof Parse.Error) {
|
if (error instanceof Parse.Error) {
|
||||||
this.log.error('Parse error: ', error);
|
this.log.error('Parse error: ', error);
|
||||||
@@ -238,7 +321,32 @@ class ParseGraphQLSchema {
|
|||||||
parseGraphQLConfig: ParseGraphQLConfig
|
parseGraphQLConfig: ParseGraphQLConfig
|
||||||
) {
|
) {
|
||||||
const { classConfigs } = parseGraphQLConfig;
|
const { classConfigs } = parseGraphQLConfig;
|
||||||
return parseClasses.map(parseClass => {
|
|
||||||
|
// Make sures that the default classes and classes that
|
||||||
|
// starts with capitalized letter will be generated first.
|
||||||
|
const sortClasses = (a, b) => {
|
||||||
|
a = a.className;
|
||||||
|
b = b.className;
|
||||||
|
if (a[0] === '_') {
|
||||||
|
if (b[0] !== '_') {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (b[0] === '_') {
|
||||||
|
if (a[0] !== '_') {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (a === b) {
|
||||||
|
return 0;
|
||||||
|
} else if (a < b) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return parseClasses.sort(sortClasses).map(parseClass => {
|
||||||
let parseClassConfig;
|
let parseClassConfig;
|
||||||
if (classConfigs) {
|
if (classConfigs) {
|
||||||
parseClassConfig = classConfigs.find(
|
parseClassConfig = classConfigs.find(
|
||||||
|
|||||||
@@ -25,25 +25,31 @@ class ParseGraphQLServer {
|
|||||||
}
|
}
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.parseGraphQLController = this.parseServer.config.parseGraphQLController;
|
this.parseGraphQLController = this.parseServer.config.parseGraphQLController;
|
||||||
|
this.log =
|
||||||
|
(this.parseServer.config && this.parseServer.config.loggerController) ||
|
||||||
|
defaultLogger;
|
||||||
this.parseGraphQLSchema = new ParseGraphQLSchema({
|
this.parseGraphQLSchema = new ParseGraphQLSchema({
|
||||||
parseGraphQLController: this.parseGraphQLController,
|
parseGraphQLController: this.parseGraphQLController,
|
||||||
databaseController: this.parseServer.config.databaseController,
|
databaseController: this.parseServer.config.databaseController,
|
||||||
log:
|
log: this.log,
|
||||||
(this.parseServer.config && this.parseServer.config.loggerController) ||
|
|
||||||
defaultLogger,
|
|
||||||
graphQLCustomTypeDefs: this.config.graphQLCustomTypeDefs,
|
graphQLCustomTypeDefs: this.config.graphQLCustomTypeDefs,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getGraphQLOptions(req) {
|
async _getGraphQLOptions(req) {
|
||||||
return {
|
try {
|
||||||
schema: await this.parseGraphQLSchema.load(),
|
return {
|
||||||
context: {
|
schema: await this.parseGraphQLSchema.load(),
|
||||||
info: req.info,
|
context: {
|
||||||
config: req.config,
|
info: req.info,
|
||||||
auth: req.auth,
|
config: req.config,
|
||||||
},
|
auth: req.auth,
|
||||||
};
|
},
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
this.log.error(e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyGraphQL(app) {
|
applyGraphQL(app) {
|
||||||
|
|||||||
@@ -377,24 +377,24 @@ const GEO_POINT_FIELDS = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const GEO_POINT = new GraphQLInputObjectType({
|
const GEO_POINT_INPUT = new GraphQLInputObjectType({
|
||||||
|
name: 'GeoPointInput',
|
||||||
|
description:
|
||||||
|
'The GeoPointInput type is used in operations that involve inputting fields of type geo point.',
|
||||||
|
fields: GEO_POINT_FIELDS,
|
||||||
|
});
|
||||||
|
|
||||||
|
const GEO_POINT = new GraphQLObjectType({
|
||||||
name: 'GeoPoint',
|
name: 'GeoPoint',
|
||||||
description:
|
description:
|
||||||
'The GeoPoint input type is used in operations that involve inputting fields of type geo point.',
|
'The GeoPoint object type is used to return the information about geo point fields.',
|
||||||
fields: GEO_POINT_FIELDS,
|
fields: GEO_POINT_FIELDS,
|
||||||
});
|
});
|
||||||
|
|
||||||
const GEO_POINT_INFO = new GraphQLObjectType({
|
const POLYGON_INPUT = new GraphQLList(new GraphQLNonNull(GEO_POINT_INPUT));
|
||||||
name: 'GeoPointInfo',
|
|
||||||
description:
|
|
||||||
'The GeoPointInfo object type is used to return the information about geo points.',
|
|
||||||
fields: GEO_POINT_FIELDS,
|
|
||||||
});
|
|
||||||
|
|
||||||
const POLYGON = new GraphQLList(new GraphQLNonNull(GEO_POINT));
|
const POLYGON = new GraphQLList(new GraphQLNonNull(GEO_POINT));
|
||||||
|
|
||||||
const POLYGON_INFO = new GraphQLList(new GraphQLNonNull(GEO_POINT_INFO));
|
|
||||||
|
|
||||||
const RELATION_OP = new GraphQLEnumType({
|
const RELATION_OP = new GraphQLEnumType({
|
||||||
name: 'RelationOp',
|
name: 'RelationOp',
|
||||||
description:
|
description:
|
||||||
@@ -542,10 +542,10 @@ const COUNT_ATT = {
|
|||||||
type: new GraphQLNonNull(GraphQLInt),
|
type: new GraphQLNonNull(GraphQLInt),
|
||||||
};
|
};
|
||||||
|
|
||||||
const SUBQUERY = new GraphQLInputObjectType({
|
const SUBQUERY_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'Subquery',
|
name: 'SubqueryInput',
|
||||||
description:
|
description:
|
||||||
'The Subquery input type is used to specific a different query to a different class.',
|
'The SubqueryInput type is used to specific a different query to a different class.',
|
||||||
fields: {
|
fields: {
|
||||||
className: CLASS_NAME_ATT,
|
className: CLASS_NAME_ATT,
|
||||||
where: Object.assign({}, WHERE_ATT, {
|
where: Object.assign({}, WHERE_ATT, {
|
||||||
@@ -554,14 +554,14 @@ const SUBQUERY = new GraphQLInputObjectType({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const SELECT_OPERATOR = new GraphQLInputObjectType({
|
const SELECT_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'SelectOperator',
|
name: 'SelectInput',
|
||||||
description:
|
description:
|
||||||
'The SelectOperator input type is used to specify a $select operation on a constraint.',
|
'The SelectInput type is used to specify a $select operation on a constraint.',
|
||||||
fields: {
|
fields: {
|
||||||
query: {
|
query: {
|
||||||
description: 'This is the subquery to be executed.',
|
description: 'This is the subquery to be executed.',
|
||||||
type: new GraphQLNonNull(SUBQUERY),
|
type: new GraphQLNonNull(SUBQUERY_INPUT),
|
||||||
},
|
},
|
||||||
key: {
|
key: {
|
||||||
description:
|
description:
|
||||||
@@ -571,10 +571,10 @@ const SELECT_OPERATOR = new GraphQLInputObjectType({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const SEARCH_OPERATOR = new GraphQLInputObjectType({
|
const SEARCH_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'SearchOperator',
|
name: 'SearchInput',
|
||||||
description:
|
description:
|
||||||
'The SearchOperator input type is used to specifiy a $search operation on a full text search.',
|
'The SearchInput type is used to specifiy a $search operation on a full text search.',
|
||||||
fields: {
|
fields: {
|
||||||
_term: {
|
_term: {
|
||||||
description: 'This is the term to be searched.',
|
description: 'This is the term to be searched.',
|
||||||
@@ -598,54 +598,54 @@ const SEARCH_OPERATOR = new GraphQLInputObjectType({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const TEXT_OPERATOR = new GraphQLInputObjectType({
|
const TEXT_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'TextOperator',
|
name: 'TextInput',
|
||||||
description:
|
description:
|
||||||
'The TextOperator input type is used to specify a $text operation on a constraint.',
|
'The TextInput type is used to specify a $text operation on a constraint.',
|
||||||
fields: {
|
fields: {
|
||||||
_search: {
|
_search: {
|
||||||
description: 'This is the search to be executed.',
|
description: 'This is the search to be executed.',
|
||||||
type: new GraphQLNonNull(SEARCH_OPERATOR),
|
type: new GraphQLNonNull(SEARCH_INPUT),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const BOX_OPERATOR = new GraphQLInputObjectType({
|
const BOX_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'BoxOperator',
|
name: 'BoxInput',
|
||||||
description:
|
description:
|
||||||
'The BoxOperator input type is used to specifiy a $box operation on a within geo query.',
|
'The BoxInput type is used to specifiy a $box operation on a within geo query.',
|
||||||
fields: {
|
fields: {
|
||||||
bottomLeft: {
|
bottomLeft: {
|
||||||
description: 'This is the bottom left coordinates of the box.',
|
description: 'This is the bottom left coordinates of the box.',
|
||||||
type: new GraphQLNonNull(GEO_POINT),
|
type: new GraphQLNonNull(GEO_POINT_INPUT),
|
||||||
},
|
},
|
||||||
upperRight: {
|
upperRight: {
|
||||||
description: 'This is the upper right coordinates of the box.',
|
description: 'This is the upper right coordinates of the box.',
|
||||||
type: new GraphQLNonNull(GEO_POINT),
|
type: new GraphQLNonNull(GEO_POINT_INPUT),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const WITHIN_OPERATOR = new GraphQLInputObjectType({
|
const WITHIN_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'WithinOperator',
|
name: 'WithinInput',
|
||||||
description:
|
description:
|
||||||
'The WithinOperator input type is used to specify a $within operation on a constraint.',
|
'The WithinInput type is used to specify a $within operation on a constraint.',
|
||||||
fields: {
|
fields: {
|
||||||
_box: {
|
_box: {
|
||||||
description: 'This is the box to be specified.',
|
description: 'This is the box to be specified.',
|
||||||
type: new GraphQLNonNull(BOX_OPERATOR),
|
type: new GraphQLNonNull(BOX_INPUT),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const CENTER_SPHERE_OPERATOR = new GraphQLInputObjectType({
|
const CENTER_SPHERE_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'CenterSphereOperator',
|
name: 'CenterSphereInput',
|
||||||
description:
|
description:
|
||||||
'The CenterSphereOperator input type is used to specifiy a $centerSphere operation on a geoWithin query.',
|
'The CenterSphereInput type is used to specifiy a $centerSphere operation on a geoWithin query.',
|
||||||
fields: {
|
fields: {
|
||||||
center: {
|
center: {
|
||||||
description: 'This is the center of the sphere.',
|
description: 'This is the center of the sphere.',
|
||||||
type: new GraphQLNonNull(GEO_POINT),
|
type: new GraphQLNonNull(GEO_POINT_INPUT),
|
||||||
},
|
},
|
||||||
distance: {
|
distance: {
|
||||||
description: 'This is the radius of the sphere.',
|
description: 'This is the radius of the sphere.',
|
||||||
@@ -654,30 +654,30 @@ const CENTER_SPHERE_OPERATOR = new GraphQLInputObjectType({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const GEO_WITHIN_OPERATOR = new GraphQLInputObjectType({
|
const GEO_WITHIN_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'GeoWithinOperator',
|
name: 'GeoWithinInput',
|
||||||
description:
|
description:
|
||||||
'The GeoWithinOperator input type is used to specify a $geoWithin operation on a constraint.',
|
'The GeoWithinInput type is used to specify a $geoWithin operation on a constraint.',
|
||||||
fields: {
|
fields: {
|
||||||
_polygon: {
|
_polygon: {
|
||||||
description: 'This is the polygon to be specified.',
|
description: 'This is the polygon to be specified.',
|
||||||
type: POLYGON,
|
type: POLYGON_INPUT,
|
||||||
},
|
},
|
||||||
_centerSphere: {
|
_centerSphere: {
|
||||||
description: 'This is the sphere to be specified.',
|
description: 'This is the sphere to be specified.',
|
||||||
type: CENTER_SPHERE_OPERATOR,
|
type: CENTER_SPHERE_INPUT,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const GEO_INTERSECTS = new GraphQLInputObjectType({
|
const GEO_INTERSECTS_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'GeoIntersectsOperator',
|
name: 'GeoIntersectsInput',
|
||||||
description:
|
description:
|
||||||
'The GeoIntersectsOperator input type is used to specify a $geoIntersects operation on a constraint.',
|
'The GeoIntersectsInput type is used to specify a $geoIntersects operation on a constraint.',
|
||||||
fields: {
|
fields: {
|
||||||
_point: {
|
_point: {
|
||||||
description: 'This is the point to be specified.',
|
description: 'This is the point to be specified.',
|
||||||
type: GEO_POINT,
|
type: GEO_POINT_INPUT,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -739,13 +739,13 @@ const _exists = {
|
|||||||
const _select = {
|
const _select = {
|
||||||
description:
|
description:
|
||||||
'This is the $select operator to specify a constraint to select the objects where a field equals to a key in the result of a different query.',
|
'This is the $select operator to specify a constraint to select the objects where a field equals to a key in the result of a different query.',
|
||||||
type: SELECT_OPERATOR,
|
type: SELECT_INPUT,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _dontSelect = {
|
const _dontSelect = {
|
||||||
description:
|
description:
|
||||||
'This is the $dontSelect operator to specify a constraint to select the objects where a field do not equal to a key in the result of a different query.',
|
'This is the $dontSelect operator to specify a constraint to select the objects where a field do not equal to a key in the result of a different query.',
|
||||||
type: SELECT_OPERATOR,
|
type: SELECT_INPUT,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _regex = {
|
const _regex = {
|
||||||
@@ -760,10 +760,10 @@ const _options = {
|
|||||||
type: GraphQLString,
|
type: GraphQLString,
|
||||||
};
|
};
|
||||||
|
|
||||||
const STRING_CONSTRAINT = new GraphQLInputObjectType({
|
const STRING_WHERE_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'StringConstraint',
|
name: 'StringWhereInput',
|
||||||
description:
|
description:
|
||||||
'The StringConstraint input type is used in operations that involve filtering objects by a field of type String.',
|
'The StringWhereInput input type is used in operations that involve filtering objects by a field of type String.',
|
||||||
fields: {
|
fields: {
|
||||||
_eq: _eq(GraphQLString),
|
_eq: _eq(GraphQLString),
|
||||||
_ne: _ne(GraphQLString),
|
_ne: _ne(GraphQLString),
|
||||||
@@ -781,15 +781,15 @@ const STRING_CONSTRAINT = new GraphQLInputObjectType({
|
|||||||
_text: {
|
_text: {
|
||||||
description:
|
description:
|
||||||
'This is the $text operator to specify a full text search constraint.',
|
'This is the $text operator to specify a full text search constraint.',
|
||||||
type: TEXT_OPERATOR,
|
type: TEXT_INPUT,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const NUMBER_CONSTRAINT = new GraphQLInputObjectType({
|
const NUMBER_WHERE_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'NumberConstraint',
|
name: 'NumberWhereInput',
|
||||||
description:
|
description:
|
||||||
'The NumberConstraint input type is used in operations that involve filtering objects by a field of type Number.',
|
'The NumberWhereInput input type is used in operations that involve filtering objects by a field of type Number.',
|
||||||
fields: {
|
fields: {
|
||||||
_eq: _eq(GraphQLFloat),
|
_eq: _eq(GraphQLFloat),
|
||||||
_ne: _ne(GraphQLFloat),
|
_ne: _ne(GraphQLFloat),
|
||||||
@@ -805,10 +805,10 @@ const NUMBER_CONSTRAINT = new GraphQLInputObjectType({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const BOOLEAN_CONSTRAINT = new GraphQLInputObjectType({
|
const BOOLEAN_WHERE_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'BooleanConstraint',
|
name: 'BooleanWhereInput',
|
||||||
description:
|
description:
|
||||||
'The BooleanConstraint input type is used in operations that involve filtering objects by a field of type Boolean.',
|
'The BooleanWhereInput input type is used in operations that involve filtering objects by a field of type Boolean.',
|
||||||
fields: {
|
fields: {
|
||||||
_eq: _eq(GraphQLBoolean),
|
_eq: _eq(GraphQLBoolean),
|
||||||
_ne: _ne(GraphQLBoolean),
|
_ne: _ne(GraphQLBoolean),
|
||||||
@@ -818,10 +818,10 @@ const BOOLEAN_CONSTRAINT = new GraphQLInputObjectType({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const ARRAY_CONSTRAINT = new GraphQLInputObjectType({
|
const ARRAY_WHERE_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'ArrayConstraint',
|
name: 'ArrayWhereInput',
|
||||||
description:
|
description:
|
||||||
'The ArrayConstraint input type is used in operations that involve filtering objects by a field of type Array.',
|
'The ArrayWhereInput input type is used in operations that involve filtering objects by a field of type Array.',
|
||||||
fields: {
|
fields: {
|
||||||
_eq: _eq(ANY),
|
_eq: _eq(ANY),
|
||||||
_ne: _ne(ANY),
|
_ne: _ne(ANY),
|
||||||
@@ -847,8 +847,8 @@ const ARRAY_CONSTRAINT = new GraphQLInputObjectType({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const KEY_VALUE = new GraphQLInputObjectType({
|
const KEY_VALUE_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'KeyValue',
|
name: 'KeyValueInput',
|
||||||
description: 'An entry from an object, i.e., a pair of key and value.',
|
description: 'An entry from an object, i.e., a pair of key and value.',
|
||||||
fields: {
|
fields: {
|
||||||
_key: {
|
_key: {
|
||||||
@@ -862,29 +862,29 @@ const KEY_VALUE = new GraphQLInputObjectType({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const OBJECT_CONSTRAINT = new GraphQLInputObjectType({
|
const OBJECT_WHERE_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'ObjectConstraint',
|
name: 'ObjectWhereInput',
|
||||||
description:
|
description:
|
||||||
'The ObjectConstraint input type is used in operations that involve filtering result by a field of type Object.',
|
'The ObjectWhereInput input type is used in operations that involve filtering result by a field of type Object.',
|
||||||
fields: {
|
fields: {
|
||||||
_eq: _eq(KEY_VALUE),
|
_eq: _eq(KEY_VALUE_INPUT),
|
||||||
_ne: _ne(KEY_VALUE),
|
_ne: _ne(KEY_VALUE_INPUT),
|
||||||
_in: _in(KEY_VALUE),
|
_in: _in(KEY_VALUE_INPUT),
|
||||||
_nin: _nin(KEY_VALUE),
|
_nin: _nin(KEY_VALUE_INPUT),
|
||||||
_lt: _lt(KEY_VALUE),
|
_lt: _lt(KEY_VALUE_INPUT),
|
||||||
_lte: _lte(KEY_VALUE),
|
_lte: _lte(KEY_VALUE_INPUT),
|
||||||
_gt: _gt(KEY_VALUE),
|
_gt: _gt(KEY_VALUE_INPUT),
|
||||||
_gte: _gte(KEY_VALUE),
|
_gte: _gte(KEY_VALUE_INPUT),
|
||||||
_exists,
|
_exists,
|
||||||
_select,
|
_select,
|
||||||
_dontSelect,
|
_dontSelect,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const DATE_CONSTRAINT = new GraphQLInputObjectType({
|
const DATE_WHERE_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'DateConstraint',
|
name: 'DateWhereInput',
|
||||||
description:
|
description:
|
||||||
'The DateConstraint input type is used in operations that involve filtering objects by a field of type Date.',
|
'The DateWhereInput input type is used in operations that involve filtering objects by a field of type Date.',
|
||||||
fields: {
|
fields: {
|
||||||
_eq: _eq(DATE),
|
_eq: _eq(DATE),
|
||||||
_ne: _ne(DATE),
|
_ne: _ne(DATE),
|
||||||
@@ -900,10 +900,10 @@ const DATE_CONSTRAINT = new GraphQLInputObjectType({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const BYTES_CONSTRAINT = new GraphQLInputObjectType({
|
const BYTES_WHERE_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'BytesConstraint',
|
name: 'BytesWhereInput',
|
||||||
description:
|
description:
|
||||||
'The BytesConstraint input type is used in operations that involve filtering objects by a field of type Bytes.',
|
'The BytesWhereInput input type is used in operations that involve filtering objects by a field of type Bytes.',
|
||||||
fields: {
|
fields: {
|
||||||
_eq: _eq(BYTES),
|
_eq: _eq(BYTES),
|
||||||
_ne: _ne(BYTES),
|
_ne: _ne(BYTES),
|
||||||
@@ -919,10 +919,10 @@ const BYTES_CONSTRAINT = new GraphQLInputObjectType({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const FILE_CONSTRAINT = new GraphQLInputObjectType({
|
const FILE_WHERE_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'FileConstraint',
|
name: 'FileWhereInput',
|
||||||
description:
|
description:
|
||||||
'The FILE_CONSTRAINT input type is used in operations that involve filtering objects by a field of type File.',
|
'The FileWhereInput input type is used in operations that involve filtering objects by a field of type File.',
|
||||||
fields: {
|
fields: {
|
||||||
_eq: _eq(FILE),
|
_eq: _eq(FILE),
|
||||||
_ne: _ne(FILE),
|
_ne: _ne(FILE),
|
||||||
@@ -940,16 +940,16 @@ const FILE_CONSTRAINT = new GraphQLInputObjectType({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const GEO_POINT_CONSTRAINT = new GraphQLInputObjectType({
|
const GEO_POINT_WHERE_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'GeoPointConstraint',
|
name: 'GeoPointWhereInput',
|
||||||
description:
|
description:
|
||||||
'The GeoPointConstraint input type is used in operations that involve filtering objects by a field of type GeoPoint.',
|
'The GeoPointWhereInput input type is used in operations that involve filtering objects by a field of type GeoPoint.',
|
||||||
fields: {
|
fields: {
|
||||||
_exists,
|
_exists,
|
||||||
_nearSphere: {
|
_nearSphere: {
|
||||||
description:
|
description:
|
||||||
'This is the $nearSphere operator to specify a constraint to select the objects where the values of a geo point field is near to another geo point.',
|
'This is the $nearSphere operator to specify a constraint to select the objects where the values of a geo point field is near to another geo point.',
|
||||||
type: GEO_POINT,
|
type: GEO_POINT_INPUT,
|
||||||
},
|
},
|
||||||
_maxDistance: {
|
_maxDistance: {
|
||||||
description:
|
description:
|
||||||
@@ -974,26 +974,26 @@ const GEO_POINT_CONSTRAINT = new GraphQLInputObjectType({
|
|||||||
_within: {
|
_within: {
|
||||||
description:
|
description:
|
||||||
'This is the $within operator to specify a constraint to select the objects where the values of a geo point field is within a specified box.',
|
'This is the $within operator to specify a constraint to select the objects where the values of a geo point field is within a specified box.',
|
||||||
type: WITHIN_OPERATOR,
|
type: WITHIN_INPUT,
|
||||||
},
|
},
|
||||||
_geoWithin: {
|
_geoWithin: {
|
||||||
description:
|
description:
|
||||||
'This is the $geoWithin operator to specify a constraint to select the objects where the values of a geo point field is within a specified polygon or sphere.',
|
'This is the $geoWithin operator to specify a constraint to select the objects where the values of a geo point field is within a specified polygon or sphere.',
|
||||||
type: GEO_WITHIN_OPERATOR,
|
type: GEO_WITHIN_INPUT,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const POLYGON_CONSTRAINT = new GraphQLInputObjectType({
|
const POLYGON_WHERE_INPUT = new GraphQLInputObjectType({
|
||||||
name: 'PolygonConstraint',
|
name: 'PolygonWhereInput',
|
||||||
description:
|
description:
|
||||||
'The PolygonConstraint input type is used in operations that involve filtering objects by a field of type Polygon.',
|
'The PolygonWhereInput input type is used in operations that involve filtering objects by a field of type Polygon.',
|
||||||
fields: {
|
fields: {
|
||||||
_exists,
|
_exists,
|
||||||
_geoIntersects: {
|
_geoIntersects: {
|
||||||
description:
|
description:
|
||||||
'This is the $geoIntersects operator to specify a constraint to select the objects where the values of a polygon field intersect a specified point.',
|
'This is the $geoIntersects operator to specify a constraint to select the objects where the values of a polygon field intersect a specified point.',
|
||||||
type: GEO_INTERSECTS,
|
type: GEO_INTERSECTS_INPUT,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -1071,42 +1071,43 @@ const loadArrayResult = (parseGraphQLSchema, parseClasses) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const load = parseGraphQLSchema => {
|
const load = parseGraphQLSchema => {
|
||||||
parseGraphQLSchema.graphQLTypes.push(GraphQLUpload);
|
parseGraphQLSchema.addGraphQLType(GraphQLUpload, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(ANY);
|
parseGraphQLSchema.addGraphQLType(ANY, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(OBJECT);
|
parseGraphQLSchema.addGraphQLType(OBJECT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(DATE);
|
parseGraphQLSchema.addGraphQLType(DATE, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(BYTES);
|
parseGraphQLSchema.addGraphQLType(BYTES, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(FILE);
|
parseGraphQLSchema.addGraphQLType(FILE, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(FILE_INFO);
|
parseGraphQLSchema.addGraphQLType(FILE_INFO, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(GEO_POINT);
|
parseGraphQLSchema.addGraphQLType(GEO_POINT_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(GEO_POINT_INFO);
|
parseGraphQLSchema.addGraphQLType(GEO_POINT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(RELATION_OP);
|
parseGraphQLSchema.addGraphQLType(RELATION_OP, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(CREATE_RESULT);
|
parseGraphQLSchema.addGraphQLType(CREATE_RESULT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(UPDATE_RESULT);
|
parseGraphQLSchema.addGraphQLType(UPDATE_RESULT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(CLASS);
|
parseGraphQLSchema.addGraphQLType(CLASS, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(READ_PREFERENCE);
|
parseGraphQLSchema.addGraphQLType(READ_PREFERENCE, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(SUBQUERY);
|
parseGraphQLSchema.addGraphQLType(SUBQUERY_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(SELECT_OPERATOR);
|
parseGraphQLSchema.addGraphQLType(SELECT_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(SEARCH_OPERATOR);
|
parseGraphQLSchema.addGraphQLType(SEARCH_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(TEXT_OPERATOR);
|
parseGraphQLSchema.addGraphQLType(TEXT_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(BOX_OPERATOR);
|
parseGraphQLSchema.addGraphQLType(BOX_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(WITHIN_OPERATOR);
|
parseGraphQLSchema.addGraphQLType(WITHIN_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(CENTER_SPHERE_OPERATOR);
|
parseGraphQLSchema.addGraphQLType(CENTER_SPHERE_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(GEO_WITHIN_OPERATOR);
|
parseGraphQLSchema.addGraphQLType(GEO_WITHIN_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(GEO_INTERSECTS);
|
parseGraphQLSchema.addGraphQLType(GEO_INTERSECTS_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(STRING_CONSTRAINT);
|
parseGraphQLSchema.addGraphQLType(STRING_WHERE_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(NUMBER_CONSTRAINT);
|
parseGraphQLSchema.addGraphQLType(NUMBER_WHERE_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(BOOLEAN_CONSTRAINT);
|
parseGraphQLSchema.addGraphQLType(BOOLEAN_WHERE_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(ARRAY_CONSTRAINT);
|
parseGraphQLSchema.addGraphQLType(ARRAY_WHERE_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(OBJECT_CONSTRAINT);
|
parseGraphQLSchema.addGraphQLType(KEY_VALUE_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(DATE_CONSTRAINT);
|
parseGraphQLSchema.addGraphQLType(OBJECT_WHERE_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(BYTES_CONSTRAINT);
|
parseGraphQLSchema.addGraphQLType(DATE_WHERE_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(FILE_CONSTRAINT);
|
parseGraphQLSchema.addGraphQLType(BYTES_WHERE_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(GEO_POINT_CONSTRAINT);
|
parseGraphQLSchema.addGraphQLType(FILE_WHERE_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(POLYGON_CONSTRAINT);
|
parseGraphQLSchema.addGraphQLType(GEO_POINT_WHERE_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(FIND_RESULT);
|
parseGraphQLSchema.addGraphQLType(POLYGON_WHERE_INPUT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(SIGN_UP_RESULT);
|
parseGraphQLSchema.addGraphQLType(FIND_RESULT, true);
|
||||||
parseGraphQLSchema.graphQLTypes.push(ELEMENT);
|
parseGraphQLSchema.addGraphQLType(SIGN_UP_RESULT, true);
|
||||||
|
parseGraphQLSchema.addGraphQLType(ELEMENT, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -1128,10 +1129,10 @@ export {
|
|||||||
FILE,
|
FILE,
|
||||||
FILE_INFO,
|
FILE_INFO,
|
||||||
GEO_POINT_FIELDS,
|
GEO_POINT_FIELDS,
|
||||||
|
GEO_POINT_INPUT,
|
||||||
GEO_POINT,
|
GEO_POINT,
|
||||||
GEO_POINT_INFO,
|
POLYGON_INPUT,
|
||||||
POLYGON,
|
POLYGON,
|
||||||
POLYGON_INFO,
|
|
||||||
RELATION_OP,
|
RELATION_OP,
|
||||||
CLASS_NAME_ATT,
|
CLASS_NAME_ATT,
|
||||||
FIELDS_ATT,
|
FIELDS_ATT,
|
||||||
@@ -1157,15 +1158,15 @@ export {
|
|||||||
SKIP_ATT,
|
SKIP_ATT,
|
||||||
LIMIT_ATT,
|
LIMIT_ATT,
|
||||||
COUNT_ATT,
|
COUNT_ATT,
|
||||||
SUBQUERY,
|
SUBQUERY_INPUT,
|
||||||
SELECT_OPERATOR,
|
SELECT_INPUT,
|
||||||
SEARCH_OPERATOR,
|
SEARCH_INPUT,
|
||||||
TEXT_OPERATOR,
|
TEXT_INPUT,
|
||||||
BOX_OPERATOR,
|
BOX_INPUT,
|
||||||
WITHIN_OPERATOR,
|
WITHIN_INPUT,
|
||||||
CENTER_SPHERE_OPERATOR,
|
CENTER_SPHERE_INPUT,
|
||||||
GEO_WITHIN_OPERATOR,
|
GEO_WITHIN_INPUT,
|
||||||
GEO_INTERSECTS,
|
GEO_INTERSECTS_INPUT,
|
||||||
_eq,
|
_eq,
|
||||||
_ne,
|
_ne,
|
||||||
_lt,
|
_lt,
|
||||||
@@ -1179,16 +1180,17 @@ export {
|
|||||||
_dontSelect,
|
_dontSelect,
|
||||||
_regex,
|
_regex,
|
||||||
_options,
|
_options,
|
||||||
STRING_CONSTRAINT,
|
STRING_WHERE_INPUT,
|
||||||
NUMBER_CONSTRAINT,
|
NUMBER_WHERE_INPUT,
|
||||||
BOOLEAN_CONSTRAINT,
|
BOOLEAN_WHERE_INPUT,
|
||||||
ARRAY_CONSTRAINT,
|
ARRAY_WHERE_INPUT,
|
||||||
OBJECT_CONSTRAINT,
|
KEY_VALUE_INPUT,
|
||||||
DATE_CONSTRAINT,
|
OBJECT_WHERE_INPUT,
|
||||||
BYTES_CONSTRAINT,
|
DATE_WHERE_INPUT,
|
||||||
FILE_CONSTRAINT,
|
BYTES_WHERE_INPUT,
|
||||||
GEO_POINT_CONSTRAINT,
|
FILE_WHERE_INPUT,
|
||||||
POLYGON_CONSTRAINT,
|
GEO_POINT_WHERE_INPUT,
|
||||||
|
POLYGON_WHERE_INPUT,
|
||||||
FIND_RESULT,
|
FIND_RESULT,
|
||||||
SIGN_UP_RESULT,
|
SIGN_UP_RESULT,
|
||||||
ARRAY_RESULT,
|
ARRAY_RESULT,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const load = parseGraphQLSchema => {
|
|||||||
description:
|
description:
|
||||||
'The create mutation can be used to create and upload a new file.',
|
'The create mutation can be used to create and upload a new file.',
|
||||||
args: {
|
args: {
|
||||||
file: {
|
upload: {
|
||||||
description: 'This is the new file to be created and uploaded',
|
description: 'This is the new file to be created and uploaded',
|
||||||
type: new GraphQLNonNull(GraphQLUpload),
|
type: new GraphQLNonNull(GraphQLUpload),
|
||||||
},
|
},
|
||||||
@@ -19,10 +19,10 @@ const load = parseGraphQLSchema => {
|
|||||||
type: new GraphQLNonNull(defaultGraphQLTypes.FILE_INFO),
|
type: new GraphQLNonNull(defaultGraphQLTypes.FILE_INFO),
|
||||||
async resolve(_source, args, context) {
|
async resolve(_source, args, context) {
|
||||||
try {
|
try {
|
||||||
const { file } = args;
|
const { upload } = args;
|
||||||
const { config } = context;
|
const { config } = context;
|
||||||
|
|
||||||
const { createReadStream, filename, mimetype } = await file;
|
const { createReadStream, filename, mimetype } = await upload;
|
||||||
let data = null;
|
let data = null;
|
||||||
if (createReadStream) {
|
if (createReadStream) {
|
||||||
const stream = createReadStream();
|
const stream = createReadStream();
|
||||||
@@ -81,7 +81,7 @@ const load = parseGraphQLSchema => {
|
|||||||
description: 'FilesMutation is the top level type for files mutations.',
|
description: 'FilesMutation is the top level type for files mutations.',
|
||||||
fields,
|
fields,
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.graphQLTypes.push(filesMutation);
|
parseGraphQLSchema.addGraphQLType(filesMutation, true, true);
|
||||||
|
|
||||||
parseGraphQLSchema.graphQLMutations.files = {
|
parseGraphQLSchema.graphQLMutations.files = {
|
||||||
description: 'This is the top level for files mutations.',
|
description: 'This is the top level for files mutations.',
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const load = parseGraphQLSchema => {
|
|||||||
'FunctionsMutation is the top level type for functions mutations.',
|
'FunctionsMutation is the top level type for functions mutations.',
|
||||||
fields,
|
fields,
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.graphQLTypes.push(functionsMutation);
|
parseGraphQLSchema.addGraphQLType(functionsMutation, true, true);
|
||||||
|
|
||||||
parseGraphQLSchema.graphQLMutations.functions = {
|
parseGraphQLSchema.graphQLMutations.functions = {
|
||||||
description: 'This is the top level for functions mutations.',
|
description: 'This is the top level for functions mutations.',
|
||||||
|
|||||||
@@ -1,33 +1,14 @@
|
|||||||
import { GraphQLNonNull, GraphQLBoolean, GraphQLObjectType } from 'graphql';
|
import { GraphQLNonNull, GraphQLBoolean, GraphQLObjectType } from 'graphql';
|
||||||
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
|
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
|
||||||
import rest from '../../rest';
|
import rest from '../../rest';
|
||||||
|
import { transformMutationInputToParse } from '../transformers/mutation';
|
||||||
const parseMap = {
|
|
||||||
_op: '__op',
|
|
||||||
};
|
|
||||||
|
|
||||||
const transformToParse = fields => {
|
|
||||||
if (!fields || typeof fields !== 'object') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Object.keys(fields).forEach(fieldName => {
|
|
||||||
const fieldValue = fields[fieldName];
|
|
||||||
if (parseMap[fieldName]) {
|
|
||||||
delete fields[fieldName];
|
|
||||||
fields[parseMap[fieldName]] = fieldValue;
|
|
||||||
}
|
|
||||||
if (typeof fieldValue === 'object') {
|
|
||||||
transformToParse(fieldValue);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const createObject = async (className, fields, config, auth, info) => {
|
const createObject = async (className, fields, config, auth, info) => {
|
||||||
if (!fields) {
|
if (!fields) {
|
||||||
fields = {};
|
fields = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
transformToParse(fields);
|
transformMutationInputToParse(fields);
|
||||||
|
|
||||||
return (await rest.create(config, auth, className, fields, info.clientSDK))
|
return (await rest.create(config, auth, className, fields, info.clientSDK))
|
||||||
.response;
|
.response;
|
||||||
@@ -45,7 +26,7 @@ const updateObject = async (
|
|||||||
fields = {};
|
fields = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
transformToParse(fields);
|
transformMutationInputToParse(fields);
|
||||||
|
|
||||||
return (await rest.update(
|
return (await rest.update(
|
||||||
config,
|
config,
|
||||||
@@ -63,80 +44,95 @@ const deleteObject = async (className, objectId, config, auth, info) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const load = parseGraphQLSchema => {
|
const load = parseGraphQLSchema => {
|
||||||
parseGraphQLSchema.graphQLObjectsMutations.create = {
|
parseGraphQLSchema.addGraphQLObjectMutation(
|
||||||
description:
|
'create',
|
||||||
'The create mutation can be used to create a new object of a certain class.',
|
{
|
||||||
args: {
|
description:
|
||||||
className: defaultGraphQLTypes.CLASS_NAME_ATT,
|
'The create mutation can be used to create a new object of a certain class.',
|
||||||
fields: defaultGraphQLTypes.FIELDS_ATT,
|
args: {
|
||||||
},
|
className: defaultGraphQLTypes.CLASS_NAME_ATT,
|
||||||
type: new GraphQLNonNull(defaultGraphQLTypes.CREATE_RESULT),
|
fields: defaultGraphQLTypes.FIELDS_ATT,
|
||||||
async resolve(_source, args, context) {
|
},
|
||||||
try {
|
type: new GraphQLNonNull(defaultGraphQLTypes.CREATE_RESULT),
|
||||||
const { className, fields } = args;
|
async resolve(_source, args, context) {
|
||||||
const { config, auth, info } = context;
|
try {
|
||||||
|
const { className, fields } = args;
|
||||||
|
const { config, auth, info } = context;
|
||||||
|
|
||||||
return await createObject(className, fields, config, auth, info);
|
return await createObject(className, fields, config, auth, info);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
parseGraphQLSchema.handleError(e);
|
parseGraphQLSchema.handleError(e);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
true,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
parseGraphQLSchema.graphQLObjectsMutations.update = {
|
parseGraphQLSchema.addGraphQLObjectMutation(
|
||||||
description:
|
'update',
|
||||||
'The update mutation can be used to update an object of a certain class.',
|
{
|
||||||
args: {
|
description:
|
||||||
className: defaultGraphQLTypes.CLASS_NAME_ATT,
|
'The update mutation can be used to update an object of a certain class.',
|
||||||
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
args: {
|
||||||
fields: defaultGraphQLTypes.FIELDS_ATT,
|
className: defaultGraphQLTypes.CLASS_NAME_ATT,
|
||||||
},
|
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
||||||
type: new GraphQLNonNull(defaultGraphQLTypes.UPDATE_RESULT),
|
fields: defaultGraphQLTypes.FIELDS_ATT,
|
||||||
async resolve(_source, args, context) {
|
},
|
||||||
try {
|
type: new GraphQLNonNull(defaultGraphQLTypes.UPDATE_RESULT),
|
||||||
const { className, objectId, fields } = args;
|
async resolve(_source, args, context) {
|
||||||
const { config, auth, info } = context;
|
try {
|
||||||
|
const { className, objectId, fields } = args;
|
||||||
|
const { config, auth, info } = context;
|
||||||
|
|
||||||
return await updateObject(
|
return await updateObject(
|
||||||
className,
|
className,
|
||||||
objectId,
|
objectId,
|
||||||
fields,
|
fields,
|
||||||
config,
|
config,
|
||||||
auth,
|
auth,
|
||||||
info
|
info
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
parseGraphQLSchema.handleError(e);
|
parseGraphQLSchema.handleError(e);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
true,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
parseGraphQLSchema.graphQLObjectsMutations.delete = {
|
parseGraphQLSchema.addGraphQLObjectMutation(
|
||||||
description:
|
'delete',
|
||||||
'The delete mutation can be used to delete an object of a certain class.',
|
{
|
||||||
args: {
|
description:
|
||||||
className: defaultGraphQLTypes.CLASS_NAME_ATT,
|
'The delete mutation can be used to delete an object of a certain class.',
|
||||||
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
args: {
|
||||||
},
|
className: defaultGraphQLTypes.CLASS_NAME_ATT,
|
||||||
type: new GraphQLNonNull(GraphQLBoolean),
|
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
||||||
async resolve(_source, args, context) {
|
},
|
||||||
try {
|
type: new GraphQLNonNull(GraphQLBoolean),
|
||||||
const { className, objectId } = args;
|
async resolve(_source, args, context) {
|
||||||
const { config, auth, info } = context;
|
try {
|
||||||
|
const { className, objectId } = args;
|
||||||
|
const { config, auth, info } = context;
|
||||||
|
|
||||||
return await deleteObject(className, objectId, config, auth, info);
|
return await deleteObject(className, objectId, config, auth, info);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
parseGraphQLSchema.handleError(e);
|
parseGraphQLSchema.handleError(e);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
true,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
const objectsMutation = new GraphQLObjectType({
|
const objectsMutation = new GraphQLObjectType({
|
||||||
name: 'ObjectsMutation',
|
name: 'ObjectsMutation',
|
||||||
description: 'ObjectsMutation is the top level type for objects mutations.',
|
description: 'ObjectsMutation is the top level type for objects mutations.',
|
||||||
fields: parseGraphQLSchema.graphQLObjectsMutations,
|
fields: parseGraphQLSchema.graphQLObjectsMutations,
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.graphQLTypes.push(objectsMutation);
|
parseGraphQLSchema.addGraphQLType(objectsMutation, true, true);
|
||||||
|
|
||||||
parseGraphQLSchema.graphQLMutations.objects = {
|
parseGraphQLSchema.graphQLMutations.objects = {
|
||||||
description: 'This is the top level for objects mutations.',
|
description: 'This is the top level for objects mutations.',
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import getFieldNames from 'graphql-list-fields';
|
|||||||
import Parse from 'parse/node';
|
import Parse from 'parse/node';
|
||||||
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
|
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
|
||||||
import rest from '../../rest';
|
import rest from '../../rest';
|
||||||
|
import { transformQueryInputToParse } from '../transformers/query';
|
||||||
|
|
||||||
const getObject = async (
|
const getObject = async (
|
||||||
className,
|
className,
|
||||||
@@ -54,155 +55,6 @@ const getObject = async (
|
|||||||
return response.results[0];
|
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 (
|
const findObjects = async (
|
||||||
className,
|
className,
|
||||||
where,
|
where,
|
||||||
@@ -224,7 +76,7 @@ const findObjects = async (
|
|||||||
where = {};
|
where = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
transformToParse(where);
|
transformQueryInputToParse(where);
|
||||||
|
|
||||||
const options = {};
|
const options = {};
|
||||||
|
|
||||||
@@ -282,118 +134,131 @@ const findObjects = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const load = parseGraphQLSchema => {
|
const load = parseGraphQLSchema => {
|
||||||
parseGraphQLSchema.graphQLObjectsQueries.get = {
|
parseGraphQLSchema.addGraphQLObjectQuery(
|
||||||
description:
|
'get',
|
||||||
'The get query can be used to get an object of a certain class by its objectId.',
|
{
|
||||||
args: {
|
description:
|
||||||
className: defaultGraphQLTypes.CLASS_NAME_ATT,
|
'The get query can be used to get an object of a certain class by its objectId.',
|
||||||
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
args: {
|
||||||
keys: defaultGraphQLTypes.KEYS_ATT,
|
className: defaultGraphQLTypes.CLASS_NAME_ATT,
|
||||||
include: defaultGraphQLTypes.INCLUDE_ATT,
|
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
||||||
readPreference: defaultGraphQLTypes.READ_PREFERENCE_ATT,
|
keys: defaultGraphQLTypes.KEYS_ATT,
|
||||||
includeReadPreference: defaultGraphQLTypes.INCLUDE_READ_PREFERENCE_ATT,
|
include: defaultGraphQLTypes.INCLUDE_ATT,
|
||||||
},
|
readPreference: defaultGraphQLTypes.READ_PREFERENCE_ATT,
|
||||||
type: new GraphQLNonNull(defaultGraphQLTypes.OBJECT),
|
includeReadPreference: defaultGraphQLTypes.INCLUDE_READ_PREFERENCE_ATT,
|
||||||
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,
|
|
||||||
},
|
},
|
||||||
skip: defaultGraphQLTypes.SKIP_ATT,
|
type: new GraphQLNonNull(defaultGraphQLTypes.OBJECT),
|
||||||
limit: defaultGraphQLTypes.LIMIT_ATT,
|
async resolve(_source, args, context) {
|
||||||
keys: defaultGraphQLTypes.KEYS_ATT,
|
try {
|
||||||
include: defaultGraphQLTypes.INCLUDE_ATT,
|
const {
|
||||||
includeAll: {
|
className,
|
||||||
description: 'All pointers will be returned',
|
objectId,
|
||||||
type: GraphQLBoolean,
|
keys,
|
||||||
},
|
include,
|
||||||
readPreference: defaultGraphQLTypes.READ_PREFERENCE_ATT,
|
readPreference,
|
||||||
includeReadPreference: defaultGraphQLTypes.INCLUDE_READ_PREFERENCE_ATT,
|
includeReadPreference,
|
||||||
subqueryReadPreference: defaultGraphQLTypes.SUBQUERY_READ_PREFERENCE_ATT,
|
} = args;
|
||||||
},
|
|
||||||
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(
|
const { config, auth, info } = context;
|
||||||
className,
|
|
||||||
where,
|
return await getObject(
|
||||||
order,
|
className,
|
||||||
skip,
|
objectId,
|
||||||
limit,
|
keys,
|
||||||
keys,
|
include,
|
||||||
include,
|
readPreference,
|
||||||
includeAll,
|
includeReadPreference,
|
||||||
readPreference,
|
config,
|
||||||
includeReadPreference,
|
auth,
|
||||||
subqueryReadPreference,
|
info
|
||||||
config,
|
);
|
||||||
auth,
|
} catch (e) {
|
||||||
info,
|
parseGraphQLSchema.handleError(e);
|
||||||
selectedFields
|
}
|
||||||
);
|
},
|
||||||
} 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({
|
const objectsQuery = new GraphQLObjectType({
|
||||||
name: 'ObjectsQuery',
|
name: 'ObjectsQuery',
|
||||||
description: 'ObjectsQuery is the top level type for objects queries.',
|
description: 'ObjectsQuery is the top level type for objects queries.',
|
||||||
fields: parseGraphQLSchema.graphQLObjectsQueries,
|
fields: parseGraphQLSchema.graphQLObjectsQueries,
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.graphQLTypes.push(objectsQuery);
|
parseGraphQLSchema.addGraphQLType(objectsQuery, true, true);
|
||||||
|
|
||||||
parseGraphQLSchema.graphQLQueries.objects = {
|
parseGraphQLSchema.graphQLQueries.objects = {
|
||||||
description: 'This is the top level for objects queries.',
|
description: 'This is the top level for objects queries.',
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { extractKeysAndInclude } from '../parseGraphQLUtils';
|
|||||||
import * as objectsMutations from './objectsMutations';
|
import * as objectsMutations from './objectsMutations';
|
||||||
import * as objectsQueries from './objectsQueries';
|
import * as objectsQueries from './objectsQueries';
|
||||||
import { ParseGraphQLClassConfig } from '../../Controllers/ParseGraphQLController';
|
import { ParseGraphQLClassConfig } from '../../Controllers/ParseGraphQLController';
|
||||||
|
import { transformClassNameToGraphQL } from '../transformers/className';
|
||||||
|
|
||||||
const getParseClassMutationConfig = function(
|
const getParseClassMutationConfig = function(
|
||||||
parseClassConfig: ?ParseGraphQLClassConfig
|
parseClassConfig: ?ParseGraphQLClassConfig
|
||||||
@@ -39,7 +40,9 @@ const load = function(
|
|||||||
parseClass,
|
parseClass,
|
||||||
parseClassConfig: ?ParseGraphQLClassConfig
|
parseClassConfig: ?ParseGraphQLClassConfig
|
||||||
) {
|
) {
|
||||||
const { className } = parseClass;
|
const className = parseClass.className;
|
||||||
|
const graphQLClassName = transformClassNameToGraphQL(className);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
create: isCreateEnabled = true,
|
create: isCreateEnabled = true,
|
||||||
update: isUpdateEnabled = true,
|
update: isUpdateEnabled = true,
|
||||||
@@ -52,37 +55,29 @@ const load = function(
|
|||||||
classGraphQLOutputType,
|
classGraphQLOutputType,
|
||||||
} = parseGraphQLSchema.parseClassTypes[className];
|
} = parseGraphQLSchema.parseClassTypes[className];
|
||||||
|
|
||||||
const createFields = {
|
|
||||||
description: 'These are the fields used to create the object.',
|
|
||||||
type: classGraphQLCreateType,
|
|
||||||
};
|
|
||||||
const updateFields = {
|
|
||||||
description: 'These are the fields used to update the object.',
|
|
||||||
type: classGraphQLUpdateType,
|
|
||||||
};
|
|
||||||
|
|
||||||
const classGraphQLCreateTypeFields = isCreateEnabled
|
|
||||||
? classGraphQLCreateType.getFields()
|
|
||||||
: null;
|
|
||||||
const classGraphQLUpdateTypeFields = isUpdateEnabled
|
|
||||||
? classGraphQLUpdateType.getFields()
|
|
||||||
: null;
|
|
||||||
|
|
||||||
const transformTypes = (inputType: 'create' | 'update', fields) => {
|
const transformTypes = (inputType: 'create' | 'update', fields) => {
|
||||||
if (fields) {
|
if (fields) {
|
||||||
|
const classGraphQLCreateTypeFields =
|
||||||
|
isCreateEnabled && classGraphQLCreateType
|
||||||
|
? classGraphQLCreateType.getFields()
|
||||||
|
: null;
|
||||||
|
const classGraphQLUpdateTypeFields =
|
||||||
|
isUpdateEnabled && classGraphQLUpdateType
|
||||||
|
? classGraphQLUpdateType.getFields()
|
||||||
|
: null;
|
||||||
Object.keys(fields).forEach(field => {
|
Object.keys(fields).forEach(field => {
|
||||||
let inputTypeField;
|
let inputTypeField;
|
||||||
if (inputType === 'create') {
|
if (inputType === 'create' && classGraphQLCreateTypeFields) {
|
||||||
inputTypeField = classGraphQLCreateTypeFields[field];
|
inputTypeField = classGraphQLCreateTypeFields[field];
|
||||||
} else {
|
} else if (classGraphQLUpdateTypeFields) {
|
||||||
inputTypeField = classGraphQLUpdateTypeFields[field];
|
inputTypeField = classGraphQLUpdateTypeFields[field];
|
||||||
}
|
}
|
||||||
if (inputTypeField) {
|
if (inputTypeField) {
|
||||||
switch (inputTypeField.type) {
|
switch (inputTypeField.type) {
|
||||||
case defaultGraphQLTypes.GEO_POINT:
|
case defaultGraphQLTypes.GEO_POINT_INPUT:
|
||||||
fields[field].__type = 'GeoPoint';
|
fields[field].__type = 'GeoPoint';
|
||||||
break;
|
break;
|
||||||
case defaultGraphQLTypes.POLYGON:
|
case defaultGraphQLTypes.POLYGON_INPUT:
|
||||||
fields[field] = {
|
fields[field] = {
|
||||||
__type: 'Polygon',
|
__type: 'Polygon',
|
||||||
coordinates: fields[field].map(geoPoint => [
|
coordinates: fields[field].map(geoPoint => [
|
||||||
@@ -98,13 +93,18 @@ const load = function(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isCreateEnabled) {
|
if (isCreateEnabled) {
|
||||||
const createGraphQLMutationName = `create${className}`;
|
const createGraphQLMutationName = `create${graphQLClassName}`;
|
||||||
parseGraphQLSchema.graphQLObjectsMutations[createGraphQLMutationName] = {
|
parseGraphQLSchema.addGraphQLObjectMutation(createGraphQLMutationName, {
|
||||||
description: `The ${createGraphQLMutationName} mutation can be used to create a new object of the ${className} class.`,
|
description: `The ${createGraphQLMutationName} mutation can be used to create a new object of the ${graphQLClassName} class.`,
|
||||||
args: {
|
args: {
|
||||||
fields: createFields,
|
fields: {
|
||||||
|
description: 'These are the fields used to create the object.',
|
||||||
|
type: classGraphQLCreateType || defaultGraphQLTypes.OBJECT,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
type: new GraphQLNonNull(classGraphQLOutputType),
|
type: new GraphQLNonNull(
|
||||||
|
classGraphQLOutputType || defaultGraphQLTypes.OBJECT
|
||||||
|
),
|
||||||
async resolve(_source, args, context, mutationInfo) {
|
async resolve(_source, args, context, mutationInfo) {
|
||||||
try {
|
try {
|
||||||
let { fields } = args;
|
let { fields } = args;
|
||||||
@@ -150,18 +150,23 @@ const load = function(
|
|||||||
parseGraphQLSchema.handleError(e);
|
parseGraphQLSchema.handleError(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUpdateEnabled) {
|
if (isUpdateEnabled) {
|
||||||
const updateGraphQLMutationName = `update${className}`;
|
const updateGraphQLMutationName = `update${graphQLClassName}`;
|
||||||
parseGraphQLSchema.graphQLObjectsMutations[updateGraphQLMutationName] = {
|
parseGraphQLSchema.addGraphQLObjectMutation(updateGraphQLMutationName, {
|
||||||
description: `The ${updateGraphQLMutationName} mutation can be used to update an object of the ${className} class.`,
|
description: `The ${updateGraphQLMutationName} mutation can be used to update an object of the ${graphQLClassName} class.`,
|
||||||
args: {
|
args: {
|
||||||
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
||||||
fields: updateFields,
|
fields: {
|
||||||
|
description: 'These are the fields used to update the object.',
|
||||||
|
type: classGraphQLUpdateType || defaultGraphQLTypes.OBJECT,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
type: new GraphQLNonNull(classGraphQLOutputType),
|
type: new GraphQLNonNull(
|
||||||
|
classGraphQLOutputType || defaultGraphQLTypes.OBJECT
|
||||||
|
),
|
||||||
async resolve(_source, args, context, mutationInfo) {
|
async resolve(_source, args, context, mutationInfo) {
|
||||||
try {
|
try {
|
||||||
const { objectId, fields } = args;
|
const { objectId, fields } = args;
|
||||||
@@ -205,17 +210,19 @@ const load = function(
|
|||||||
parseGraphQLSchema.handleError(e);
|
parseGraphQLSchema.handleError(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDestroyEnabled) {
|
if (isDestroyEnabled) {
|
||||||
const deleteGraphQLMutationName = `delete${className}`;
|
const deleteGraphQLMutationName = `delete${graphQLClassName}`;
|
||||||
parseGraphQLSchema.graphQLObjectsMutations[deleteGraphQLMutationName] = {
|
parseGraphQLSchema.addGraphQLObjectMutation(deleteGraphQLMutationName, {
|
||||||
description: `The ${deleteGraphQLMutationName} mutation can be used to delete an object of the ${className} class.`,
|
description: `The ${deleteGraphQLMutationName} mutation can be used to delete an object of the ${graphQLClassName} class.`,
|
||||||
args: {
|
args: {
|
||||||
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
||||||
},
|
},
|
||||||
type: new GraphQLNonNull(classGraphQLOutputType),
|
type: new GraphQLNonNull(
|
||||||
|
classGraphQLOutputType || defaultGraphQLTypes.OBJECT
|
||||||
|
),
|
||||||
async resolve(_source, args, context, mutationInfo) {
|
async resolve(_source, args, context, mutationInfo) {
|
||||||
try {
|
try {
|
||||||
const { objectId } = args;
|
const { objectId } = args;
|
||||||
@@ -250,7 +257,7 @@ const load = function(
|
|||||||
parseGraphQLSchema.handleError(e);
|
parseGraphQLSchema.handleError(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { GraphQLNonNull } from 'graphql';
|
import { GraphQLNonNull } from 'graphql';
|
||||||
import getFieldNames from 'graphql-list-fields';
|
import getFieldNames from 'graphql-list-fields';
|
||||||
|
import pluralize from 'pluralize';
|
||||||
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
|
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
|
||||||
import * as objectsQueries from './objectsQueries';
|
import * as objectsQueries from './objectsQueries';
|
||||||
import { ParseGraphQLClassConfig } from '../../Controllers/ParseGraphQLController';
|
import { ParseGraphQLClassConfig } from '../../Controllers/ParseGraphQLController';
|
||||||
|
import { transformClassNameToGraphQL } from '../transformers/className';
|
||||||
import { extractKeysAndInclude } from '../parseGraphQLUtils';
|
import { extractKeysAndInclude } from '../parseGraphQLUtils';
|
||||||
|
|
||||||
const getParseClassQueryConfig = function(
|
const getParseClassQueryConfig = function(
|
||||||
@@ -36,7 +38,8 @@ const load = function(
|
|||||||
parseClass,
|
parseClass,
|
||||||
parseClassConfig: ?ParseGraphQLClassConfig
|
parseClassConfig: ?ParseGraphQLClassConfig
|
||||||
) {
|
) {
|
||||||
const { className } = parseClass;
|
const className = parseClass.className;
|
||||||
|
const graphQLClassName = transformClassNameToGraphQL(className);
|
||||||
const {
|
const {
|
||||||
get: isGetEnabled = true,
|
get: isGetEnabled = true,
|
||||||
find: isFindEnabled = true,
|
find: isFindEnabled = true,
|
||||||
@@ -49,15 +52,18 @@ const load = function(
|
|||||||
} = parseGraphQLSchema.parseClassTypes[className];
|
} = parseGraphQLSchema.parseClassTypes[className];
|
||||||
|
|
||||||
if (isGetEnabled) {
|
if (isGetEnabled) {
|
||||||
const getGraphQLQueryName = `get${className}`;
|
const getGraphQLQueryName =
|
||||||
parseGraphQLSchema.graphQLObjectsQueries[getGraphQLQueryName] = {
|
graphQLClassName.charAt(0).toLowerCase() + graphQLClassName.slice(1);
|
||||||
description: `The ${getGraphQLQueryName} query can be used to get an object of the ${className} class by its id.`,
|
parseGraphQLSchema.addGraphQLObjectQuery(getGraphQLQueryName, {
|
||||||
|
description: `The ${getGraphQLQueryName} query can be used to get an object of the ${graphQLClassName} class by its id.`,
|
||||||
args: {
|
args: {
|
||||||
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
||||||
readPreference: defaultGraphQLTypes.READ_PREFERENCE_ATT,
|
readPreference: defaultGraphQLTypes.READ_PREFERENCE_ATT,
|
||||||
includeReadPreference: defaultGraphQLTypes.INCLUDE_READ_PREFERENCE_ATT,
|
includeReadPreference: defaultGraphQLTypes.INCLUDE_READ_PREFERENCE_ATT,
|
||||||
},
|
},
|
||||||
type: new GraphQLNonNull(classGraphQLOutputType),
|
type: new GraphQLNonNull(
|
||||||
|
classGraphQLOutputType || defaultGraphQLTypes.OBJECT
|
||||||
|
),
|
||||||
async resolve(_source, args, context, queryInfo) {
|
async resolve(_source, args, context, queryInfo) {
|
||||||
try {
|
try {
|
||||||
return await getQuery(className, _source, args, context, queryInfo);
|
return await getQuery(className, _source, args, context, queryInfo);
|
||||||
@@ -65,15 +71,19 @@ const load = function(
|
|||||||
parseGraphQLSchema.handleError(e);
|
parseGraphQLSchema.handleError(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFindEnabled) {
|
if (isFindEnabled) {
|
||||||
const findGraphQLQueryName = `find${className}`;
|
const findGraphQLQueryName = pluralize(
|
||||||
parseGraphQLSchema.graphQLObjectsQueries[findGraphQLQueryName] = {
|
graphQLClassName.charAt(0).toLowerCase() + graphQLClassName.slice(1)
|
||||||
description: `The ${findGraphQLQueryName} query can be used to find objects of the ${className} class.`,
|
);
|
||||||
|
parseGraphQLSchema.addGraphQLObjectQuery(findGraphQLQueryName, {
|
||||||
|
description: `The ${findGraphQLQueryName} query can be used to find objects of the ${graphQLClassName} class.`,
|
||||||
args: classGraphQLFindArgs,
|
args: classGraphQLFindArgs,
|
||||||
type: new GraphQLNonNull(classGraphQLFindResultType),
|
type: new GraphQLNonNull(
|
||||||
|
classGraphQLFindResultType || defaultGraphQLTypes.FIND_RESULT
|
||||||
|
),
|
||||||
async resolve(_source, args, context, queryInfo) {
|
async resolve(_source, args, context, queryInfo) {
|
||||||
try {
|
try {
|
||||||
const {
|
const {
|
||||||
@@ -116,7 +126,7 @@ const load = function(
|
|||||||
parseGraphQLSchema.handleError(e);
|
parseGraphQLSchema.handleError(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import getFieldNames from 'graphql-list-fields';
|
|||||||
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
|
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
|
||||||
import * as objectsQueries from './objectsQueries';
|
import * as objectsQueries from './objectsQueries';
|
||||||
import { ParseGraphQLClassConfig } from '../../Controllers/ParseGraphQLController';
|
import { ParseGraphQLClassConfig } from '../../Controllers/ParseGraphQLController';
|
||||||
|
import { transformClassNameToGraphQL } from '../transformers/className';
|
||||||
import { extractKeysAndInclude } from '../parseGraphQLUtils';
|
import { extractKeysAndInclude } from '../parseGraphQLUtils';
|
||||||
|
|
||||||
const mapInputType = (parseType, targetClass, parseClassTypes) => {
|
const mapInputType = (parseType, targetClass, parseClassTypes) => {
|
||||||
@@ -31,13 +32,19 @@ const mapInputType = (parseType, targetClass, parseClassTypes) => {
|
|||||||
case 'Date':
|
case 'Date':
|
||||||
return defaultGraphQLTypes.DATE;
|
return defaultGraphQLTypes.DATE;
|
||||||
case 'Pointer':
|
case 'Pointer':
|
||||||
if (parseClassTypes[targetClass]) {
|
if (
|
||||||
|
parseClassTypes[targetClass] &&
|
||||||
|
parseClassTypes[targetClass].classGraphQLScalarType
|
||||||
|
) {
|
||||||
return parseClassTypes[targetClass].classGraphQLScalarType;
|
return parseClassTypes[targetClass].classGraphQLScalarType;
|
||||||
} else {
|
} else {
|
||||||
return defaultGraphQLTypes.OBJECT;
|
return defaultGraphQLTypes.OBJECT;
|
||||||
}
|
}
|
||||||
case 'Relation':
|
case 'Relation':
|
||||||
if (parseClassTypes[targetClass]) {
|
if (
|
||||||
|
parseClassTypes[targetClass] &&
|
||||||
|
parseClassTypes[targetClass].classGraphQLRelationOpType
|
||||||
|
) {
|
||||||
return parseClassTypes[targetClass].classGraphQLRelationOpType;
|
return parseClassTypes[targetClass].classGraphQLRelationOpType;
|
||||||
} else {
|
} else {
|
||||||
return defaultGraphQLTypes.OBJECT;
|
return defaultGraphQLTypes.OBJECT;
|
||||||
@@ -45,9 +52,9 @@ const mapInputType = (parseType, targetClass, parseClassTypes) => {
|
|||||||
case 'File':
|
case 'File':
|
||||||
return defaultGraphQLTypes.FILE;
|
return defaultGraphQLTypes.FILE;
|
||||||
case 'GeoPoint':
|
case 'GeoPoint':
|
||||||
return defaultGraphQLTypes.GEO_POINT;
|
return defaultGraphQLTypes.GEO_POINT_INPUT;
|
||||||
case 'Polygon':
|
case 'Polygon':
|
||||||
return defaultGraphQLTypes.POLYGON;
|
return defaultGraphQLTypes.POLYGON_INPUT;
|
||||||
case 'Bytes':
|
case 'Bytes':
|
||||||
return defaultGraphQLTypes.BYTES;
|
return defaultGraphQLTypes.BYTES;
|
||||||
case 'ACL':
|
case 'ACL':
|
||||||
@@ -72,13 +79,19 @@ const mapOutputType = (parseType, targetClass, parseClassTypes) => {
|
|||||||
case 'Date':
|
case 'Date':
|
||||||
return defaultGraphQLTypes.DATE;
|
return defaultGraphQLTypes.DATE;
|
||||||
case 'Pointer':
|
case 'Pointer':
|
||||||
if (parseClassTypes[targetClass]) {
|
if (
|
||||||
|
parseClassTypes[targetClass] &&
|
||||||
|
parseClassTypes[targetClass].classGraphQLOutputType
|
||||||
|
) {
|
||||||
return parseClassTypes[targetClass].classGraphQLOutputType;
|
return parseClassTypes[targetClass].classGraphQLOutputType;
|
||||||
} else {
|
} else {
|
||||||
return defaultGraphQLTypes.OBJECT;
|
return defaultGraphQLTypes.OBJECT;
|
||||||
}
|
}
|
||||||
case 'Relation':
|
case 'Relation':
|
||||||
if (parseClassTypes[targetClass]) {
|
if (
|
||||||
|
parseClassTypes[targetClass] &&
|
||||||
|
parseClassTypes[targetClass].classGraphQLFindResultType
|
||||||
|
) {
|
||||||
return new GraphQLNonNull(
|
return new GraphQLNonNull(
|
||||||
parseClassTypes[targetClass].classGraphQLFindResultType
|
parseClassTypes[targetClass].classGraphQLFindResultType
|
||||||
);
|
);
|
||||||
@@ -88,9 +101,9 @@ const mapOutputType = (parseType, targetClass, parseClassTypes) => {
|
|||||||
case 'File':
|
case 'File':
|
||||||
return defaultGraphQLTypes.FILE_INFO;
|
return defaultGraphQLTypes.FILE_INFO;
|
||||||
case 'GeoPoint':
|
case 'GeoPoint':
|
||||||
return defaultGraphQLTypes.GEO_POINT_INFO;
|
return defaultGraphQLTypes.GEO_POINT;
|
||||||
case 'Polygon':
|
case 'Polygon':
|
||||||
return defaultGraphQLTypes.POLYGON_INFO;
|
return defaultGraphQLTypes.POLYGON;
|
||||||
case 'Bytes':
|
case 'Bytes':
|
||||||
return defaultGraphQLTypes.BYTES;
|
return defaultGraphQLTypes.BYTES;
|
||||||
case 'ACL':
|
case 'ACL':
|
||||||
@@ -103,33 +116,36 @@ const mapOutputType = (parseType, targetClass, parseClassTypes) => {
|
|||||||
const mapConstraintType = (parseType, targetClass, parseClassTypes) => {
|
const mapConstraintType = (parseType, targetClass, parseClassTypes) => {
|
||||||
switch (parseType) {
|
switch (parseType) {
|
||||||
case 'String':
|
case 'String':
|
||||||
return defaultGraphQLTypes.STRING_CONSTRAINT;
|
return defaultGraphQLTypes.STRING_WHERE_INPUT;
|
||||||
case 'Number':
|
case 'Number':
|
||||||
return defaultGraphQLTypes.NUMBER_CONSTRAINT;
|
return defaultGraphQLTypes.NUMBER_WHERE_INPUT;
|
||||||
case 'Boolean':
|
case 'Boolean':
|
||||||
return defaultGraphQLTypes.BOOLEAN_CONSTRAINT;
|
return defaultGraphQLTypes.BOOLEAN_WHERE_INPUT;
|
||||||
case 'Array':
|
case 'Array':
|
||||||
return defaultGraphQLTypes.ARRAY_CONSTRAINT;
|
return defaultGraphQLTypes.ARRAY_WHERE_INPUT;
|
||||||
case 'Object':
|
case 'Object':
|
||||||
return defaultGraphQLTypes.OBJECT_CONSTRAINT;
|
return defaultGraphQLTypes.OBJECT_WHERE_INPUT;
|
||||||
case 'Date':
|
case 'Date':
|
||||||
return defaultGraphQLTypes.DATE_CONSTRAINT;
|
return defaultGraphQLTypes.DATE_WHERE_INPUT;
|
||||||
case 'Pointer':
|
case 'Pointer':
|
||||||
if (parseClassTypes[targetClass]) {
|
if (
|
||||||
|
parseClassTypes[targetClass] &&
|
||||||
|
parseClassTypes[targetClass].classGraphQLConstraintType
|
||||||
|
) {
|
||||||
return parseClassTypes[targetClass].classGraphQLConstraintType;
|
return parseClassTypes[targetClass].classGraphQLConstraintType;
|
||||||
} else {
|
} else {
|
||||||
return defaultGraphQLTypes.OBJECT;
|
return defaultGraphQLTypes.OBJECT;
|
||||||
}
|
}
|
||||||
case 'File':
|
case 'File':
|
||||||
return defaultGraphQLTypes.FILE_CONSTRAINT;
|
return defaultGraphQLTypes.FILE_WHERE_INPUT;
|
||||||
case 'GeoPoint':
|
case 'GeoPoint':
|
||||||
return defaultGraphQLTypes.GEO_POINT_CONSTRAINT;
|
return defaultGraphQLTypes.GEO_POINT_WHERE_INPUT;
|
||||||
case 'Polygon':
|
case 'Polygon':
|
||||||
return defaultGraphQLTypes.POLYGON_CONSTRAINT;
|
return defaultGraphQLTypes.POLYGON_WHERE_INPUT;
|
||||||
case 'Bytes':
|
case 'Bytes':
|
||||||
return defaultGraphQLTypes.BYTES_CONSTRAINT;
|
return defaultGraphQLTypes.BYTES_WHERE_INPUT;
|
||||||
case 'ACL':
|
case 'ACL':
|
||||||
return defaultGraphQLTypes.OBJECT_CONSTRAINT;
|
return defaultGraphQLTypes.OBJECT_WHERE_INPUT;
|
||||||
case 'Relation':
|
case 'Relation':
|
||||||
default:
|
default:
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -233,7 +249,8 @@ const load = (
|
|||||||
parseClass,
|
parseClass,
|
||||||
parseClassConfig: ?ParseGraphQLClassConfig
|
parseClassConfig: ?ParseGraphQLClassConfig
|
||||||
) => {
|
) => {
|
||||||
const { className } = parseClass;
|
const className = parseClass.className;
|
||||||
|
const graphQLClassName = transformClassNameToGraphQL(className);
|
||||||
const {
|
const {
|
||||||
classCreateFields,
|
classCreateFields,
|
||||||
classUpdateFields,
|
classUpdateFields,
|
||||||
@@ -242,12 +259,12 @@ const load = (
|
|||||||
classSortFields,
|
classSortFields,
|
||||||
} = getInputFieldsAndConstraints(parseClass, parseClassConfig);
|
} = getInputFieldsAndConstraints(parseClass, parseClassConfig);
|
||||||
|
|
||||||
const classGraphQLScalarTypeName = `${className}Pointer`;
|
const classGraphQLScalarTypeName = `${graphQLClassName}Pointer`;
|
||||||
const parseScalarValue = value => {
|
const parseScalarValue = value => {
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
return {
|
return {
|
||||||
__type: 'Pointer',
|
__type: 'Pointer',
|
||||||
className,
|
className: className,
|
||||||
objectId: value,
|
objectId: value,
|
||||||
};
|
};
|
||||||
} else if (
|
} else if (
|
||||||
@@ -256,7 +273,7 @@ const load = (
|
|||||||
value.className === className &&
|
value.className === className &&
|
||||||
typeof value.objectId === 'string'
|
typeof value.objectId === 'string'
|
||||||
) {
|
) {
|
||||||
return value;
|
return { ...value, className };
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new defaultGraphQLTypes.TypeValidationError(
|
throw new defaultGraphQLTypes.TypeValidationError(
|
||||||
@@ -264,9 +281,9 @@ const load = (
|
|||||||
classGraphQLScalarTypeName
|
classGraphQLScalarTypeName
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
const classGraphQLScalarType = new GraphQLScalarType({
|
let classGraphQLScalarType = new GraphQLScalarType({
|
||||||
name: classGraphQLScalarTypeName,
|
name: classGraphQLScalarTypeName,
|
||||||
description: `The ${classGraphQLScalarTypeName} is used in operations that involve ${className} pointers.`,
|
description: `The ${classGraphQLScalarTypeName} is used in operations that involve ${graphQLClassName} pointers.`,
|
||||||
parseValue: parseScalarValue,
|
parseValue: parseScalarValue,
|
||||||
serialize(value) {
|
serialize(value) {
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
@@ -318,12 +335,14 @@ const load = (
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.graphQLTypes.push(classGraphQLScalarType);
|
classGraphQLScalarType =
|
||||||
|
parseGraphQLSchema.addGraphQLType(classGraphQLScalarType) ||
|
||||||
|
defaultGraphQLTypes.OBJECT;
|
||||||
|
|
||||||
const classGraphQLRelationOpTypeName = `${className}RelationOp`;
|
const classGraphQLRelationOpTypeName = `${graphQLClassName}RelationOpInput`;
|
||||||
const classGraphQLRelationOpType = new GraphQLInputObjectType({
|
let classGraphQLRelationOpType = new GraphQLInputObjectType({
|
||||||
name: classGraphQLRelationOpTypeName,
|
name: classGraphQLRelationOpTypeName,
|
||||||
description: `The ${classGraphQLRelationOpTypeName} input type is used in operations that involve relations with the ${className} class.`,
|
description: `The ${classGraphQLRelationOpTypeName} type is used in operations that involve relations with the ${graphQLClassName} class.`,
|
||||||
fields: () => ({
|
fields: () => ({
|
||||||
_op: {
|
_op: {
|
||||||
description: 'This is the operation to be executed.',
|
description: 'This is the operation to be executed.',
|
||||||
@@ -341,12 +360,14 @@ const load = (
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.graphQLTypes.push(classGraphQLRelationOpType);
|
classGraphQLRelationOpType =
|
||||||
|
parseGraphQLSchema.addGraphQLType(classGraphQLRelationOpType) ||
|
||||||
|
defaultGraphQLTypes.OBJECT;
|
||||||
|
|
||||||
const classGraphQLCreateTypeName = `${className}CreateFields`;
|
const classGraphQLCreateTypeName = `Create${graphQLClassName}FieldsInput`;
|
||||||
const classGraphQLCreateType = new GraphQLInputObjectType({
|
let classGraphQLCreateType = new GraphQLInputObjectType({
|
||||||
name: classGraphQLCreateTypeName,
|
name: classGraphQLCreateTypeName,
|
||||||
description: `The ${classGraphQLCreateTypeName} input type is used in operations that involve creation of objects in the ${className} class.`,
|
description: `The ${classGraphQLCreateTypeName} input type is used in operations that involve creation of objects in the ${graphQLClassName} class.`,
|
||||||
fields: () =>
|
fields: () =>
|
||||||
classCreateFields.reduce(
|
classCreateFields.reduce(
|
||||||
(fields, field) => {
|
(fields, field) => {
|
||||||
@@ -372,12 +393,14 @@ const load = (
|
|||||||
}
|
}
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.graphQLTypes.push(classGraphQLCreateType);
|
classGraphQLCreateType = parseGraphQLSchema.addGraphQLType(
|
||||||
|
classGraphQLCreateType
|
||||||
|
);
|
||||||
|
|
||||||
const classGraphQLUpdateTypeName = `${className}UpdateFields`;
|
const classGraphQLUpdateTypeName = `Update${graphQLClassName}FieldsInput`;
|
||||||
const classGraphQLUpdateType = new GraphQLInputObjectType({
|
let classGraphQLUpdateType = new GraphQLInputObjectType({
|
||||||
name: classGraphQLUpdateTypeName,
|
name: classGraphQLUpdateTypeName,
|
||||||
description: `The ${classGraphQLUpdateTypeName} input type is used in operations that involve creation of objects in the ${className} class.`,
|
description: `The ${classGraphQLUpdateTypeName} input type is used in operations that involve creation of objects in the ${graphQLClassName} class.`,
|
||||||
fields: () =>
|
fields: () =>
|
||||||
classUpdateFields.reduce(
|
classUpdateFields.reduce(
|
||||||
(fields, field) => {
|
(fields, field) => {
|
||||||
@@ -403,12 +426,14 @@ const load = (
|
|||||||
}
|
}
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.graphQLTypes.push(classGraphQLUpdateType);
|
classGraphQLUpdateType = parseGraphQLSchema.addGraphQLType(
|
||||||
|
classGraphQLUpdateType
|
||||||
|
);
|
||||||
|
|
||||||
const classGraphQLConstraintTypeName = `${className}PointerConstraint`;
|
const classGraphQLConstraintTypeName = `${graphQLClassName}PointerWhereInput`;
|
||||||
const classGraphQLConstraintType = new GraphQLInputObjectType({
|
let classGraphQLConstraintType = new GraphQLInputObjectType({
|
||||||
name: classGraphQLConstraintTypeName,
|
name: classGraphQLConstraintTypeName,
|
||||||
description: `The ${classGraphQLConstraintTypeName} input type is used in operations that involve filtering objects by a pointer field to ${className} class.`,
|
description: `The ${classGraphQLConstraintTypeName} input type is used in operations that involve filtering objects by a pointer field to ${graphQLClassName} class.`,
|
||||||
fields: {
|
fields: {
|
||||||
_eq: defaultGraphQLTypes._eq(classGraphQLScalarType),
|
_eq: defaultGraphQLTypes._eq(classGraphQLScalarType),
|
||||||
_ne: defaultGraphQLTypes._ne(classGraphQLScalarType),
|
_ne: defaultGraphQLTypes._ne(classGraphQLScalarType),
|
||||||
@@ -420,21 +445,23 @@ const load = (
|
|||||||
_inQuery: {
|
_inQuery: {
|
||||||
description:
|
description:
|
||||||
'This is the $inQuery operator to specify a constraint to select the objects where a field equals to any of the ids in the result of a different query.',
|
'This is the $inQuery operator to specify a constraint to select the objects where a field equals to any of the ids in the result of a different query.',
|
||||||
type: defaultGraphQLTypes.SUBQUERY,
|
type: defaultGraphQLTypes.SUBQUERY_INPUT,
|
||||||
},
|
},
|
||||||
_notInQuery: {
|
_notInQuery: {
|
||||||
description:
|
description:
|
||||||
'This is the $notInQuery operator to specify a constraint to select the objects where a field do not equal to any of the ids in the result of a different query.',
|
'This is the $notInQuery operator to specify a constraint to select the objects where a field do not equal to any of the ids in the result of a different query.',
|
||||||
type: defaultGraphQLTypes.SUBQUERY,
|
type: defaultGraphQLTypes.SUBQUERY_INPUT,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.graphQLTypes.push(classGraphQLConstraintType);
|
classGraphQLConstraintType = parseGraphQLSchema.addGraphQLType(
|
||||||
|
classGraphQLConstraintType
|
||||||
|
);
|
||||||
|
|
||||||
const classGraphQLConstraintsTypeName = `${className}Constraints`;
|
const classGraphQLConstraintsTypeName = `${graphQLClassName}WhereInput`;
|
||||||
const classGraphQLConstraintsType = new GraphQLInputObjectType({
|
let classGraphQLConstraintsType = new GraphQLInputObjectType({
|
||||||
name: classGraphQLConstraintsTypeName,
|
name: classGraphQLConstraintsTypeName,
|
||||||
description: `The ${classGraphQLConstraintsTypeName} input type is used in operations that involve filtering objects of ${className} class.`,
|
description: `The ${classGraphQLConstraintsTypeName} input type is used in operations that involve filtering objects of ${graphQLClassName} class.`,
|
||||||
fields: () => ({
|
fields: () => ({
|
||||||
...classConstraintFields.reduce((fields, field) => {
|
...classConstraintFields.reduce((fields, field) => {
|
||||||
const type = mapConstraintType(
|
const type = mapConstraintType(
|
||||||
@@ -468,12 +495,14 @@ const load = (
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.graphQLTypes.push(classGraphQLConstraintsType);
|
classGraphQLConstraintsType =
|
||||||
|
parseGraphQLSchema.addGraphQLType(classGraphQLConstraintsType) ||
|
||||||
|
defaultGraphQLTypes.OBJECT;
|
||||||
|
|
||||||
const classGraphQLOrderTypeName = `${className}Order`;
|
const classGraphQLOrderTypeName = `${graphQLClassName}Order`;
|
||||||
const classGraphQLOrderType = new GraphQLEnumType({
|
let classGraphQLOrderType = new GraphQLEnumType({
|
||||||
name: classGraphQLOrderTypeName,
|
name: classGraphQLOrderTypeName,
|
||||||
description: `The ${classGraphQLOrderTypeName} input type is used when sorting objects of the ${className} class.`,
|
description: `The ${classGraphQLOrderTypeName} input type is used when sorting objects of the ${graphQLClassName} class.`,
|
||||||
values: classSortFields.reduce((sortFields, fieldConfig) => {
|
values: classSortFields.reduce((sortFields, fieldConfig) => {
|
||||||
const { field, asc, desc } = fieldConfig;
|
const { field, asc, desc } = fieldConfig;
|
||||||
const updatedSortFields = {
|
const updatedSortFields = {
|
||||||
@@ -488,7 +517,9 @@ const load = (
|
|||||||
return updatedSortFields;
|
return updatedSortFields;
|
||||||
}, {}),
|
}, {}),
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.graphQLTypes.push(classGraphQLOrderType);
|
classGraphQLOrderType = parseGraphQLSchema.addGraphQLType(
|
||||||
|
classGraphQLOrderType
|
||||||
|
);
|
||||||
|
|
||||||
const classGraphQLFindArgs = {
|
const classGraphQLFindArgs = {
|
||||||
where: {
|
where: {
|
||||||
@@ -498,7 +529,9 @@ const load = (
|
|||||||
},
|
},
|
||||||
order: {
|
order: {
|
||||||
description: 'The fields to be used when sorting the data fetched.',
|
description: 'The fields to be used when sorting the data fetched.',
|
||||||
type: new GraphQLList(new GraphQLNonNull(classGraphQLOrderType)),
|
type: classGraphQLOrderType
|
||||||
|
? new GraphQLList(new GraphQLNonNull(classGraphQLOrderType))
|
||||||
|
: GraphQLString,
|
||||||
},
|
},
|
||||||
skip: defaultGraphQLTypes.SKIP_ATT,
|
skip: defaultGraphQLTypes.SKIP_ATT,
|
||||||
limit: defaultGraphQLTypes.LIMIT_ATT,
|
limit: defaultGraphQLTypes.LIMIT_ATT,
|
||||||
@@ -507,7 +540,7 @@ const load = (
|
|||||||
subqueryReadPreference: defaultGraphQLTypes.SUBQUERY_READ_PREFERENCE_ATT,
|
subqueryReadPreference: defaultGraphQLTypes.SUBQUERY_READ_PREFERENCE_ATT,
|
||||||
};
|
};
|
||||||
|
|
||||||
const classGraphQLOutputTypeName = `${className}Class`;
|
const classGraphQLOutputTypeName = `${graphQLClassName}`;
|
||||||
const outputFields = () => {
|
const outputFields = () => {
|
||||||
return classOutputFields.reduce((fields, field) => {
|
return classOutputFields.reduce((fields, field) => {
|
||||||
const type = mapOutputType(
|
const type = mapOutputType(
|
||||||
@@ -548,14 +581,13 @@ const load = (
|
|||||||
.filter(field => field.includes('.'))
|
.filter(field => field.includes('.'))
|
||||||
.map(field => field.slice(field.indexOf('.') + 1))
|
.map(field => field.slice(field.indexOf('.') + 1))
|
||||||
);
|
);
|
||||||
|
|
||||||
return await objectsQueries.findObjects(
|
return await objectsQueries.findObjects(
|
||||||
source[field].className,
|
source[field].className,
|
||||||
{
|
{
|
||||||
_relatedTo: {
|
_relatedTo: {
|
||||||
object: {
|
object: {
|
||||||
__type: 'Pointer',
|
__type: 'Pointer',
|
||||||
className,
|
className: className,
|
||||||
objectId: source.objectId,
|
objectId: source.objectId,
|
||||||
},
|
},
|
||||||
key: field,
|
key: field,
|
||||||
@@ -634,29 +666,37 @@ const load = (
|
|||||||
}
|
}
|
||||||
}, defaultGraphQLTypes.CLASS_FIELDS);
|
}, defaultGraphQLTypes.CLASS_FIELDS);
|
||||||
};
|
};
|
||||||
const classGraphQLOutputType = new GraphQLObjectType({
|
let classGraphQLOutputType = new GraphQLObjectType({
|
||||||
name: classGraphQLOutputTypeName,
|
name: classGraphQLOutputTypeName,
|
||||||
description: `The ${classGraphQLOutputTypeName} object type is used in operations that involve outputting objects of ${className} class.`,
|
description: `The ${classGraphQLOutputTypeName} object type is used in operations that involve outputting objects of ${graphQLClassName} class.`,
|
||||||
interfaces: [defaultGraphQLTypes.CLASS],
|
interfaces: [defaultGraphQLTypes.CLASS],
|
||||||
fields: outputFields,
|
fields: outputFields,
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.graphQLTypes.push(classGraphQLOutputType);
|
classGraphQLOutputType = parseGraphQLSchema.addGraphQLType(
|
||||||
|
classGraphQLOutputType
|
||||||
|
);
|
||||||
|
|
||||||
const classGraphQLFindResultTypeName = `${className}FindResult`;
|
const classGraphQLFindResultTypeName = `${graphQLClassName}FindResult`;
|
||||||
const classGraphQLFindResultType = new GraphQLObjectType({
|
let classGraphQLFindResultType = new GraphQLObjectType({
|
||||||
name: classGraphQLFindResultTypeName,
|
name: classGraphQLFindResultTypeName,
|
||||||
description: `The ${classGraphQLFindResultTypeName} object type is used in the ${className} find query to return the data of the matched objects.`,
|
description: `The ${classGraphQLFindResultTypeName} object type is used in the ${graphQLClassName} find query to return the data of the matched objects.`,
|
||||||
fields: {
|
fields: {
|
||||||
results: {
|
results: {
|
||||||
description: 'This is the objects returned by the query',
|
description: 'This is the objects returned by the query',
|
||||||
type: new GraphQLNonNull(
|
type: new GraphQLNonNull(
|
||||||
new GraphQLList(new GraphQLNonNull(classGraphQLOutputType))
|
new GraphQLList(
|
||||||
|
new GraphQLNonNull(
|
||||||
|
classGraphQLOutputType || defaultGraphQLTypes.OBJECT
|
||||||
|
)
|
||||||
|
)
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
count: defaultGraphQLTypes.COUNT_ATT,
|
count: defaultGraphQLTypes.COUNT_ATT,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.graphQLTypes.push(classGraphQLFindResultType);
|
classGraphQLFindResultType = parseGraphQLSchema.addGraphQLType(
|
||||||
|
classGraphQLFindResultType
|
||||||
|
);
|
||||||
|
|
||||||
parseGraphQLSchema.parseClassTypes[className] = {
|
parseGraphQLSchema.parseClassTypes[className] = {
|
||||||
classGraphQLScalarType,
|
classGraphQLScalarType,
|
||||||
@@ -671,22 +711,22 @@ const load = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (className === '_User') {
|
if (className === '_User') {
|
||||||
const meType = new GraphQLObjectType({
|
const viewerType = new GraphQLObjectType({
|
||||||
name: 'Me',
|
name: 'Viewer',
|
||||||
description: `The Me object type is used in operations that involve outputting the current user data.`,
|
description: `The Viewer object type is used in operations that involve outputting the current user data.`,
|
||||||
interfaces: [defaultGraphQLTypes.CLASS],
|
interfaces: [defaultGraphQLTypes.CLASS],
|
||||||
fields: () => ({
|
fields: () => ({
|
||||||
...outputFields(),
|
...outputFields(),
|
||||||
sessionToken: defaultGraphQLTypes.SESSION_TOKEN_ATT,
|
sessionToken: defaultGraphQLTypes.SESSION_TOKEN_ATT,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.meType = meType;
|
parseGraphQLSchema.viewerType = viewerType;
|
||||||
parseGraphQLSchema.graphQLTypes.push(meType);
|
parseGraphQLSchema.addGraphQLType(viewerType, true, true);
|
||||||
|
|
||||||
const userSignUpInputTypeName = '_UserSignUpFields';
|
const userSignUpInputTypeName = 'SignUpFieldsInput';
|
||||||
const userSignUpInputType = new GraphQLInputObjectType({
|
const userSignUpInputType = new GraphQLInputObjectType({
|
||||||
name: userSignUpInputTypeName,
|
name: userSignUpInputTypeName,
|
||||||
description: `The ${userSignUpInputTypeName} input type is used in operations that involve inputting objects of ${className} class when signing up.`,
|
description: `The ${userSignUpInputTypeName} input type is used in operations that involve inputting objects of ${graphQLClassName} class when signing up.`,
|
||||||
fields: () =>
|
fields: () =>
|
||||||
classCreateFields.reduce((fields, field) => {
|
classCreateFields.reduce((fields, field) => {
|
||||||
const type = mapInputType(
|
const type = mapInputType(
|
||||||
@@ -710,8 +750,9 @@ const load = (
|
|||||||
}
|
}
|
||||||
}, {}),
|
}, {}),
|
||||||
});
|
});
|
||||||
|
parseGraphQLSchema.addGraphQLType(userSignUpInputType, true, true);
|
||||||
|
|
||||||
const userLogInInputTypeName = '_UserLoginFields';
|
const userLogInInputTypeName = 'LogInFieldsInput';
|
||||||
const userLogInInputType = new GraphQLInputObjectType({
|
const userLogInInputType = new GraphQLInputObjectType({
|
||||||
name: userLogInInputTypeName,
|
name: userLogInInputTypeName,
|
||||||
description: `The ${userLogInInputTypeName} input type is used to login.`,
|
description: `The ${userLogInInputTypeName} input type is used to login.`,
|
||||||
@@ -726,13 +767,14 @@ const load = (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
parseGraphQLSchema.addGraphQLType(userLogInInputType, true, true);
|
||||||
|
|
||||||
parseGraphQLSchema.parseClassTypes[
|
parseGraphQLSchema.parseClassTypes[
|
||||||
'_User'
|
className
|
||||||
].signUpInputType = userSignUpInputType;
|
].signUpInputType = userSignUpInputType;
|
||||||
parseGraphQLSchema.parseClassTypes[
|
parseGraphQLSchema.parseClassTypes[
|
||||||
'_User'
|
className
|
||||||
].logInInputType = userLogInInputType;
|
].logInInputType = userLogInInputType;
|
||||||
parseGraphQLSchema.graphQLTypes.push(userSignUpInputType);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { GraphQLBoolean, GraphQLNonNull, GraphQLObjectType } from 'graphql';
|
import { GraphQLNonNull, GraphQLObjectType } from 'graphql';
|
||||||
import UsersRouter from '../../Routers/UsersRouter';
|
import UsersRouter from '../../Routers/UsersRouter';
|
||||||
import * as objectsMutations from './objectsMutations';
|
import * as objectsMutations from './objectsMutations';
|
||||||
import { getUserFromSessionToken } from './usersQueries';
|
import { getUserFromSessionToken } from './usersQueries';
|
||||||
@@ -19,10 +19,11 @@ const load = parseGraphQLSchema => {
|
|||||||
type: parseGraphQLSchema.parseClassTypes['_User'].signUpInputType,
|
type: parseGraphQLSchema.parseClassTypes['_User'].signUpInputType,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
type: new GraphQLNonNull(parseGraphQLSchema.meType),
|
type: new GraphQLNonNull(parseGraphQLSchema.viewerType),
|
||||||
async resolve(_source, args, context, mutationInfo) {
|
async resolve(_source, args, context, mutationInfo) {
|
||||||
try {
|
try {
|
||||||
const { fields } = args;
|
const { fields } = args;
|
||||||
|
|
||||||
const { config, auth, info } = context;
|
const { config, auth, info } = context;
|
||||||
|
|
||||||
const { sessionToken } = await objectsMutations.createObject(
|
const { sessionToken } = await objectsMutations.createObject(
|
||||||
@@ -45,16 +46,16 @@ const load = parseGraphQLSchema => {
|
|||||||
fields.logIn = {
|
fields.logIn = {
|
||||||
description: 'The logIn mutation can be used to log the user in.',
|
description: 'The logIn mutation can be used to log the user in.',
|
||||||
args: {
|
args: {
|
||||||
input: {
|
fields: {
|
||||||
description: 'This is data needed to login',
|
description: 'This is data needed to login',
|
||||||
type: parseGraphQLSchema.parseClassTypes['_User'].logInInputType,
|
type: parseGraphQLSchema.parseClassTypes['_User'].logInInputType,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
type: new GraphQLNonNull(parseGraphQLSchema.meType),
|
type: new GraphQLNonNull(parseGraphQLSchema.viewerType),
|
||||||
async resolve(_source, args, context) {
|
async resolve(_source, args, context) {
|
||||||
try {
|
try {
|
||||||
const {
|
const {
|
||||||
input: { username, password },
|
fields: { username, password },
|
||||||
} = args;
|
} = args;
|
||||||
const { config, auth, info } = context;
|
const { config, auth, info } = context;
|
||||||
|
|
||||||
@@ -76,17 +77,24 @@ const load = parseGraphQLSchema => {
|
|||||||
|
|
||||||
fields.logOut = {
|
fields.logOut = {
|
||||||
description: 'The logOut mutation can be used to log the user out.',
|
description: 'The logOut mutation can be used to log the user out.',
|
||||||
type: new GraphQLNonNull(GraphQLBoolean),
|
type: new GraphQLNonNull(parseGraphQLSchema.viewerType),
|
||||||
async resolve(_source, _args, context) {
|
async resolve(_source, _args, context, mutationInfo) {
|
||||||
try {
|
try {
|
||||||
const { config, auth, info } = context;
|
const { config, auth, info } = context;
|
||||||
|
|
||||||
|
const viewer = await getUserFromSessionToken(
|
||||||
|
config,
|
||||||
|
info,
|
||||||
|
mutationInfo
|
||||||
|
);
|
||||||
|
|
||||||
await usersRouter.handleLogOut({
|
await usersRouter.handleLogOut({
|
||||||
config,
|
config,
|
||||||
auth,
|
auth,
|
||||||
info,
|
info,
|
||||||
});
|
});
|
||||||
return true;
|
|
||||||
|
return viewer;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
parseGraphQLSchema.handleError(e);
|
parseGraphQLSchema.handleError(e);
|
||||||
}
|
}
|
||||||
@@ -98,7 +106,7 @@ const load = parseGraphQLSchema => {
|
|||||||
description: 'UsersMutation is the top level type for files mutations.',
|
description: 'UsersMutation is the top level type for files mutations.',
|
||||||
fields,
|
fields,
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.graphQLTypes.push(usersMutation);
|
parseGraphQLSchema.addGraphQLType(usersMutation, true, true);
|
||||||
|
|
||||||
parseGraphQLSchema.graphQLMutations.users = {
|
parseGraphQLSchema.graphQLMutations.users = {
|
||||||
description: 'This is the top level for users mutations.',
|
description: 'This is the top level for users mutations.',
|
||||||
|
|||||||
@@ -51,9 +51,10 @@ const load = parseGraphQLSchema => {
|
|||||||
}
|
}
|
||||||
const fields = {};
|
const fields = {};
|
||||||
|
|
||||||
fields.me = {
|
fields.viewer = {
|
||||||
description: 'The Me query can be used to return the current user data.',
|
description:
|
||||||
type: new GraphQLNonNull(parseGraphQLSchema.meType),
|
'The viewer query can be used to return the current user data.',
|
||||||
|
type: new GraphQLNonNull(parseGraphQLSchema.viewerType),
|
||||||
async resolve(_source, _args, context, queryInfo) {
|
async resolve(_source, _args, context, queryInfo) {
|
||||||
try {
|
try {
|
||||||
const { config, info } = context;
|
const { config, info } = context;
|
||||||
@@ -69,7 +70,7 @@ const load = parseGraphQLSchema => {
|
|||||||
description: 'UsersQuery is the top level type for users queries.',
|
description: 'UsersQuery is the top level type for users queries.',
|
||||||
fields,
|
fields,
|
||||||
});
|
});
|
||||||
parseGraphQLSchema.graphQLTypes.push(usersQuery);
|
parseGraphQLSchema.addGraphQLType(usersQuery, true, true);
|
||||||
|
|
||||||
parseGraphQLSchema.graphQLQueries.users = {
|
parseGraphQLSchema.graphQLQueries.users = {
|
||||||
description: 'This is the top level for users queries.',
|
description: 'This is the top level for users queries.',
|
||||||
|
|||||||
8
src/GraphQL/transformers/className.js
Normal file
8
src/GraphQL/transformers/className.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
const transformClassNameToGraphQL = className => {
|
||||||
|
if (className[0] === '_') {
|
||||||
|
className = className.slice(1);
|
||||||
|
}
|
||||||
|
return className[0].toUpperCase() + className.slice(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { transformClassNameToGraphQL };
|
||||||
21
src/GraphQL/transformers/mutation.js
Normal file
21
src/GraphQL/transformers/mutation.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
const parseMap = {
|
||||||
|
_op: '__op',
|
||||||
|
};
|
||||||
|
|
||||||
|
const transformMutationInputToParse = fields => {
|
||||||
|
if (!fields || typeof fields !== 'object') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Object.keys(fields).forEach(fieldName => {
|
||||||
|
const fieldValue = fields[fieldName];
|
||||||
|
if (parseMap[fieldName]) {
|
||||||
|
delete fields[fieldName];
|
||||||
|
fields[parseMap[fieldName]] = fieldValue;
|
||||||
|
}
|
||||||
|
if (typeof fieldValue === 'object') {
|
||||||
|
transformMutationInputToParse(fieldValue);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export { transformMutationInputToParse };
|
||||||
154
src/GraphQL/transformers/query.js
Normal file
154
src/GraphQL/transformers/query.js
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
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 transformQueryInputToParse = (
|
||||||
|
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') {
|
||||||
|
transformQueryInputToParse(fieldValue, fieldName, constraints);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export { transformQueryInputToParse };
|
||||||
Reference in New Issue
Block a user