-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GraphQL schema merging reports "Invalid schema passed" #6760
Comments
@Moumouls As the author of the PR, may you have a look at this? I have used your example from the PR. |
@lucatk thanks for report, your schema seems valid for me. |
Note: I currently use this feature extensively on high security projects, with many custom type/query/mutation, it works well. So you probably have a configuration issue here 😃 |
Thanks for taking a look at it :) As I said, I have copied most of the boilerplate from the cli/ directory, so here's my startup script: const path = require('path');
const definitions = require('parse-server/lib/Options/Definitions').ParseServerOptions;
const ParseServer = require('parse-server').default;
const { GraphQLSchema, GraphQLObjectType, GraphQLNonNull, GraphQLString } = require('graphql');
function parseConfigFile() {
let options = {};
const jsonPath = path.resolve('/parse/config/config.json');
const jsonConfig = require(jsonPath);
if (jsonConfig.apps) {
if (jsonConfig.apps.length > 1) {
throw 'Multiple apps are not supported';
}
options = jsonConfig.apps[0];
} else {
options = jsonConfig;
}
Object.keys(options).forEach(key => {
const value = options[key];
if (!definitions[key]) {
throw `error: unknown option ${key}`;
}
const action = definitions[key].action;
if (action) {
options[key] = action(value);
}
});
console.log(`Configuration loaded from ${jsonPath}`);
return options;
}
function getOptions(_opts) {
return Object.keys(definitions).reduce((options, key) => {
if (typeof _opts[key] !== 'undefined') {
options[key] = _opts[key];
}
return options;
}, {});
}
function logStartupOptions(options) {
for (const key in options) {
let value = options[key];
if (key == 'masterKey') {
value = '***REDACTED***';
}
if (key == 'push' && options.verbose != true) {
value = '***REDACTED***';
}
if (typeof value === 'object') {
try {
value = JSON.stringify(value);
} catch (e) {
if (value && value.constructor && value.constructor.name) {
value = value.constructor.name;
}
}
}
/* eslint-disable no-console */
console.log(`${key}: ${value}`);
/* eslint-enable no-console */
}
}
function printSuccessMessage() {
console.log(
'[' + process.pid + '] Wherr parse-server running on ' + options.serverURL
);
if (options.mountGraphQL) {
console.log(
'[' +
process.pid +
'] GraphQL running on http://localhost:' +
options.port +
options.graphQLPath
);
}
if (options.mountPlayground) {
console.log(
'[' +
process.pid +
'] Playground running on http://localhost:' +
options.port +
options.playgroundPath
);
}
}
const options = getOptions(parseConfigFile());
options.graphQLSchema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
// Here we define a custom Query field with the associated resolver
customQuery: {
type: new GraphQLNonNull(GraphQLString),
args: {
message: { type: new GraphQLNonNull(GraphQLString) },
},
resolve: (source, args, context, queryInfo) => {
console.log('source', source);
console.log('args', args);
console.log('context', context);
console.log('queryInfo', queryInfo);
return args.message;
},
},
},
}),
});
// TODO: cluster work (https://github.com/parse-community/parse-server/blob/67bf868208f8906793143a20eef4987b2cbffc9d/src/cli/parse-server.js#L69)
ParseServer.start(options, () => {
logStartupOptions(options);
console.log('');
printSuccessMessage();
}); So my options object should just consist of the data I get from my config.json and the passed in custom schema. {
"appId": "***",
"cloud": "/parse/cloud/index.js",
"databaseURI": "mongodb://mongo/parse",
"javascriptKey": "***",
"masterKey": "***",
"mountGraphQL": true,
"restAPIKey": "***",
"graphQLSchema": {
"_queryType": "Query",
"_directives": [
"@include",
"@skip",
"@deprecated",
"@specifiedBy"
],
"_typeMap": {
"Query": "Query",
"String": "String",
"Boolean": "Boolean",
"__Schema": "__Schema",
"__Type": "__Type",
"__TypeKind": "__TypeKind",
"__Field": "__Field",
"__InputValue": "__InputValue",
"__EnumValue": "__EnumValue",
"__Directive": "__Directive",
"__DirectiveLocation": "__DirectiveLocation"
},
"_subTypeMap": {},
"_implementationsMap": {}
},
"allowClientClassCreation": true,
"allowCustomObjectId": false,
"cacheMaxSize": 10000,
"cacheTTL": 5000,
"collectionPrefix": "",
"customPages": {},
"directAccess": false,
"enableAnonymousUsers": true,
"enableExpressErrorHandler": false,
"enableSingleSchemaCache": false,
"expireInactiveSessions": true,
"graphQLPath": "/graphql",
"host": "0.0.0.0",
"logsFolder": "./logs/",
"masterKeyIps": [],
"maxUploadSize": "20mb",
"mountPath": "/parse",
"mountPlayground": false,
"objectIdSize": 10,
"playgroundPath": "/playground",
"port": 1337,
"preserveFileName": false,
"preventLoginWithUnverifiedEmail": false,
"protectedFields": {
"_User": {
"*": [
"email"
]
}
},
"revokeSessionOnPasswordReset": true,
"scheduledPush": false,
"schemaCacheTTL": 5000,
"sessionLength": 31536000,
"verifyUserEmails": false,
"jsonLogs": false,
"verbose": false,
"serverURL": "http://localhost:1337/parse"
} |
Additional question, what is your parse server version ? |
It's 4.2.0, installed from NPM. |
However, starting without the custom schema works out perfectly, and everything's normal. |
Seems like I resolved the issue! |
@lucatk thanks for your investigation. Graphql package is hyper sensitive on versions (instances of GraphQLSchema are different from one version to another), and lead to merging issues. |
Issue Description
After reading #6360 I attempted to pass a custom graphql schema into Parse options, just like the example suggests. (see code below)
However, /graphql ceases to respond and outputs an error to the console.
I am pretty sure I have just missed some little detail, but after extensive research I can't find it. There's not much documentation around supplying a custom schema (except for the PR or supplying a .graphql file and using a Cloud Code-based resolver, which doesn't suffice for my use case, though), so I'd appreciate a slight nudge in the right direction.. :)
Steps to reproduce
Expected Results
The request should resolve and graphql should be usable. My custom query should be usable.
Actual Outcome
/graphql does not respond. Errors in console. (see below)
Environment Setup
Server
Database
Logs/Trace
The text was updated successfully, but these errors were encountered: