GraphQL: Allow true GraphQL Schema Customization (#6360)
* Allow real GraphQL Schema via ParseServer.start * wip * working * tests ok * add tests about enum/input use case * Add async function based merge * Better naming * remove useless condition
This commit is contained in:
@@ -17,6 +17,14 @@ const { SubscriptionClient } = require('subscriptions-transport-ws');
|
|||||||
const { WebSocketLink } = require('apollo-link-ws');
|
const { WebSocketLink } = require('apollo-link-ws');
|
||||||
const ApolloClient = require('apollo-client').default;
|
const ApolloClient = require('apollo-client').default;
|
||||||
const gql = require('graphql-tag');
|
const gql = require('graphql-tag');
|
||||||
|
const {
|
||||||
|
GraphQLObjectType,
|
||||||
|
GraphQLString,
|
||||||
|
GraphQLNonNull,
|
||||||
|
GraphQLEnumType,
|
||||||
|
GraphQLInputObjectType,
|
||||||
|
GraphQLSchema,
|
||||||
|
} = require('graphql');
|
||||||
const { ParseServer } = require('../');
|
const { ParseServer } = require('../');
|
||||||
const { ParseGraphQLServer } = require('../lib/GraphQL/ParseGraphQLServer');
|
const { ParseGraphQLServer } = require('../lib/GraphQL/ParseGraphQLServer');
|
||||||
const ReadPreference = require('mongodb').ReadPreference;
|
const ReadPreference = require('mongodb').ReadPreference;
|
||||||
@@ -10594,13 +10602,13 @@ describe('ParseGraphQLServer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('Custom API', () => {
|
describe('Custom API', () => {
|
||||||
|
describe('GraphQL Schema Based', () => {
|
||||||
let httpServer;
|
let httpServer;
|
||||||
const headers = {
|
const headers = {
|
||||||
'X-Parse-Application-Id': 'test',
|
'X-Parse-Application-Id': 'test',
|
||||||
'X-Parse-Javascript-Key': 'test',
|
'X-Parse-Javascript-Key': 'test',
|
||||||
};
|
};
|
||||||
let apolloClient;
|
let apolloClient;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const expressApp = express();
|
const expressApp = express();
|
||||||
httpServer = http.createServer(expressApp);
|
httpServer = http.createServer(expressApp);
|
||||||
@@ -10617,7 +10625,9 @@ describe('ParseGraphQLServer', () => {
|
|||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
parseGraphQLServer.applyGraphQL(expressApp);
|
parseGraphQLServer.applyGraphQL(expressApp);
|
||||||
await new Promise(resolve => httpServer.listen({ port: 13377 }, resolve));
|
await new Promise(resolve =>
|
||||||
|
httpServer.listen({ port: 13377 }, resolve)
|
||||||
|
);
|
||||||
const httpLink = createUploadLink({
|
const httpLink = createUploadLink({
|
||||||
uri: 'http://localhost:13377/graphql',
|
uri: 'http://localhost:13377/graphql',
|
||||||
fetch,
|
fetch,
|
||||||
@@ -10669,55 +10679,219 @@ describe('ParseGraphQLServer', () => {
|
|||||||
|
|
||||||
expect(result.data.hello2).toEqual('Hello world!');
|
expect(result.data.hello2).toEqual('Hello world!');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should resolve auto types', async () => {
|
|
||||||
Parse.Cloud.define('userEcho', async req => {
|
|
||||||
return req.params.user;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = await apolloClient.query({
|
describe('SDL Based', () => {
|
||||||
query: gql`
|
let httpServer;
|
||||||
query UserEcho($user: CreateUserFieldsInput!) {
|
const headers = {
|
||||||
userEcho(user: $user) {
|
'X-Parse-Application-Id': 'test',
|
||||||
username
|
'X-Parse-Javascript-Key': 'test',
|
||||||
}
|
};
|
||||||
}
|
let apolloClient;
|
||||||
`,
|
|
||||||
variables: {
|
beforeAll(async () => {
|
||||||
user: {
|
const expressApp = express();
|
||||||
username: 'somefolk',
|
httpServer = http.createServer(expressApp);
|
||||||
password: 'somepassword',
|
const TypeEnum = new GraphQLEnumType({
|
||||||
|
name: 'TypeEnum',
|
||||||
|
values: {
|
||||||
|
human: { value: 'human' },
|
||||||
|
robot: { value: 'robot' },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
parseGraphQLServer = new ParseGraphQLServer(parseServer, {
|
||||||
|
graphQLPath: '/graphql',
|
||||||
|
graphQLCustomTypeDefs: new GraphQLSchema({
|
||||||
|
query: new GraphQLObjectType({
|
||||||
|
name: 'Query',
|
||||||
|
fields: {
|
||||||
|
customQuery: {
|
||||||
|
type: new GraphQLNonNull(GraphQLString),
|
||||||
|
args: {
|
||||||
|
message: { type: new GraphQLNonNull(GraphQLString) },
|
||||||
|
},
|
||||||
|
resolve: (p, { message }) => message,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
types: [
|
||||||
|
new GraphQLInputObjectType({
|
||||||
|
name: 'CreateSomeClassFieldsInput',
|
||||||
|
fields: {
|
||||||
|
type: { type: TypeEnum },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new GraphQLInputObjectType({
|
||||||
|
name: 'UpdateSomeClassFieldsInput',
|
||||||
|
fields: {
|
||||||
|
type: { type: TypeEnum },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new GraphQLObjectType({
|
||||||
|
name: 'SomeClass',
|
||||||
|
fields: {
|
||||||
|
nameUpperCase: {
|
||||||
|
type: new GraphQLNonNull(GraphQLString),
|
||||||
|
resolve: p => p.name.toUpperCase(),
|
||||||
|
},
|
||||||
|
type: { type: TypeEnum },
|
||||||
|
language: {
|
||||||
|
type: new GraphQLEnumType({
|
||||||
|
name: 'LanguageEnum',
|
||||||
|
values: {
|
||||||
|
fr: { value: 'fr' },
|
||||||
|
en: { value: 'en' },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
resolve: () => 'fr',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
parseGraphQLServer.applyGraphQL(expressApp);
|
||||||
|
await new Promise(resolve =>
|
||||||
|
httpServer.listen({ port: 13377 }, resolve)
|
||||||
|
);
|
||||||
|
const httpLink = createUploadLink({
|
||||||
|
uri: 'http://localhost:13377/graphql',
|
||||||
|
fetch,
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
apolloClient = new ApolloClient({
|
||||||
|
link: httpLink,
|
||||||
|
cache: new InMemoryCache(),
|
||||||
|
defaultOptions: {
|
||||||
|
query: {
|
||||||
|
fetchPolicy: 'no-cache',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.data.userEcho.username).toEqual('somefolk');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can mock a custom query with string', async () => {
|
afterAll(async () => {
|
||||||
|
await httpServer.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can resolve a custom query', async () => {
|
||||||
const result = await apolloClient.query({
|
const result = await apolloClient.query({
|
||||||
|
variables: { message: 'hello' },
|
||||||
query: gql`
|
query: gql`
|
||||||
query Hello {
|
query CustomQuery($message: String!) {
|
||||||
hello3
|
customQuery(message: $message)
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
|
expect(result.data.customQuery).toEqual('hello');
|
||||||
expect(result.data.hello3).toEqual('Hello world!');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can mock a custom query with auto type', async () => {
|
it('can resolve a custom extend type', async () => {
|
||||||
|
const obj = new Parse.Object('SomeClass');
|
||||||
|
await obj.save({ name: 'aname', type: 'robot' });
|
||||||
|
await parseGraphQLServer.parseGraphQLSchema.databaseController.schemaCache.clear();
|
||||||
const result = await apolloClient.query({
|
const result = await apolloClient.query({
|
||||||
|
variables: { id: obj.id },
|
||||||
query: gql`
|
query: gql`
|
||||||
query Hello {
|
query someClass($id: ID!) {
|
||||||
hello4 {
|
someClass(id: $id) {
|
||||||
username
|
nameUpperCase
|
||||||
|
language
|
||||||
|
type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
|
expect(result.data.someClass.nameUpperCase).toEqual('ANAME');
|
||||||
|
expect(result.data.someClass.language).toEqual('fr');
|
||||||
|
expect(result.data.someClass.type).toEqual('robot');
|
||||||
|
|
||||||
expect(result.data.hello4.username).toEqual('somefolk');
|
const result2 = await apolloClient.query({
|
||||||
|
variables: { id: obj.id },
|
||||||
|
query: gql`
|
||||||
|
query someClass($id: ID!) {
|
||||||
|
someClass(id: $id) {
|
||||||
|
name
|
||||||
|
language
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
expect(result2.data.someClass.name).toEqual('aname');
|
||||||
|
expect(result.data.someClass.language).toEqual('fr');
|
||||||
|
const result3 = await apolloClient.mutate({
|
||||||
|
variables: { id: obj.id, name: 'anewname' },
|
||||||
|
mutation: gql`
|
||||||
|
mutation someClass($id: ID!, $name: String!) {
|
||||||
|
updateSomeClass(
|
||||||
|
input: { id: $id, fields: { name: $name, type: human } }
|
||||||
|
) {
|
||||||
|
someClass {
|
||||||
|
nameUpperCase
|
||||||
|
type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
expect(result3.data.updateSomeClass.someClass.nameUpperCase).toEqual(
|
||||||
|
'ANEWNAME'
|
||||||
|
);
|
||||||
|
expect(result3.data.updateSomeClass.someClass.type).toEqual('human');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('Async Function Based Merge', () => {
|
||||||
|
let httpServer;
|
||||||
|
const headers = {
|
||||||
|
'X-Parse-Application-Id': 'test',
|
||||||
|
'X-Parse-Javascript-Key': 'test',
|
||||||
|
};
|
||||||
|
let apolloClient;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const expressApp = express();
|
||||||
|
httpServer = http.createServer(expressApp);
|
||||||
|
parseGraphQLServer = new ParseGraphQLServer(parseServer, {
|
||||||
|
graphQLPath: '/graphql',
|
||||||
|
graphQLCustomTypeDefs: ({ autoSchema, mergeSchemas }) =>
|
||||||
|
mergeSchemas({ schemas: [autoSchema] }),
|
||||||
|
});
|
||||||
|
|
||||||
|
parseGraphQLServer.applyGraphQL(expressApp);
|
||||||
|
await new Promise(resolve =>
|
||||||
|
httpServer.listen({ port: 13377 }, resolve)
|
||||||
|
);
|
||||||
|
const httpLink = createUploadLink({
|
||||||
|
uri: 'http://localhost:13377/graphql',
|
||||||
|
fetch,
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
apolloClient = new ApolloClient({
|
||||||
|
link: httpLink,
|
||||||
|
cache: new InMemoryCache(),
|
||||||
|
defaultOptions: {
|
||||||
|
query: {
|
||||||
|
fetchPolicy: 'no-cache',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await httpServer.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can resolve a query', async () => {
|
||||||
|
const result = await apolloClient.query({
|
||||||
|
query: gql`
|
||||||
|
query Health {
|
||||||
|
health
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
expect(result.data.health).toEqual(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -197,6 +197,43 @@ class ParseGraphQLSchema {
|
|||||||
if (this.graphQLCustomTypeDefs) {
|
if (this.graphQLCustomTypeDefs) {
|
||||||
schemaDirectives.load(this);
|
schemaDirectives.load(this);
|
||||||
|
|
||||||
|
if (typeof this.graphQLCustomTypeDefs.getTypeMap === 'function') {
|
||||||
|
const customGraphQLSchemaTypeMap = this.graphQLCustomTypeDefs.getTypeMap();
|
||||||
|
Object.values(customGraphQLSchemaTypeMap).forEach(
|
||||||
|
customGraphQLSchemaType => {
|
||||||
|
if (
|
||||||
|
!customGraphQLSchemaType ||
|
||||||
|
!customGraphQLSchemaType.name ||
|
||||||
|
customGraphQLSchemaType.name.startsWith('__')
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const autoGraphQLSchemaType = this.graphQLAutoSchema.getType(
|
||||||
|
customGraphQLSchemaType.name
|
||||||
|
);
|
||||||
|
if (autoGraphQLSchemaType) {
|
||||||
|
autoGraphQLSchemaType._fields = {
|
||||||
|
...autoGraphQLSchemaType._fields,
|
||||||
|
...customGraphQLSchemaType._fields,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.graphQLSchema = mergeSchemas({
|
||||||
|
schemas: [
|
||||||
|
this.graphQLSchemaDirectivesDefinitions,
|
||||||
|
this.graphQLCustomTypeDefs,
|
||||||
|
this.graphQLAutoSchema,
|
||||||
|
],
|
||||||
|
mergeDirectives: true,
|
||||||
|
});
|
||||||
|
} else if (typeof this.graphQLCustomTypeDefs === 'function') {
|
||||||
|
this.graphQLSchema = await this.graphQLCustomTypeDefs({
|
||||||
|
directivesDefinitionsSchema: this.graphQLSchemaDirectivesDefinitions,
|
||||||
|
autoSchema: this.graphQLAutoSchema,
|
||||||
|
mergeSchemas,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
this.graphQLSchema = mergeSchemas({
|
this.graphQLSchema = mergeSchemas({
|
||||||
schemas: [
|
schemas: [
|
||||||
this.graphQLSchemaDirectivesDefinitions,
|
this.graphQLSchemaDirectivesDefinitions,
|
||||||
@@ -205,11 +242,15 @@ class ParseGraphQLSchema {
|
|||||||
],
|
],
|
||||||
mergeDirectives: true,
|
mergeDirectives: true,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const graphQLSchemaTypeMap = this.graphQLSchema.getTypeMap();
|
const graphQLSchemaTypeMap = this.graphQLSchema.getTypeMap();
|
||||||
Object.keys(graphQLSchemaTypeMap).forEach(graphQLSchemaTypeName => {
|
Object.keys(graphQLSchemaTypeMap).forEach(graphQLSchemaTypeName => {
|
||||||
const graphQLSchemaType = graphQLSchemaTypeMap[graphQLSchemaTypeName];
|
const graphQLSchemaType = graphQLSchemaTypeMap[graphQLSchemaTypeName];
|
||||||
if (typeof graphQLSchemaType.getFields === 'function') {
|
if (
|
||||||
|
typeof graphQLSchemaType.getFields === 'function' &&
|
||||||
|
this.graphQLCustomTypeDefs.definitions
|
||||||
|
) {
|
||||||
const graphQLCustomTypeDef = this.graphQLCustomTypeDefs.definitions.find(
|
const graphQLCustomTypeDef = this.graphQLCustomTypeDefs.definitions.find(
|
||||||
definition => definition.name.value === graphQLSchemaTypeName
|
definition => definition.name.value === graphQLSchemaTypeName
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,6 +3,11 @@ import { offsetToCursor, cursorToOffset } from 'graphql-relay';
|
|||||||
import rest from '../../rest';
|
import rest from '../../rest';
|
||||||
import { transformQueryInputToParse } from '../transformers/query';
|
import { transformQueryInputToParse } from '../transformers/query';
|
||||||
|
|
||||||
|
const needToGetAllKeys = (fields, keys) =>
|
||||||
|
keys
|
||||||
|
? !!keys.split(',').find(keyName => !fields[keyName.split('.')[0]])
|
||||||
|
: true;
|
||||||
|
|
||||||
const getObject = async (
|
const getObject = async (
|
||||||
className,
|
className,
|
||||||
objectId,
|
objectId,
|
||||||
@@ -12,10 +17,11 @@ const getObject = async (
|
|||||||
includeReadPreference,
|
includeReadPreference,
|
||||||
config,
|
config,
|
||||||
auth,
|
auth,
|
||||||
info
|
info,
|
||||||
|
parseClass
|
||||||
) => {
|
) => {
|
||||||
const options = {};
|
const options = {};
|
||||||
if (keys) {
|
if (!needToGetAllKeys(parseClass.fields, keys)) {
|
||||||
options.keys = keys;
|
options.keys = keys;
|
||||||
}
|
}
|
||||||
if (include) {
|
if (include) {
|
||||||
@@ -133,7 +139,14 @@ const findObjects = async (
|
|||||||
// Silently replace the limit on the query with the max configured
|
// Silently replace the limit on the query with the max configured
|
||||||
options.limit = config.maxLimit;
|
options.limit = config.maxLimit;
|
||||||
}
|
}
|
||||||
if (keys) {
|
if (
|
||||||
|
!needToGetAllKeys(
|
||||||
|
parseClasses.find(
|
||||||
|
({ className: parseClassName }) => className === parseClassName
|
||||||
|
).fields,
|
||||||
|
keys
|
||||||
|
)
|
||||||
|
) {
|
||||||
options.keys = keys;
|
options.keys = keys;
|
||||||
}
|
}
|
||||||
if (includeAll === true) {
|
if (includeAll === true) {
|
||||||
@@ -313,4 +326,4 @@ const calculateSkipAndLimit = (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export { getObject, findObjects, calculateSkipAndLimit };
|
export { getObject, findObjects, calculateSkipAndLimit, needToGetAllKeys };
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ const load = parseGraphQLSchema => {
|
|||||||
undefined,
|
undefined,
|
||||||
config,
|
config,
|
||||||
auth,
|
auth,
|
||||||
info
|
info,
|
||||||
|
parseGraphQLSchema.parseClasses.find(
|
||||||
|
({ className }) => type === className
|
||||||
|
)
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -112,8 +112,12 @@ const load = function(
|
|||||||
include,
|
include,
|
||||||
['id', 'objectId', 'createdAt', 'updatedAt']
|
['id', 'objectId', 'createdAt', 'updatedAt']
|
||||||
);
|
);
|
||||||
|
const needToGetAllKeys = objectsQueries.needToGetAllKeys(
|
||||||
|
parseClass.fields,
|
||||||
|
keys
|
||||||
|
);
|
||||||
let optimizedObject = {};
|
let optimizedObject = {};
|
||||||
if (needGet) {
|
if (needGet && !needToGetAllKeys) {
|
||||||
optimizedObject = await objectsQueries.getObject(
|
optimizedObject = await objectsQueries.getObject(
|
||||||
className,
|
className,
|
||||||
createdObject.objectId,
|
createdObject.objectId,
|
||||||
@@ -123,7 +127,21 @@ const load = function(
|
|||||||
undefined,
|
undefined,
|
||||||
config,
|
config,
|
||||||
auth,
|
auth,
|
||||||
info
|
info,
|
||||||
|
parseClass
|
||||||
|
);
|
||||||
|
} else if (needToGetAllKeys) {
|
||||||
|
optimizedObject = await objectsQueries.getObject(
|
||||||
|
className,
|
||||||
|
createdObject.objectId,
|
||||||
|
undefined,
|
||||||
|
include,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
config,
|
||||||
|
auth,
|
||||||
|
info,
|
||||||
|
parseClass
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -212,9 +230,12 @@ const load = function(
|
|||||||
include,
|
include,
|
||||||
['id', 'objectId', 'updatedAt']
|
['id', 'objectId', 'updatedAt']
|
||||||
);
|
);
|
||||||
|
const needToGetAllKeys = objectsQueries.needToGetAllKeys(
|
||||||
|
parseClass.fields,
|
||||||
|
keys
|
||||||
|
);
|
||||||
let optimizedObject = {};
|
let optimizedObject = {};
|
||||||
if (needGet) {
|
if (needGet && !needToGetAllKeys) {
|
||||||
optimizedObject = await objectsQueries.getObject(
|
optimizedObject = await objectsQueries.getObject(
|
||||||
className,
|
className,
|
||||||
id,
|
id,
|
||||||
@@ -224,7 +245,21 @@ const load = function(
|
|||||||
undefined,
|
undefined,
|
||||||
config,
|
config,
|
||||||
auth,
|
auth,
|
||||||
info
|
info,
|
||||||
|
parseClass
|
||||||
|
);
|
||||||
|
} else if (needToGetAllKeys) {
|
||||||
|
optimizedObject = await objectsQueries.getObject(
|
||||||
|
className,
|
||||||
|
id,
|
||||||
|
undefined,
|
||||||
|
include,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
config,
|
||||||
|
auth,
|
||||||
|
info,
|
||||||
|
parseClass
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -301,7 +336,8 @@ const load = function(
|
|||||||
undefined,
|
undefined,
|
||||||
config,
|
config,
|
||||||
auth,
|
auth,
|
||||||
info
|
info,
|
||||||
|
parseClass
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await objectsMutations.deleteObject(
|
await objectsMutations.deleteObject(
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const getParseClassQueryConfig = function(
|
|||||||
return (parseClassConfig && parseClassConfig.query) || {};
|
return (parseClassConfig && parseClassConfig.query) || {};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getQuery = async (className, _source, args, context, queryInfo) => {
|
const getQuery = async (parseClass, _source, args, context, queryInfo) => {
|
||||||
let { id } = args;
|
let { id } = args;
|
||||||
const { options } = args;
|
const { options } = args;
|
||||||
const { readPreference, includeReadPreference } = options || {};
|
const { readPreference, includeReadPreference } = options || {};
|
||||||
@@ -23,14 +23,14 @@ const getQuery = async (className, _source, args, context, queryInfo) => {
|
|||||||
|
|
||||||
const globalIdObject = fromGlobalId(id);
|
const globalIdObject = fromGlobalId(id);
|
||||||
|
|
||||||
if (globalIdObject.type === className) {
|
if (globalIdObject.type === parseClass.className) {
|
||||||
id = globalIdObject.id;
|
id = globalIdObject.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { keys, include } = extractKeysAndInclude(selectedFields);
|
const { keys, include } = extractKeysAndInclude(selectedFields);
|
||||||
|
|
||||||
return await objectsQueries.getObject(
|
return await objectsQueries.getObject(
|
||||||
className,
|
parseClass.className,
|
||||||
id,
|
id,
|
||||||
keys,
|
keys,
|
||||||
include,
|
include,
|
||||||
@@ -38,7 +38,8 @@ const getQuery = async (className, _source, args, context, queryInfo) => {
|
|||||||
includeReadPreference,
|
includeReadPreference,
|
||||||
config,
|
config,
|
||||||
auth,
|
auth,
|
||||||
info
|
info,
|
||||||
|
parseClass
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -79,7 +80,7 @@ const load = function(
|
|||||||
),
|
),
|
||||||
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(parseClass, _source, args, context, queryInfo);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
parseGraphQLSchema.handleError(e);
|
parseGraphQLSchema.handleError(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -436,7 +436,7 @@ const load = (
|
|||||||
);
|
);
|
||||||
const parseOrder = order && order.join(',');
|
const parseOrder = order && order.join(',');
|
||||||
|
|
||||||
return await objectsQueries.findObjects(
|
return objectsQueries.findObjects(
|
||||||
source[field].className,
|
source[field].className,
|
||||||
{
|
{
|
||||||
$relatedTo: {
|
$relatedTo: {
|
||||||
|
|||||||
@@ -262,10 +262,12 @@ class ParseServer {
|
|||||||
|
|
||||||
if (options.mountGraphQL === true || options.mountPlayground === true) {
|
if (options.mountGraphQL === true || options.mountPlayground === true) {
|
||||||
let graphQLCustomTypeDefs = undefined;
|
let graphQLCustomTypeDefs = undefined;
|
||||||
if (options.graphQLSchema) {
|
if (typeof options.graphQLSchema === 'string') {
|
||||||
graphQLCustomTypeDefs = parse(
|
graphQLCustomTypeDefs = parse(
|
||||||
fs.readFileSync(options.graphQLSchema, 'utf8')
|
fs.readFileSync(options.graphQLSchema, 'utf8')
|
||||||
);
|
);
|
||||||
|
} else if (typeof options.graphQLSchema === 'object') {
|
||||||
|
graphQLCustomTypeDefs = options.graphQLSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parseGraphQLServer = new ParseGraphQLServer(this, {
|
const parseGraphQLServer = new ParseGraphQLServer(this, {
|
||||||
|
|||||||
Reference in New Issue
Block a user