Socket
Socket
Sign inDemoInstall

apollo-server-core

Package Overview
Dependencies
Maintainers
5
Versions
314
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

apollo-server-core - npm Package Compare versions

Comparing version 1.3.2 to 1.3.3

1

dist/graphqlOptions.d.ts

@@ -19,2 +19,1 @@ import { GraphQLSchema, ValidationContext, GraphQLFieldResolver } from 'graphql';

export declare function resolveGraphqlOptions(options: GraphQLServerOptions | Function, ...args: any[]): Promise<GraphQLServerOptions>;
export declare function isOptionsFunction(arg: GraphQLServerOptions | Function): arg is Function;

@@ -48,3 +48,3 @@ "use strict";

case 0:
if (!isOptionsFunction(options)) return [3, 5];
if (!(typeof options === 'function')) return [3, 5];
_a.label = 1;

@@ -66,6 +66,2 @@ case 1:

exports.resolveGraphqlOptions = resolveGraphqlOptions;
function isOptionsFunction(arg) {
return typeof arg === 'function';
}
exports.isOptionsFunction = isOptionsFunction;
//# sourceMappingURL=graphqlOptions.js.map

13

dist/runHttpQuery.js

@@ -69,5 +69,2 @@ "use strict";

}
function isFunction(arg) {
return typeof arg === 'function';
}
function runHttpQuery(handlerArguments, request) {

@@ -94,3 +91,3 @@ return __awaiter(this, void 0, void 0, function () {

case 'POST':
if (!request.query || (Object.keys(request.query).length === 0)) {
if (!request.query || Object.keys(request.query).length === 0) {
throw new HttpQueryError(500, 'POST body missing. Did you forget use body-parser middleware?');

@@ -101,3 +98,3 @@ }

case 'GET':
if (!request.query || (Object.keys(request.query).length === 0)) {
if (!request.query || Object.keys(request.query).length === 0) {
throw new HttpQueryError(400, 'GET query missing.');

@@ -110,3 +107,3 @@ }

throw new HttpQueryError(405, 'Apollo Server supports only GET/POST requests.', false, {
'Allow': 'GET, POST',
Allow: 'GET, POST',
});

@@ -128,3 +125,3 @@ }

throw new HttpQueryError(405, "GET supports only query operation", false, {
'Allow': 'POST',
Allow: 'POST',
});

@@ -144,3 +141,3 @@ }

var context_1 = optionsObject.context || {};
if (isFunction(context_1)) {
if (typeof context_1 === 'function') {
context_1 = context_1();

@@ -147,0 +144,0 @@ }

@@ -45,3 +45,2 @@ import { GraphQLSchema, GraphQLFieldResolver, DocumentNode, GraphQLError, ValidationContext } from 'graphql';

}
declare function runQuery(options: QueryOptions): Promise<GraphQLResponse>;
export { runQuery };
export declare function runQuery(options: QueryOptions): Promise<GraphQLResponse>;

@@ -20,12 +20,34 @@ "use strict";

})(LogStep = exports.LogStep || (exports.LogStep = {}));
var resolvedPromise = Promise.resolve();
function runQuery(options) {
return resolvedPromise.then(function () { return doRunQuery(options); });
return Promise.resolve().then(function () { return doRunQuery(options); });
}
exports.runQuery = runQuery;
function printStackTrace(error) {
console.error(error.stack);
}
function format(errors, formatter) {
return errors.map(function (error) {
if (formatter !== undefined) {
try {
return formatter(error);
}
catch (err) {
console.error('Error in formatError function:', err);
var newError = new Error('Internal server error');
return graphql_1.formatError(newError);
}
}
else {
return graphql_1.formatError(error);
}
});
}
function doRunQuery(options) {
var documentAST;
var logFunction = options.logFunction || function () { return null; };
var logFunction = options.logFunction ||
function () {
return null;
};
var debugDefault = process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test';
var debug = typeof options.debug !== 'undefined' ? options.debug : debugDefault;
var debug = options.debug !== undefined ? options.debug : debugDefault;
logFunction({ action: LogAction.request, step: LogStep.start });

@@ -46,26 +68,21 @@ var context = options.context || {};

}
function format(errors) {
return errors.map(function (error) {
if (options.formatError) {
try {
return options.formatError(error);
}
catch (err) {
console.error('Error in formatError function:', err);
var newError = new Error('Internal server error');
return graphql_1.formatError(newError);
}
}
else {
return graphql_1.formatError(error);
}
});
}
function printStackTrace(error) {
console.error(error.stack);
}
var qry = typeof options.query === 'string' ? options.query : graphql_1.print(options.query);
logFunction({ action: LogAction.request, step: LogStep.status, key: 'query', data: qry });
logFunction({ action: LogAction.request, step: LogStep.status, key: 'variables', data: options.variables });
logFunction({ action: LogAction.request, step: LogStep.status, key: 'operationName', data: options.operationName });
logFunction({
action: LogAction.request,
step: LogStep.status,
key: 'query',
data: qry,
});
logFunction({
action: LogAction.request,
step: LogStep.status,
key: 'variables',
data: options.variables,
});
logFunction({
action: LogAction.request,
step: LogStep.status,
key: 'operationName',
data: options.operationName,
});
if (typeof options.query === 'string') {

@@ -79,3 +96,5 @@ try {

logFunction({ action: LogAction.parse, step: LogStep.end });
return Promise.resolve({ errors: format([syntaxError]) });
return Promise.resolve({
errors: format([syntaxError], options.formatError),
});
}

@@ -94,3 +113,5 @@ }

if (validationErrors.length) {
return Promise.resolve({ errors: format(validationErrors) });
return Promise.resolve({
errors: format(validationErrors, options.formatError),
});
}

@@ -109,3 +130,3 @@ if (extensionStack) {

if (result.errors) {
response.errors = format(result.errors);
response.errors = format(result.errors, options.formatError);
if (debug) {

@@ -129,5 +150,7 @@ result.errors.map(printStackTrace);

logFunction({ action: LogAction.request, step: LogStep.end });
return Promise.resolve({ errors: format([executionError]) });
return Promise.resolve({
errors: format([executionError], options.formatError),
});
}
}
//# sourceMappingURL=runQuery.js.map
{
"name": "apollo-server-core",
"version": "1.3.2",
"version": "1.3.3",
"description": "Core engine for Apollo GraphQL server",

@@ -28,10 +28,10 @@ "main": "dist/index.js",

"devDependencies": {
"@types/fibers": "0.0.29",
"@types/graphql": "0.11.7",
"@types/fibers": "0.0.30",
"@types/graphql": "0.12.6",
"fibers": "1.0.15",
"meteor-promise": "0.8.6",
"typescript": "2.6.2"
"typescript": "2.7.2"
},
"peerDependencies": {
"graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0"
"graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0"
},

@@ -38,0 +38,0 @@ "typings": "dist/index.d.ts",

@@ -1,2 +0,6 @@

import { GraphQLSchema, ValidationContext, GraphQLFieldResolver } from 'graphql';
import {
GraphQLSchema,
ValidationContext,
GraphQLFieldResolver,
} from 'graphql';
import { LogFunction } from './runQuery';

@@ -37,4 +41,7 @@ import { GraphQLExtension } from 'graphql-extensions';

export async function resolveGraphqlOptions(options: GraphQLServerOptions | Function, ...args): Promise<GraphQLServerOptions> {
if (isOptionsFunction(options)) {
export async function resolveGraphqlOptions(
options: GraphQLServerOptions | Function,
...args
): Promise<GraphQLServerOptions> {
if (typeof options === 'function') {
try {

@@ -49,5 +56,1 @@ return await options(...args);

}
export function isOptionsFunction(arg: GraphQLServerOptions | Function): arg is Function {
return typeof arg === 'function';
}

@@ -1,4 +0,12 @@

export { runQuery, LogFunction, LogMessage, LogStep, LogAction } from './runQuery';
export {
runQuery,
LogFunction,
LogMessage,
LogStep,
LogAction,
} from './runQuery';
export { runHttpQuery, HttpQueryRequest, HttpQueryError } from './runHttpQuery';
export { default as GraphQLOptions, resolveGraphqlOptions } from './graphqlOptions';
export {
default as GraphQLOptions,
resolveGraphqlOptions,
} from './graphqlOptions';

@@ -1,4 +0,13 @@

import { parse, getOperationAST, DocumentNode, formatError, ExecutionResult } from 'graphql';
import {
parse,
getOperationAST,
DocumentNode,
formatError,
ExecutionResult,
} from 'graphql';
import { runQuery } from './runQuery';
import { default as GraphQLOptions, resolveGraphqlOptions } from './graphqlOptions';
import {
default as GraphQLOptions,
resolveGraphqlOptions,
} from './graphqlOptions';

@@ -16,3 +25,8 @@ export interface HttpQueryRequest {

constructor (statusCode: number, message: string, isGraphQLError: boolean = false, headers?: { [key: string]: string }) {
constructor(
statusCode: number,
message: string,
isGraphQLError: boolean = false,
headers?: { [key: string]: string },
) {
super(message);

@@ -31,7 +45,6 @@ this.name = 'HttpQueryError';

function isFunction(arg: any): arg is Function {
return typeof arg === 'function';
}
export async function runHttpQuery(handlerArguments: Array<any>, request: HttpQueryRequest): Promise<string> {
export async function runHttpQuery(
handlerArguments: Array<any>,
request: HttpQueryRequest,
): Promise<string> {
let isGetRequest: boolean = false;

@@ -41,3 +54,6 @@ let optionsObject: GraphQLOptions;

try {
optionsObject = await resolveGraphqlOptions(request.options, ...handlerArguments);
optionsObject = await resolveGraphqlOptions(
request.options,
...handlerArguments,
);
} catch (e) {

@@ -49,6 +65,9 @@ throw new HttpQueryError(500, e.message);

switch ( request.method ) {
switch (request.method) {
case 'POST':
if ( !request.query || (Object.keys(request.query).length === 0) ) {
throw new HttpQueryError(500, 'POST body missing. Did you forget use body-parser middleware?');
if (!request.query || Object.keys(request.query).length === 0) {
throw new HttpQueryError(
500,
'POST body missing. Did you forget use body-parser middleware?',
);
}

@@ -58,15 +77,20 @@

break;
case 'GET':
if ( !request.query || (Object.keys(request.query).length === 0) ) {
throw new HttpQueryError(400, 'GET query missing.');
}
case 'GET':
if (!request.query || Object.keys(request.query).length === 0) {
throw new HttpQueryError(400, 'GET query missing.');
}
isGetRequest = true;
requestPayload = request.query;
break;
isGetRequest = true;
requestPayload = request.query;
break;
default:
throw new HttpQueryError(405, 'Apollo Server supports only GET/POST requests.', false, {
'Allow': 'GET, POST',
});
default:
throw new HttpQueryError(
405,
'Apollo Server supports only GET/POST requests.',
false,
{
Allow: 'GET, POST',
},
);
}

@@ -85,3 +109,3 @@

let query = requestParams.query;
if ( isGetRequest ) {
if (isGetRequest) {
if (typeof query === 'string') {

@@ -92,6 +116,11 @@ // preparse the query incase of GET so we can assert the operation.

if ( ! isQueryOperation(query, requestParams.operationName) ) {
throw new HttpQueryError(405, `GET supports only query operation`, false, {
'Allow': 'POST',
});
if (!isQueryOperation(query, requestParams.operationName)) {
throw new HttpQueryError(
405,
`GET supports only query operation`,
false,
{
Allow: 'POST',
},
);
}

@@ -112,6 +141,9 @@ }

let context = optionsObject.context || {};
if (isFunction(context)) {
if (typeof context === 'function') {
context = context();
} else if (isBatch) {
context = Object.assign(Object.create(Object.getPrototypeOf(context)), context);
context = Object.assign(
Object.create(Object.getPrototypeOf(context)),
context,
);
}

@@ -144,3 +176,3 @@

// convert it to Http Error.
if ( e.name === 'HttpQueryError' ) {
if (e.name === 'HttpQueryError') {
return Promise.reject(e);

@@ -147,0 +179,0 @@ }

@@ -7,15 +7,11 @@ /* tslint:disable:no-unused-expression */

import {
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLNonNull,
parse,
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLNonNull,
parse,
} from 'graphql';
import {
runQuery,
LogAction,
LogStep,
} from './runQuery';
import { runQuery, LogAction, LogStep } from './runQuery';

@@ -29,66 +25,66 @@ // Make the global Promise constructor Fiber-aware to simulate a Meteor

const queryType = new GraphQLObjectType({
name: 'QueryType',
fields: {
testString: {
name: 'QueryType',
fields: {
testString: {
type: GraphQLString,
resolve() {
return 'it works';
},
},
testObject: {
type: new GraphQLObjectType({
name: 'TestObject',
fields: {
testString: {
type: GraphQLString,
resolve() {
return 'it works';
},
},
testObject: {
type: new GraphQLObjectType({
name: 'TestObject',
fields: {
testString: {
type: GraphQLString,
},
},
}),
resolve() {
return {
testString: 'a very test string',
};
},
},
testRootValue: {
type: GraphQLString,
resolve(root) {
return root + ' works';
},
},
testContextValue: {
type: GraphQLString,
resolve(root, args, context) {
return context + ' works';
},
},
testArgumentValue: {
type: GraphQLInt,
resolve(root, args, context) {
return args['base'] + 5;
},
args: {
base: { type: new GraphQLNonNull(GraphQLInt) },
},
},
testAwaitedValue: {
type: GraphQLString,
resolve(root) {
// Calling Promise.await is legal here even though this is
// not an async function, because we are guaranteed to be
// running in a Fiber.
return 'it ' + (<any>Promise).await('works');
},
},
testError: {
type: GraphQLString,
resolve() {
throw new Error('Secret error message');
},
},
}),
resolve() {
return {
testString: 'a very test string',
};
},
},
testRootValue: {
type: GraphQLString,
resolve(root) {
return root + ' works';
},
},
testContextValue: {
type: GraphQLString,
resolve(root, args, context) {
return context + ' works';
},
},
testArgumentValue: {
type: GraphQLInt,
resolve(root, args, context) {
return args['base'] + 5;
},
args: {
base: { type: new GraphQLNonNull(GraphQLInt) },
},
},
testAwaitedValue: {
type: GraphQLString,
resolve(root) {
// Calling Promise.await is legal here even though this is
// not an async function, because we are guaranteed to be
// running in a Fiber.
return 'it ' + (<any>Promise).await('works');
},
},
testError: {
type: GraphQLString,
resolve() {
throw new Error('Secret error message');
},
},
},
});
const schema = new GraphQLSchema({
query: queryType,
query: queryType,
});

@@ -98,17 +94,15 @@

it('returns the right result when query is a string', () => {
const query = `{ testString }`;
const expected = { testString: 'it works' };
return runQuery({ schema, query: query })
.then((res) => {
return expect(res.data).to.deep.equal(expected);
});
const query = `{ testString }`;
const expected = { testString: 'it works' };
return runQuery({ schema, query: query }).then(res => {
return expect(res.data).to.deep.equal(expected);
});
});
it('returns the right result when query is a document', () => {
const query = parse(`{ testString }`);
const expected = { testString: 'it works' };
return runQuery({ schema, query: query })
.then((res) => {
return expect(res.data).to.deep.equal(expected);
});
const query = parse(`{ testString }`);
const expected = { testString: 'it works' };
return runQuery({ schema, query: query }).then(res => {
return expect(res.data).to.deep.equal(expected);
});
});

@@ -120,9 +114,9 @@

return runQuery({
schema,
query: query,
variables: { base: 1 },
}).then((res) => {
expect(res.data).to.be.undefined;
expect(res.errors.length).to.equal(1);
return expect(res.errors[0].message).to.match(expected);
schema,
query: query,
variables: { base: 1 },
}).then(res => {
expect(res.data).to.be.undefined;
expect(res.errors.length).to.equal(1);
return expect(res.errors[0].message).to.match(expected);
});

@@ -136,9 +130,9 @@ });

return runQuery({
schema,
query: query,
debug: true,
}).then((res) => {
logStub.restore();
expect(logStub.callCount).to.equal(1);
return expect(logStub.getCall(0).args[0]).to.match(expected);
schema,
query: query,
debug: true,
}).then(res => {
logStub.restore();
expect(logStub.callCount).to.equal(1);
return expect(logStub.getCall(0).args[0]).to.match(expected);
});

@@ -151,8 +145,8 @@ });

return runQuery({
schema,
query: query,
debug: false,
}).then((res) => {
logStub.restore();
return expect(logStub.callCount).to.equal(0);
schema,
query: query,
debug: false,
}).then(res => {
logStub.restore();
return expect(logStub.callCount).to.equal(0);
});

@@ -162,87 +156,88 @@ });

it('returns a validation error if the query string does not pass validation', () => {
const query = `query TestVar($base: String){ testArgumentValue(base: $base) }`;
const expected = 'Variable "$base" of type "String" used in position expecting type "Int!".';
return runQuery({
schema,
query: query,
variables: { base: 1 },
}).then((res) => {
expect(res.data).to.be.undefined;
expect(res.errors.length).to.equal(1);
return expect(res.errors[0].message).to.deep.equal(expected);
});
const query = `query TestVar($base: String){ testArgumentValue(base: $base) }`;
const expected =
'Variable "$base" of type "String" used in position expecting type "Int!".';
return runQuery({
schema,
query: query,
variables: { base: 1 },
}).then(res => {
expect(res.data).to.be.undefined;
expect(res.errors.length).to.equal(1);
return expect(res.errors[0].message).to.deep.equal(expected);
});
});
it('correctly passes in the rootValue', () => {
const query = `{ testRootValue }`;
const expected = { testRootValue: 'it also works' };
return runQuery({ schema, query: query, rootValue: 'it also' })
.then((res) => {
return expect(res.data).to.deep.equal(expected);
});
const query = `{ testRootValue }`;
const expected = { testRootValue: 'it also works' };
return runQuery({ schema, query: query, rootValue: 'it also' }).then(
res => {
return expect(res.data).to.deep.equal(expected);
},
);
});
it('correctly passes in the context', () => {
const query = `{ testContextValue }`;
const expected = { testContextValue: 'it still works' };
return runQuery({ schema, query: query, context: 'it still' })
.then((res) => {
return expect(res.data).to.deep.equal(expected);
});
const query = `{ testContextValue }`;
const expected = { testContextValue: 'it still works' };
return runQuery({ schema, query: query, context: 'it still' }).then(res => {
return expect(res.data).to.deep.equal(expected);
});
});
it('passes the options to formatResponse', () => {
const query = `{ testContextValue }`;
const expected = { testContextValue: 'it still works' };
return runQuery({
schema,
query: query,
context: 'it still',
formatResponse: (response, { context }) => {
response['extensions'] = context;
return response;
},
})
.then((res) => {
expect(res.data).to.deep.equal(expected);
return expect(res['extensions']).to.equal('it still');
});
const query = `{ testContextValue }`;
const expected = { testContextValue: 'it still works' };
return runQuery({
schema,
query: query,
context: 'it still',
formatResponse: (response, { context }) => {
response['extensions'] = context;
return response;
},
}).then(res => {
expect(res.data).to.deep.equal(expected);
return expect(res['extensions']).to.equal('it still');
});
});
it('correctly passes in variables (and arguments)', () => {
const query = `query TestVar($base: Int!){ testArgumentValue(base: $base) }`;
const expected = { testArgumentValue: 6 };
return runQuery({
schema,
query: query,
variables: { base: 1 },
}).then((res) => {
return expect(res.data).to.deep.equal(expected);
});
const query = `query TestVar($base: Int!){ testArgumentValue(base: $base) }`;
const expected = { testArgumentValue: 6 };
return runQuery({
schema,
query: query,
variables: { base: 1 },
}).then(res => {
return expect(res.data).to.deep.equal(expected);
});
});
it('throws an error if there are missing variables', () => {
const query = `query TestVar($base: Int!){ testArgumentValue(base: $base) }`;
const expected = 'Variable "$base" of required type "Int!" was not provided.';
return runQuery({
schema,
query: query,
}).then((res) => {
return expect(res.errors[0].message).to.deep.equal(expected);
});
const query = `query TestVar($base: Int!){ testArgumentValue(base: $base) }`;
const expected =
'Variable "$base" of required type "Int!" was not provided.';
return runQuery({
schema,
query: query,
}).then(res => {
return expect(res.errors[0].message).to.deep.equal(expected);
});
});
it('supports yielding resolver functions', () => {
return runQuery({
schema,
query: `{ testAwaitedValue }`,
}).then((res) => {
expect(res.data).to.deep.equal({
testAwaitedValue: 'it works',
});
});
it('supports yielding resolver functions', () => {
return runQuery({
schema,
query: `{ testAwaitedValue }`,
}).then(res => {
expect(res.data).to.deep.equal({
testAwaitedValue: 'it works',
});
});
});
it('runs the correct operation when operationName is specified', () => {
const query = `
it('runs the correct operation when operationName is specified', () => {
const query = `
query Q1 {

@@ -254,41 +249,60 @@ testString

}`;
const expected = {
testString: 'it works',
};
return runQuery({ schema, query: query, operationName: 'Q1' })
.then((res) => {
return expect(res.data).to.deep.equal(expected);
});
const expected = {
testString: 'it works',
};
return runQuery({ schema, query: query, operationName: 'Q1' }).then(res => {
return expect(res.data).to.deep.equal(expected);
});
});
it('calls logFunction', () => {
const query = `
it('calls logFunction', () => {
const query = `
query Q1 {
testString
}`;
const logs = [];
const logFn = (obj) => logs.push(obj);
const expected = {
testString: 'it works',
};
return runQuery({
schema,
query: query,
operationName: 'Q1',
variables: { test: 123 },
logFunction: logFn,
})
.then((res) => {
expect(res.data).to.deep.equal(expected);
expect(logs.length).to.equals(11);
expect(logs[0]).to.deep.equals({action: LogAction.request, step: LogStep.start});
expect(logs[1]).to.deep.equals({action: LogAction.request, step: LogStep.status, key: 'query', data: query});
expect(logs[2]).to.deep.equals({action: LogAction.request, step: LogStep.status, key: 'variables', data: { test: 123 }});
expect(logs[3]).to.deep.equals({action: LogAction.request, step: LogStep.status, key: 'operationName', data: 'Q1'});
expect(logs[10]).to.deep.equals({action: LogAction.request, step: LogStep.end});
});
const logs = [];
const logFn = obj => logs.push(obj);
const expected = {
testString: 'it works',
};
return runQuery({
schema,
query: query,
operationName: 'Q1',
variables: { test: 123 },
logFunction: logFn,
}).then(res => {
expect(res.data).to.deep.equal(expected);
expect(logs.length).to.equals(11);
expect(logs[0]).to.deep.equals({
action: LogAction.request,
step: LogStep.start,
});
expect(logs[1]).to.deep.equals({
action: LogAction.request,
step: LogStep.status,
key: 'query',
data: query,
});
expect(logs[2]).to.deep.equals({
action: LogAction.request,
step: LogStep.status,
key: 'variables',
data: { test: 123 },
});
expect(logs[3]).to.deep.equals({
action: LogAction.request,
step: LogStep.status,
key: 'operationName',
data: 'Q1',
});
expect(logs[10]).to.deep.equals({
action: LogAction.request,
step: LogStep.end,
});
});
});
it('uses custom field resolver', async () => {
const query = `
it('uses custom field resolver', async () => {
const query = `
query Q1 {

@@ -301,27 +315,71 @@ testObject {

const result1 = await runQuery({
schema,
query: query,
operationName: 'Q1',
});
const result1 = await runQuery({
schema,
query: query,
operationName: 'Q1',
});
expect(result1.data).to.deep.equal({
testObject: {
testString: 'a very test string',
},
});
expect(result1.data).to.deep.equal({
testObject: {
testString: 'a very test string',
},
});
const result2 = await runQuery({
schema,
query: query,
operationName: 'Q1',
fieldResolver: () => 'a very testful field resolver string',
const result2 = await runQuery({
schema,
query: query,
operationName: 'Q1',
fieldResolver: () => 'a very testful field resolver string',
});
expect(result2.data).to.deep.equal({
testObject: {
testString: 'a very testful field resolver string',
},
});
});
describe('async_hooks', () => {
let asyncHooks;
let asyncHook;
const ids: number[] = [];
try {
asyncHooks = require('async_hooks');
} catch (err) {
return; // async_hooks not present, give up
}
before(() => {
asyncHook = asyncHooks.createHook({ init: asyncId => ids.push(asyncId) });
asyncHook.enable();
});
after(() => {
asyncHook.disable();
});
it('does not break async_hook call stack', async () => {
const query = `
query Q1 {
testObject {
testString
}
}
`;
await runQuery({
schema,
query: query,
operationName: 'Q1',
});
expect(result2.data).to.deep.equal({
testObject: {
testString: 'a very testful field resolver string',
},
// this is the only async process so we expect the async ids to be a sequence
ids.forEach((id, i) => {
if (i > 0) {
expect(id).to.equal(ids[i - 1] + 1);
}
});
});
});
});
import {
GraphQLSchema,
GraphQLFieldResolver,
ExecutionResult,
DocumentNode,
parse,
print,
validate,
execute,
GraphQLError,
formatError,
specifiedRules,
ValidationContext,
GraphQLSchema,
GraphQLFieldResolver,
ExecutionResult,
DocumentNode,
parse,
print,
validate,
execute,
GraphQLError,
formatError,
specifiedRules,
ValidationContext,
} from 'graphql';
import { enableGraphQLExtensions, GraphQLExtension, GraphQLExtensionStack } from 'graphql-extensions';
import {
enableGraphQLExtensions,
GraphQLExtension,
GraphQLExtensionStack,
} from 'graphql-extensions';
import { TracingExtension } from 'apollo-tracing';

@@ -27,7 +31,12 @@ import { CacheControlExtension } from 'apollo-cache-control';

export enum LogAction {
request, parse, validation, execute,
request,
parse,
validation,
execute,
}
export enum LogStep {
start, end, status,
start,
end,
status,
}

@@ -47,153 +56,179 @@

export interface QueryOptions {
schema: GraphQLSchema;
query: string | DocumentNode;
rootValue?: any;
context?: any;
variables?: { [key: string]: any };
operationName?: string;
logFunction?: LogFunction;
validationRules?: Array<(context: ValidationContext) => any>;
fieldResolver?: GraphQLFieldResolver<any, any>;
// WARNING: these extra validation rules are only applied to queries
// submitted as string, not those submitted as Document!
schema: GraphQLSchema;
query: string | DocumentNode;
rootValue?: any;
context?: any;
variables?: { [key: string]: any };
operationName?: string;
logFunction?: LogFunction;
validationRules?: Array<(context: ValidationContext) => any>;
fieldResolver?: GraphQLFieldResolver<any, any>;
// WARNING: these extra validation rules are only applied to queries
// submitted as string, not those submitted as Document!
formatError?: Function;
formatResponse?: Function;
debug?: boolean;
tracing?: boolean;
cacheControl?: boolean;
formatError?: Function;
formatResponse?: Function;
debug?: boolean;
tracing?: boolean;
cacheControl?: boolean;
}
const resolvedPromise = Promise.resolve();
export function runQuery(options: QueryOptions): Promise<GraphQLResponse> {
// Fiber-aware Promises run their .then callbacks in Fibers.
return Promise.resolve().then(() => doRunQuery(options));
}
function runQuery(options: QueryOptions): Promise<GraphQLResponse> {
// Fiber-aware Promises run their .then callbacks in Fibers.
return resolvedPromise.then(() => doRunQuery(options));
function printStackTrace(error: Error) {
console.error(error.stack);
}
function format(errors: Array<Error>, formatter?: Function): Array<Error> {
return errors.map(error => {
if (formatter !== undefined) {
try {
return formatter(error);
} catch (err) {
console.error('Error in formatError function:', err);
const newError = new Error('Internal server error');
return formatError(newError);
}
} else {
return formatError(error);
}
}) as Array<Error>;
}
function doRunQuery(options: QueryOptions): Promise<GraphQLResponse> {
let documentAST: DocumentNode;
let documentAST: DocumentNode;
const logFunction = options.logFunction || function(){ return null; };
const debugDefault = process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test';
const debug = typeof options.debug !== 'undefined' ? options.debug : debugDefault;
const logFunction =
options.logFunction ||
function() {
return null;
};
const debugDefault =
process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test';
const debug = options.debug !== undefined ? options.debug : debugDefault;
logFunction({action: LogAction.request, step: LogStep.start});
logFunction({ action: LogAction.request, step: LogStep.start });
const context = options.context || {};
let extensions = [];
if (options.tracing) {
extensions.push(TracingExtension);
}
if (options.cacheControl) {
extensions.push(CacheControlExtension);
}
const extensionStack = extensions.length > 0 && new GraphQLExtensionStack(extensions);
const context = options.context || {};
let extensions = [];
if (options.tracing) {
extensions.push(TracingExtension);
}
if (options.cacheControl) {
extensions.push(CacheControlExtension);
}
const extensionStack =
extensions.length > 0 && new GraphQLExtensionStack(extensions);
if (extensionStack) {
context._extensionStack = extensionStack;
enableGraphQLExtensions(options.schema);
if (extensionStack) {
context._extensionStack = extensionStack;
enableGraphQLExtensions(options.schema);
extensionStack.requestDidStart();
}
extensionStack.requestDidStart();
}
function format(errors: Array<Error>): Array<Error> {
return errors.map((error) => {
if (options.formatError) {
try {
return options.formatError(error);
} catch (err) {
console.error('Error in formatError function:', err);
const newError = new Error('Internal server error');
return formatError(newError);
}
} else {
return formatError(error);
}
}) as Array<Error>;
}
const qry =
typeof options.query === 'string' ? options.query : print(options.query);
logFunction({
action: LogAction.request,
step: LogStep.status,
key: 'query',
data: qry,
});
logFunction({
action: LogAction.request,
step: LogStep.status,
key: 'variables',
data: options.variables,
});
logFunction({
action: LogAction.request,
step: LogStep.status,
key: 'operationName',
data: options.operationName,
});
function printStackTrace(error: Error) {
console.error(error.stack);
// if query is already an AST, don't parse or validate
// XXX: This refers the operations-store flow.
if (typeof options.query === 'string') {
try {
logFunction({ action: LogAction.parse, step: LogStep.start });
documentAST = parse(options.query as string);
logFunction({ action: LogAction.parse, step: LogStep.end });
} catch (syntaxError) {
logFunction({ action: LogAction.parse, step: LogStep.end });
return Promise.resolve({
errors: format([syntaxError], options.formatError),
});
}
} else {
documentAST = options.query as DocumentNode;
}
const qry = typeof options.query === 'string' ? options.query : print(options.query);
logFunction({action: LogAction.request, step: LogStep.status, key: 'query', data: qry});
logFunction({action: LogAction.request, step: LogStep.status, key: 'variables', data: options.variables});
logFunction({action: LogAction.request, step: LogStep.status, key: 'operationName', data: options.operationName});
let rules = specifiedRules;
if (options.validationRules) {
rules = rules.concat(options.validationRules);
}
logFunction({ action: LogAction.validation, step: LogStep.start });
const validationErrors = validate(options.schema, documentAST, rules);
logFunction({ action: LogAction.validation, step: LogStep.end });
if (validationErrors.length) {
return Promise.resolve({
errors: format(validationErrors, options.formatError),
});
}
// if query is already an AST, don't parse or validate
// XXX: This refers the operations-store flow.
if (typeof options.query === 'string') {
try {
logFunction({action: LogAction.parse, step: LogStep.start});
documentAST = parse(options.query as string);
logFunction({action: LogAction.parse, step: LogStep.end});
} catch (syntaxError) {
logFunction({action: LogAction.parse, step: LogStep.end});
return Promise.resolve({ errors: format([syntaxError]) });
}
} else {
documentAST = options.query as DocumentNode;
}
if (extensionStack) {
extensionStack.executionDidStart();
}
let rules = specifiedRules;
if (options.validationRules) {
rules = rules.concat(options.validationRules);
}
logFunction({action: LogAction.validation, step: LogStep.start});
const validationErrors = validate(options.schema, documentAST, rules);
logFunction({action: LogAction.validation, step: LogStep.end});
if (validationErrors.length) {
return Promise.resolve({ errors: format(validationErrors) });
}
try {
logFunction({ action: LogAction.execute, step: LogStep.start });
return Promise.resolve(
execute(
options.schema,
documentAST,
options.rootValue,
context,
options.variables,
options.operationName,
options.fieldResolver,
),
).then(result => {
logFunction({ action: LogAction.execute, step: LogStep.end });
logFunction({ action: LogAction.request, step: LogStep.end });
if (extensionStack) {
extensionStack.executionDidStart();
}
let response: GraphQLResponse = {
data: result.data,
};
try {
logFunction({action: LogAction.execute, step: LogStep.start});
return Promise.resolve(execute(
options.schema,
documentAST,
options.rootValue,
context,
options.variables,
options.operationName,
options.fieldResolver,
)).then(result => {
logFunction({action: LogAction.execute, step: LogStep.end});
logFunction({action: LogAction.request, step: LogStep.end});
if (result.errors) {
response.errors = format(result.errors, options.formatError);
if (debug) {
result.errors.map(printStackTrace);
}
}
let response: GraphQLResponse = {
data: result.data,
};
if (extensionStack) {
extensionStack.executionDidEnd();
extensionStack.requestDidEnd();
response.extensions = extensionStack.format();
}
if (result.errors) {
response.errors = format(result.errors);
if (debug) {
result.errors.map(printStackTrace);
}
}
if (options.formatResponse) {
response = options.formatResponse(response, options);
}
if (extensionStack) {
extensionStack.executionDidEnd();
extensionStack.requestDidEnd();
response.extensions = extensionStack.format();
}
if (options.formatResponse) {
response = options.formatResponse(response, options);
}
return response;
});
} catch (executionError) {
logFunction({action: LogAction.execute, step: LogStep.end});
logFunction({action: LogAction.request, step: LogStep.end});
return Promise.resolve({ errors: format([executionError]) });
}
return response;
});
} catch (executionError) {
logFunction({ action: LogAction.execute, step: LogStep.end });
logFunction({ action: LogAction.request, step: LogStep.end });
return Promise.resolve({
errors: format([executionError], options.formatError),
});
}
}
export { runQuery };

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc