2016-06-10 20:48:21 -04:00
|
|
|
import {
|
|
|
|
GraphQLSchema,
|
|
|
|
GraphQLResult,
|
|
|
|
Document,
|
|
|
|
parse,
|
|
|
|
validate,
|
|
|
|
execute,
|
|
|
|
} from 'graphql';
|
2016-06-10 17:05:39 -07:00
|
|
|
|
2016-06-24 16:57:52 -04:00
|
|
|
// TODO: maybe return a status as well,
|
|
|
|
// because for HTTP we need to return 200, 400, 405 etc.
|
|
|
|
|
|
|
|
// the annoying thing is that if we want to allow operations over GET
|
|
|
|
// then we need to parse the request before we pass it in to make sure
|
|
|
|
// it's a query and not a mutation or something else.
|
2016-06-14 12:04:28 -07:00
|
|
|
|
2016-06-10 20:48:21 -04:00
|
|
|
export interface GqlResponse {
|
|
|
|
data?: Object;
|
|
|
|
errors?: Array<string>;
|
2016-06-10 17:05:39 -07:00
|
|
|
}
|
|
|
|
|
2016-06-18 10:19:51 -07:00
|
|
|
export interface QueryOptions {
|
|
|
|
schema: GraphQLSchema;
|
|
|
|
query: string | Document;
|
|
|
|
rootValue?: any;
|
|
|
|
context?: any;
|
|
|
|
variables?: { [key: string]: any };
|
|
|
|
operationName?: string;
|
|
|
|
//logFunction?: function => void
|
|
|
|
//validationRules?: No, too risky. If you want extra validation rules, then parse it yourself.
|
|
|
|
}
|
|
|
|
|
|
|
|
function runQuery(options: QueryOptions): Promise<GraphQLResult> {
|
2016-06-10 17:05:39 -07:00
|
|
|
let documentAST: Document;
|
|
|
|
|
2016-06-24 16:57:52 -04:00
|
|
|
// TODO: add loggingFunction
|
|
|
|
|
2016-06-24 17:16:33 -04:00
|
|
|
|
2016-06-10 17:05:39 -07:00
|
|
|
// if query is already an AST, don't parse or validate
|
2016-06-18 10:19:51 -07:00
|
|
|
if (typeof options.query === 'string') {
|
2016-06-10 17:05:39 -07:00
|
|
|
// parse
|
|
|
|
try {
|
2016-06-18 10:19:51 -07:00
|
|
|
documentAST = parse(options.query as string);
|
2016-06-10 17:05:39 -07:00
|
|
|
} catch (syntaxError) {
|
|
|
|
return Promise.resolve({ errors: [syntaxError] });
|
|
|
|
}
|
|
|
|
|
|
|
|
// validate
|
2016-06-18 10:19:51 -07:00
|
|
|
const validationErrors = validate(options.schema, documentAST);
|
2016-06-10 17:05:39 -07:00
|
|
|
if (validationErrors.length) {
|
2016-06-10 20:48:21 -04:00
|
|
|
return Promise.resolve({ errors: validationErrors });
|
2016-06-10 17:05:39 -07:00
|
|
|
}
|
|
|
|
} else {
|
2016-06-18 10:19:51 -07:00
|
|
|
documentAST = options.query as Document;
|
2016-06-24 16:57:52 -04:00
|
|
|
// validate variables here, i.e. noUndefinedVariables, NoUnusedVariables, ArgumentsOfCorrectType?
|
|
|
|
// TODO: the way graphql-js validates this could be inefficient.
|
2016-06-10 17:05:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// execute
|
2016-06-24 16:57:52 -04:00
|
|
|
try {
|
|
|
|
return execute(
|
2016-06-24 17:16:33 -04:00
|
|
|
options.schema,
|
2016-06-24 16:57:52 -04:00
|
|
|
documentAST,
|
2016-06-24 17:16:33 -04:00
|
|
|
options.rootValue,
|
|
|
|
options.context,
|
|
|
|
options.variables,
|
|
|
|
options.operationName
|
2016-06-24 16:57:52 -04:00
|
|
|
);
|
|
|
|
} catch (executionError) {
|
|
|
|
return Promise.resolve({ errors: [ executionError ] });
|
|
|
|
}
|
2016-06-10 17:05:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
export { runQuery };
|