apollo-server-core
Advanced tools
Comparing version 1.4.0-alpha.0 to 2.0.0-beta.0
@@ -1,12 +0,39 @@ | ||
/// <reference types="@types/node" /> | ||
import { Server as HTTPServer } from 'http'; | ||
export declare class ApolloServer<Server = HTTPServer> { | ||
server: Server; | ||
constructor(config: any); | ||
private applyMiddleware(server); | ||
private start(config, callback); | ||
/// <reference types="node" /> | ||
import { Server as HttpServer } from 'http'; | ||
import { GraphQLSchema, GraphQLError, GraphQLResolveInfo, ValidationContext } from 'graphql'; | ||
import { LogFunction } from './runQuery'; | ||
import { Config, ListenOptions, RegistrationOptions, ServerInfo } from './types'; | ||
export declare class ApolloServerBase<Request = RequestInit> { | ||
subscriptions: Config<Request>['subscriptions']; | ||
disableTools: boolean; | ||
private schema; | ||
private context?; | ||
private requestOptions; | ||
private graphqlPath; | ||
private engine; | ||
private engineEnabled; | ||
private http?; | ||
protected getHttp: () => HttpServer; | ||
constructor(config: Config<Request>); | ||
use({getHttp, path}: RegistrationOptions): void; | ||
listen(opts?: ListenOptions): Promise<ServerInfo>; | ||
stop(): Promise<void>; | ||
private createSubscriptionServer(server, config); | ||
private createEngine({engineInRequestPath, engine}); | ||
request(request: Request): Promise<{ | ||
schema: GraphQLSchema; | ||
formatError: Function | ((e: GraphQLError) => GraphQLError); | ||
rootValue?: any; | ||
context: any; | ||
logFunction?: LogFunction; | ||
formatParams?: Function; | ||
validationRules?: ((context: ValidationContext) => any)[]; | ||
formatResponse?: Function; | ||
fieldResolver?: (source: any, args: { | ||
[argName: string]: any; | ||
}, context: any, info: GraphQLResolveInfo) => any; | ||
debug?: boolean; | ||
tracing: boolean; | ||
cacheControl: any; | ||
}>; | ||
} | ||
export declare class ExpressServer extends ApolloServer { | ||
constructor(config: any); | ||
private applyMiddleware(options); | ||
} |
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return function (d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
var __assign = (this && this.__assign) || Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
@@ -47,45 +45,228 @@ return new (P || (P = Promise))(function (resolve, reject) { | ||
}; | ||
var __rest = (this && this.__rest) || function (s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) | ||
t[p[i]] = s[p[i]]; | ||
return t; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var ApolloServer = (function () { | ||
function ApolloServer(config) { | ||
var graphql_tools_1 = require("graphql-tools"); | ||
var graphql_1 = require("graphql"); | ||
var subscriptions_transport_ws_1 = require("subscriptions-transport-ws"); | ||
var errors_1 = require("./errors"); | ||
var env = process.env.NODE_ENV; | ||
var isDev = env !== 'production' && env !== 'test'; | ||
var NoIntrospection = function (context) { return ({ | ||
Field: function (node) { | ||
if (node.name.value === '__schema' || node.name.value === '__type') { | ||
context.reportError(new graphql_1.GraphQLError('GraphQL introspection is not allowed by Apollo Server, but the query containted __schema or __type. To enable introspection, pass enableIntrospection: true to ApolloServer in production', [node])); | ||
} | ||
}, | ||
}); }; | ||
var ApolloServerBase = (function () { | ||
function ApolloServerBase(config) { | ||
this.disableTools = !isDev; | ||
this.graphqlPath = '/graphql'; | ||
this.engineEnabled = false; | ||
var context = config.context, resolvers = config.resolvers, schema = config.schema, schemaDirectives = config.schemaDirectives, subscriptions = config.subscriptions, typeDefs = config.typeDefs, enableIntrospection = config.enableIntrospection, mocks = config.mocks, requestOptions = __rest(config, ["context", "resolvers", "schema", "schemaDirectives", "subscriptions", "typeDefs", "enableIntrospection", "mocks"]); | ||
if (enableIntrospection || isDev) | ||
this.disableTools = false; | ||
if (this.disableTools) { | ||
var noIntro = [NoIntrospection]; | ||
requestOptions.validationRules = requestOptions.validationRules | ||
? requestOptions.validationRules.concat(noIntro) | ||
: noIntro; | ||
} | ||
this.requestOptions = requestOptions; | ||
this.context = context; | ||
this.schema = schema | ||
? schema | ||
: graphql_tools_1.makeExecutableSchema({ | ||
typeDefs: Array.isArray(typeDefs) | ||
? typeDefs.reduce(function (prev, next) { return prev + '\n' + next; }) | ||
: typeDefs, | ||
schemaDirectives: schemaDirectives, | ||
resolvers: resolvers, | ||
}); | ||
if (mocks) { | ||
graphql_tools_1.addMockFunctionsToSchema({ | ||
schema: this.schema, | ||
preserveResolvers: true, | ||
mocks: typeof mocks === 'boolean' ? {} : mocks, | ||
}); | ||
} | ||
this.subscriptions = subscriptions; | ||
} | ||
ApolloServer.prototype.applyMiddleware = function (server) { | ||
return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { | ||
return [2]; | ||
}); }); | ||
ApolloServerBase.prototype.use = function (_a) { | ||
var getHttp = _a.getHttp, path = _a.path; | ||
this.getHttp = getHttp; | ||
this.graphqlPath = path; | ||
}; | ||
ApolloServer.prototype.start = function (config, callback) { }; | ||
return ApolloServer; | ||
}()); | ||
exports.ApolloServer = ApolloServer; | ||
var ExpressServer = (function (_super) { | ||
__extends(ExpressServer, _super); | ||
function ExpressServer(config) { | ||
ApolloServerBase.prototype.listen = function (opts) { | ||
var _this = this; | ||
_this.server = config.server; | ||
return _this; | ||
} | ||
ExpressServer.prototype.applyMiddleware = function (options) { | ||
if (opts === void 0) { opts = {}; } | ||
this.http = this.getHttp(); | ||
var options = __assign({ port: process.env.PORT || 4000 }, opts); | ||
if (this.subscriptions !== false) { | ||
var config = this.subscriptions === true || typeof this.subscriptions === 'undefined' | ||
? { | ||
path: this.graphqlPath, | ||
} | ||
: this.subscriptions; | ||
this.createSubscriptionServer(this.http, config); | ||
} | ||
if (opts.engine || opts.engineInRequestPath) | ||
this.createEngine(opts); | ||
return new Promise(function (success, fail) { | ||
if (_this.engine) { | ||
_this.engine.listen(Object.assign({}, options.engineLauncherOptions, { | ||
graphqlPaths: [_this.graphqlPath], | ||
port: options.port, | ||
httpServer: _this.http, | ||
}), function () { | ||
_this.engine.engineListeningAddress.url = require('url').resolve(_this.engine.engineListeningAddress.url, _this.graphqlPath); | ||
success(_this.engine.engineListeningAddress); | ||
}); | ||
_this.engine.on('error', fail); | ||
return; | ||
} | ||
_this.http.listen({ | ||
port: options.port, | ||
host: options.host, | ||
path: options.path, | ||
backlog: options.backlog, | ||
exclusive: options.exclusive, | ||
}, function () { | ||
var la = _this.http.address(); | ||
var hostForUrl = la.address; | ||
if (la.address === '' || la.address === '::') | ||
hostForUrl = 'localhost'; | ||
la.url = require('url').format({ | ||
protocol: 'http', | ||
hostname: hostForUrl, | ||
port: la.port, | ||
pathname: _this.graphqlPath, | ||
}); | ||
success(la); | ||
}); | ||
}); | ||
}; | ||
ApolloServerBase.prototype.stop = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
this.server.use(options.endpoint, cors(options.cors), graphqlExpress(function (req) { return __awaiter(_this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
return [2, { | ||
tracing: true, | ||
cacheControl: true, | ||
schema: makeExecutableSchema({ | ||
typeDefs: this.typeDefs, | ||
resolvers: this.resolvers, | ||
}), | ||
}]; | ||
}); | ||
}); })); | ||
return [2]; | ||
switch (_a.label) { | ||
case 0: | ||
if (!this.engine) return [3, 2]; | ||
return [4, this.engine.stop()]; | ||
case 1: | ||
_a.sent(); | ||
_a.label = 2; | ||
case 2: | ||
if (!this.http) return [3, 4]; | ||
return [4, new Promise(function (s) { return _this.http.close(s); })]; | ||
case 3: | ||
_a.sent(); | ||
_a.label = 4; | ||
case 4: return [2]; | ||
} | ||
}); | ||
}); | ||
}; | ||
return ExpressServer; | ||
}(ApolloServer)); | ||
exports.ExpressServer = ExpressServer; | ||
ApolloServerBase.prototype.createSubscriptionServer = function (server, config) { | ||
var _this = this; | ||
var onDisconnect = config.onDisconnect, onConnect = config.onConnect, keepAlive = config.keepAlive; | ||
subscriptions_transport_ws_1.SubscriptionServer.create({ | ||
schema: this.schema, | ||
execute: graphql_1.execute, | ||
subscribe: graphql_1.subscribe, | ||
onConnect: onConnect | ||
? onConnect | ||
: function (connectionParams) { return (__assign({}, connectionParams)); }, | ||
onDisconnect: onDisconnect, | ||
onOperation: function (_, connection) { return __awaiter(_this, void 0, void 0, function () { | ||
var context, _a, e_1; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
connection.formatResponse = function (value) { return (__assign({}, value, { errors: value.errors && value.errors.map(function (err) { return errors_1.internalFormatError(err); }) })); }; | ||
context = this.context ? this.context : { connection: connection }; | ||
_b.label = 1; | ||
case 1: | ||
_b.trys.push([1, 5, , 6]); | ||
if (!(typeof this.context === 'function')) return [3, 3]; | ||
return [4, this.context({ connection: connection })]; | ||
case 2: | ||
_a = _b.sent(); | ||
return [3, 4]; | ||
case 3: | ||
_a = context; | ||
_b.label = 4; | ||
case 4: | ||
context = _a; | ||
return [3, 6]; | ||
case 5: | ||
e_1 = _b.sent(); | ||
console.error(e_1); | ||
throw e_1; | ||
case 6: return [2, __assign({}, connection, { context: context })]; | ||
} | ||
}); | ||
}); }, | ||
keepAlive: keepAlive, | ||
}, { | ||
server: server, | ||
path: this.graphqlPath, | ||
}); | ||
}; | ||
ApolloServerBase.prototype.createEngine = function (_a) { | ||
var engineInRequestPath = _a.engineInRequestPath, engine = _a.engine; | ||
var _b = process.env, ENGINE_API_KEY = _b.ENGINE_API_KEY, ENGINE_CONFIG = _b.ENGINE_CONFIG; | ||
if (engine === false && (ENGINE_API_KEY || ENGINE_CONFIG)) { | ||
console.warn('engine is set to false when creating ApolloServer but either ENGINE_CONFIG or ENGINE_API_KEY was found in the environment'); | ||
} | ||
var ApolloEngine; | ||
if (engine) { | ||
try { | ||
ApolloEngine = require('apollo-engine').ApolloEngine; | ||
} | ||
catch (e) { | ||
console.warn("ApolloServer was unable to load Apollo Engine yet engine was configured in the options when creating this ApolloServer? To fix this, run the following command:\n\n npm install apollo-engine --save\n"); | ||
} | ||
this.engine = new ApolloEngine(typeof engine === 'boolean' ? undefined : engine); | ||
} | ||
if (this.engine || engineInRequestPath) | ||
this.engineEnabled = true; | ||
}; | ||
ApolloServerBase.prototype.request = function (request) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _this = this; | ||
var context, _a; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
context = this.context ? this.context : { request: request }; | ||
if (!(typeof this.context === 'function')) return [3, 2]; | ||
return [4, this.context({ req: request })]; | ||
case 1: | ||
_a = _b.sent(); | ||
return [3, 3]; | ||
case 2: | ||
_a = context; | ||
_b.label = 3; | ||
case 3: | ||
context = _a; | ||
return [2, __assign({ schema: this.schema, tracing: Boolean(this.engineEnabled), cacheControl: Boolean(this.engineEnabled), formatError: function (e) { | ||
return errors_1.internalFormatError(e, _this.requestOptions.debug); | ||
}, context: context }, this.requestOptions)]; | ||
} | ||
}); | ||
}); | ||
}; | ||
return ApolloServerBase; | ||
}()); | ||
exports.ApolloServerBase = ApolloServerBase; | ||
//# sourceMappingURL=ApolloServer.js.map |
import { GraphQLError } from 'graphql'; | ||
export interface IApolloError { | ||
} | ||
export declare class ApolloError extends Error { | ||
extensions: any; | ||
constructor(message: string, code: string, properties?: Record<string, any>); | ||
constructor(message: string, code?: string, properties?: Record<string, any>); | ||
} | ||
export declare function formatError(error: GraphQLError, debug?: boolean): GraphQLError; | ||
export declare function internalFormatError(error: GraphQLError, debug?: boolean): GraphQLError; | ||
export declare function toApolloError(error: Error, code?: string): Error & { | ||
extensions: Record<string, any>; | ||
}; | ||
export declare function fromGraphQLError(error: GraphQLError, code?: string): GraphQLError; | ||
export declare class ParseError extends ApolloError { | ||
name: string; | ||
export interface ErrorOptions { | ||
code?: string; | ||
errorClass?: typeof ApolloError; | ||
} | ||
export declare function fromGraphQLError(error: GraphQLError, options?: ErrorOptions): GraphQLError; | ||
export declare class SyntaxError extends ApolloError { | ||
constructor(message: string); | ||
} | ||
export declare class ValidationError extends ApolloError { | ||
name: string; | ||
constructor(message: string); | ||
} | ||
export declare class AuthenticationError extends ApolloError { | ||
name: string; | ||
constructor(message: string); | ||
} | ||
export declare class ForbiddenError extends ApolloError { | ||
constructor(message: string); | ||
} |
@@ -31,5 +31,5 @@ "use strict"; | ||
exports.ApolloError = ApolloError; | ||
function formatError(error, debug) { | ||
function internalFormatError(error, debug) { | ||
if (debug === void 0) { debug = false; } | ||
var expanded = __assign({}, error, { extensions: __assign({}, error.extensions, { code: (error.extensions && error.extensions.code) || 'INTERNAL_ERROR', exception: __assign({}, (error.extensions && error.extensions.exception), error.originalError) }) }); | ||
var expanded = __assign({ message: error.message, path: error.path, locations: error.locations }, error, { extensions: __assign({}, error.extensions, { code: (error.extensions && error.extensions.code) || 'INTERNAL_SERVER_ERROR', exception: __assign({}, (error.extensions && error.extensions.exception), error.originalError) }) }); | ||
delete expanded.extensions.exception.extensions; | ||
@@ -48,5 +48,5 @@ if (debug && !expanded.extensions.exception.stacktrace) { | ||
} | ||
exports.formatError = formatError; | ||
exports.internalFormatError = internalFormatError; | ||
function toApolloError(error, code) { | ||
if (code === void 0) { code = 'INTERNAL_ERROR'; } | ||
if (code === void 0) { code = 'INTERNAL_SERVER_ERROR'; } | ||
var err = error; | ||
@@ -62,6 +62,13 @@ if (err.extensions) { | ||
exports.toApolloError = toApolloError; | ||
function fromGraphQLError(error, code) { | ||
if (code === void 0) { code = 'INTERNAL_ERROR'; } | ||
var copy = __assign({}, error); | ||
copy.extensions = __assign({}, copy.extensions, { code: code }); | ||
function fromGraphQLError(error, options) { | ||
var copy = options && options.errorClass | ||
? new options.errorClass(error.message) | ||
: new ApolloError(error.message); | ||
Object.keys(error).forEach(function (key) { | ||
copy[key] = error[key]; | ||
}); | ||
copy.extensions = __assign({}, copy.extensions, error.extensions); | ||
if (!copy.extensions.code) { | ||
copy.extensions.code = (options && options.code) || 'INTERNAL_SERVER_ERROR'; | ||
} | ||
Object.defineProperty(copy, 'originalError', { value: {} }); | ||
@@ -74,18 +81,14 @@ Reflect.ownKeys(error).forEach(function (key) { | ||
exports.fromGraphQLError = fromGraphQLError; | ||
var ParseError = (function (_super) { | ||
__extends(ParseError, _super); | ||
function ParseError(message) { | ||
var _this = _super.call(this, message, 'MALFORMED_QUERY') || this; | ||
_this.name = 'MalformedQueryError'; | ||
return _this; | ||
var SyntaxError = (function (_super) { | ||
__extends(SyntaxError, _super); | ||
function SyntaxError(message) { | ||
return _super.call(this, message, 'GRAPHQL_PARSE_FAILED') || this; | ||
} | ||
return ParseError; | ||
return SyntaxError; | ||
}(ApolloError)); | ||
exports.ParseError = ParseError; | ||
exports.SyntaxError = SyntaxError; | ||
var ValidationError = (function (_super) { | ||
__extends(ValidationError, _super); | ||
function ValidationError(message) { | ||
var _this = _super.call(this, message, 'QUERY_VALIDATION_FAILED') || this; | ||
_this.name = 'ValidationError'; | ||
return _this; | ||
return _super.call(this, message, 'GRAPHQL_VALIDATION_FAILED') || this; | ||
} | ||
@@ -98,5 +101,3 @@ return ValidationError; | ||
function AuthenticationError(message) { | ||
var _this = _super.call(this, message, 'UNAUTHORIZED') || this; | ||
_this.name = 'UnauthorizedError'; | ||
return _this; | ||
return _super.call(this, message, 'UNAUTHENTICATED') || this; | ||
} | ||
@@ -106,2 +107,10 @@ return AuthenticationError; | ||
exports.AuthenticationError = AuthenticationError; | ||
var ForbiddenError = (function (_super) { | ||
__extends(ForbiddenError, _super); | ||
function ForbiddenError(message) { | ||
return _super.call(this, message, 'FORBIDDEN') || this; | ||
} | ||
return ForbiddenError; | ||
}(ApolloError)); | ||
exports.ForbiddenError = ForbiddenError; | ||
//# sourceMappingURL=errors.js.map |
import { GraphQLSchema, ValidationContext, GraphQLFieldResolver } from 'graphql'; | ||
import { LogFunction } from './runQuery'; | ||
import { CacheControlExtensionOptions } from 'apollo-cache-control'; | ||
export interface GraphQLServerOptions<TContext = any> { | ||
@@ -16,5 +15,5 @@ schema: GraphQLSchema; | ||
tracing?: boolean; | ||
cacheControl?: boolean | CacheControlExtensionOptions; | ||
cacheControl?: boolean | any; | ||
} | ||
export default GraphQLServerOptions; | ||
export declare function resolveGraphqlOptions(options: GraphQLServerOptions | Function, ...args: any[]): Promise<GraphQLServerOptions>; |
export { runQuery, LogFunction, LogMessage, LogStep, LogAction } from './runQuery'; | ||
export { runHttpQuery, HttpQueryRequest, HttpQueryError } from './runHttpQuery'; | ||
export { default as GraphQLOptions, resolveGraphqlOptions } from './graphqlOptions'; | ||
export { ApolloError, toApolloError, ParseError, ValidationError, AuthenticationError, formatError } from './errors'; | ||
export { ApolloError, toApolloError, SyntaxError, ValidationError, AuthenticationError, ForbiddenError, internalFormatError } from './errors'; | ||
export { ApolloServerBase } from './ApolloServer'; | ||
export * from './types'; |
@@ -15,6 +15,9 @@ "use strict"; | ||
exports.toApolloError = errors_1.toApolloError; | ||
exports.ParseError = errors_1.ParseError; | ||
exports.SyntaxError = errors_1.SyntaxError; | ||
exports.ValidationError = errors_1.ValidationError; | ||
exports.AuthenticationError = errors_1.AuthenticationError; | ||
exports.formatError = errors_1.formatError; | ||
exports.ForbiddenError = errors_1.ForbiddenError; | ||
exports.internalFormatError = errors_1.internalFormatError; | ||
var ApolloServer_1 = require("./ApolloServer"); | ||
exports.ApolloServerBase = ApolloServer_1.ApolloServerBase; | ||
//# sourceMappingURL=index.js.map |
@@ -88,5 +88,5 @@ "use strict"; | ||
case 4: | ||
formatErrorFn = function (error) { | ||
return optionsObject.formatError(errors_1.formatError(error)) || errors_1.formatError; | ||
}; | ||
formatErrorFn = optionsObject.formatError | ||
? function (error) { return optionsObject.formatError(errors_1.internalFormatError(error)); } | ||
: errors_1.internalFormatError; | ||
debugDefault = process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test'; | ||
@@ -121,2 +121,22 @@ debug = optionsObject.debug !== undefined ? optionsObject.debug : debugDefault; | ||
var query = requestParams.query; | ||
var extensions = requestParams.extensions; | ||
if (isGetRequest && extensions) { | ||
try { | ||
extensions = JSON.parse(extensions); | ||
} | ||
catch (error) { | ||
throw new HttpQueryError(400, 'Extensions are invalid JSON.'); | ||
} | ||
} | ||
if (query === undefined && extensions && extensions.persistedQuery) { | ||
throw new HttpQueryError(200, JSON.stringify({ | ||
errors: [ | ||
{ | ||
message: 'PersistedQueryNotSupported', | ||
}, | ||
], | ||
}), true, { | ||
'Content-Type': 'application/json', | ||
}); | ||
} | ||
if (isGetRequest) { | ||
@@ -161,3 +181,3 @@ if (typeof query === 'string') { | ||
validationRules: optionsObject.validationRules, | ||
formatError: optionsObject.formatError, | ||
formatError: formatErrorFn, | ||
formatResponse: optionsObject.formatResponse, | ||
@@ -164,0 +184,0 @@ fieldResolver: optionsObject.fieldResolver, |
import { GraphQLSchema, GraphQLFieldResolver, DocumentNode, GraphQLError, ValidationContext } from 'graphql'; | ||
import { CacheControlExtensionOptions } from 'apollo-cache-control'; | ||
export interface GraphQLResponse { | ||
@@ -23,3 +22,3 @@ data?: object; | ||
key?: string; | ||
data?: Object; | ||
data?: any; | ||
} | ||
@@ -45,4 +44,4 @@ export interface LogFunction { | ||
tracing?: boolean; | ||
cacheControl?: boolean | CacheControlExtensionOptions; | ||
cacheControl?: boolean | any; | ||
} | ||
export declare function runQuery(options: QueryOptions): Promise<GraphQLResponse>; |
@@ -25,8 +25,5 @@ "use strict"; | ||
exports.runQuery = runQuery; | ||
function printStackTrace(error) { | ||
console.error(error.stack); | ||
} | ||
function format(errors, options) { | ||
var formatter = options.formatter, debug = options.debug; | ||
return errors.map(function (error) { return errors_1.formatError(error, debug); }).map(function (error) { | ||
return errors.map(function (error) { return errors_1.internalFormatError(error, debug); }).map(function (error) { | ||
if (formatter !== undefined) { | ||
@@ -38,4 +35,4 @@ try { | ||
console.error('Error in formatError function:', err); | ||
var newError = errors_1.fromGraphQLError(new graphql_1.GraphQLError('Internal server error'), 'INTERNAL_ERROR'); | ||
return errors_1.formatError(newError, debug); | ||
var newError = errors_1.fromGraphQLError(new graphql_1.GraphQLError('Internal server error')); | ||
return errors_1.internalFormatError(newError, debug); | ||
} | ||
@@ -102,3 +99,7 @@ } | ||
return Promise.resolve({ | ||
errors: format([errors_1.fromGraphQLError(syntaxError, 'MALFORMED_QUERY')], { | ||
errors: format([ | ||
errors_1.fromGraphQLError(syntaxError, { | ||
errorClass: errors_1.SyntaxError, | ||
}), | ||
], { | ||
formatter: options.formatError, | ||
@@ -123,3 +124,3 @@ debug: debug, | ||
errors: format(validationErrors.map(function (err) { | ||
return errors_1.fromGraphQLError(err, 'QUERY_VALIDATION_FAILED'); | ||
return errors_1.fromGraphQLError(err, { errorClass: errors_1.ValidationError }); | ||
}), { | ||
@@ -138,3 +139,2 @@ formatter: options.formatError, | ||
logFunction({ action: LogAction.execute, step: LogStep.end }); | ||
logFunction({ action: LogAction.request, step: LogStep.end }); | ||
var response = { | ||
@@ -148,5 +148,2 @@ data: result.data, | ||
}); | ||
if (debug) { | ||
result.errors.map(printStackTrace); | ||
} | ||
} | ||
@@ -161,2 +158,8 @@ if (extensionStack) { | ||
} | ||
logFunction({ | ||
action: LogAction.request, | ||
step: LogStep.end, | ||
key: 'response', | ||
data: response, | ||
}); | ||
return response; | ||
@@ -169,3 +172,3 @@ }); | ||
return Promise.resolve({ | ||
errors: format([errors_1.fromGraphQLError(executionError, 'EXECUTION_ERROR')], { | ||
errors: format([errors_1.fromGraphQLError(executionError)], { | ||
formatter: options.formatError, | ||
@@ -172,0 +175,0 @@ debug: debug, |
{ | ||
"name": "apollo-server-core", | ||
"version": "1.4.0-alpha.0", | ||
"version": "2.0.0-beta.0", | ||
"description": "Core engine for Apollo GraphQL server", | ||
@@ -30,8 +30,11 @@ "main": "dist/index.js", | ||
"@types/graphql": "0.12.7", | ||
"@types/node": "^9.6.1", | ||
"@types/ws": "^4.0.2", | ||
"apollo-engine": "^1.0.6", | ||
"fibers": "1.0.15", | ||
"meteor-promise": "0.8.6", | ||
"typescript": "2.8.1" | ||
"typescript": "2.8.3" | ||
}, | ||
"peerDependencies": { | ||
"graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0" | ||
"graphql": "^0.12.0 || ^0.13.0 || ^14.0.0" | ||
}, | ||
@@ -43,6 +46,10 @@ "typings": "dist/index.d.ts", | ||
"dependencies": { | ||
"apollo-cache-control": "^0.1.0", | ||
"apollo-cache-control": "^0.1.1", | ||
"apollo-tracing": "^0.1.0", | ||
"graphql-extensions": "^0.0.x" | ||
"graphql-extensions": "^0.0.x", | ||
"graphql-subscriptions": "^0.5.8", | ||
"graphql-tools": "^2.23.1", | ||
"subscriptions-transport-ws": "^0.9.7", | ||
"ws": "^5.1.1" | ||
} | ||
} |
import { GraphQLError } from 'graphql'; | ||
export interface IApolloError {} | ||
export class ApolloError extends Error { | ||
public extensions; | ||
constructor(message: string, code: string, properties?: Record<string, any>) { | ||
constructor( | ||
message: string, | ||
code?: string, | ||
properties?: Record<string, any>, | ||
) { | ||
super(message); | ||
@@ -12,8 +15,15 @@ this.extensions = { ...properties, code }; | ||
export function formatError(error: GraphQLError, debug: boolean = false) { | ||
export function internalFormatError( | ||
error: GraphQLError, | ||
debug: boolean = false, | ||
) { | ||
const expanded: GraphQLError = { | ||
message: error.message, | ||
path: error.path, | ||
locations: error.locations, | ||
...error, | ||
extensions: { | ||
...error.extensions, | ||
code: (error.extensions && error.extensions.code) || 'INTERNAL_ERROR', | ||
code: | ||
(error.extensions && error.extensions.code) || 'INTERNAL_SERVER_ERROR', | ||
exception: { | ||
@@ -48,3 +58,3 @@ ...(error.extensions && error.extensions.exception), | ||
error: Error, | ||
code: string = 'INTERNAL_ERROR', | ||
code: string = 'INTERNAL_SERVER_ERROR', | ||
): Error & { extensions: Record<string, any> } { | ||
@@ -60,14 +70,29 @@ let err: GraphQLError = error; | ||
export function fromGraphQLError( | ||
error: GraphQLError, | ||
code: string = 'INTERNAL_ERROR', | ||
) { | ||
const copy: GraphQLError = { | ||
...error, | ||
}; | ||
export interface ErrorOptions { | ||
code?: string; | ||
errorClass?: typeof ApolloError; | ||
} | ||
export function fromGraphQLError(error: GraphQLError, options?: ErrorOptions) { | ||
const copy: GraphQLError = | ||
options && options.errorClass | ||
? new options.errorClass(error.message) | ||
: new ApolloError(error.message); | ||
//copy enumerable keys | ||
Object.keys(error).forEach(key => { | ||
copy[key] = error[key]; | ||
}); | ||
//extensions are non enumerable, so copy them directly | ||
copy.extensions = { | ||
...copy.extensions, | ||
code, | ||
...error.extensions, | ||
}; | ||
//Fallback on default for code | ||
if (!copy.extensions.code) { | ||
copy.extensions.code = (options && options.code) || 'INTERNAL_SERVER_ERROR'; | ||
} | ||
//copy the original error, while keeping all values non-enumerable, so they | ||
@@ -83,6 +108,7 @@ //are not printed unless directly referenced | ||
export class ParseError extends ApolloError { | ||
name = 'MalformedQueryError'; | ||
export class SyntaxError extends ApolloError { | ||
// TODO make the name nonenumerable | ||
// name = 'SyntaxError'; | ||
constructor(message: string) { | ||
super(message, 'MALFORMED_QUERY'); | ||
super(message, 'GRAPHQL_PARSE_FAILED'); | ||
} | ||
@@ -92,5 +118,6 @@ } | ||
export class ValidationError extends ApolloError { | ||
name = 'ValidationError'; | ||
// TODO make the name nonenumerable | ||
// name = 'ValidationError'; | ||
constructor(message: string) { | ||
super(message, 'QUERY_VALIDATION_FAILED'); | ||
super(message, 'GRAPHQL_VALIDATION_FAILED'); | ||
} | ||
@@ -100,6 +127,15 @@ } | ||
export class AuthenticationError extends ApolloError { | ||
name = 'UnauthorizedError'; | ||
// TODO make the name nonenumerable | ||
// name = 'AuthenticationError'; | ||
constructor(message: string) { | ||
super(message, 'UNAUTHORIZED'); | ||
super(message, 'UNAUTHENTICATED'); | ||
} | ||
} | ||
export class ForbiddenError extends ApolloError { | ||
// TODO make the name nonenumerable | ||
// name = 'ForbiddenError'; | ||
constructor(message: string) { | ||
super(message, 'FORBIDDEN'); | ||
} | ||
} |
@@ -8,3 +8,2 @@ import { | ||
import { GraphQLExtension } from 'graphql-extensions'; | ||
import { CacheControlExtensionOptions } from 'apollo-cache-control'; | ||
@@ -38,3 +37,4 @@ /* | ||
tracing?: boolean; | ||
cacheControl?: boolean | CacheControlExtensionOptions; | ||
// cacheControl?: boolean | CacheControlExtensionOptions; | ||
cacheControl?: boolean | any; | ||
} | ||
@@ -41,0 +41,0 @@ |
@@ -16,6 +16,11 @@ export { | ||
toApolloError, | ||
ParseError, | ||
SyntaxError, | ||
ValidationError, | ||
AuthenticationError, | ||
formatError, | ||
ForbiddenError, | ||
internalFormatError, | ||
} from './errors'; | ||
// ApolloServer Base class | ||
export { ApolloServerBase } from './ApolloServer'; | ||
export * from './types'; |
@@ -7,3 +7,3 @@ import { parse, getOperationAST, DocumentNode, ExecutionResult } from 'graphql'; | ||
} from './graphqlOptions'; | ||
import { formatError } from './errors'; | ||
import { internalFormatError } from './errors'; | ||
@@ -55,4 +55,5 @@ export interface HttpQueryRequest { | ||
} | ||
const formatErrorFn = error => | ||
optionsObject.formatError(formatError(error)) || formatError; | ||
const formatErrorFn = optionsObject.formatError | ||
? error => optionsObject.formatError(internalFormatError(error)) | ||
: internalFormatError; | ||
const debugDefault = | ||
@@ -106,7 +107,50 @@ process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test'; | ||
let query = requestParams.query; | ||
let extensions = requestParams.extensions; | ||
if (isGetRequest && extensions) { | ||
// For GET requests, we have to JSON-parse extensions. (For POST | ||
// requests they get parsed as part of parsing the larger body they're | ||
// inside.) | ||
try { | ||
extensions = JSON.parse(extensions); | ||
} catch (error) { | ||
throw new HttpQueryError(400, 'Extensions are invalid JSON.'); | ||
} | ||
} | ||
if (query === undefined && extensions && extensions.persistedQuery) { | ||
// It looks like we've received an Apollo Persisted Query. Apollo Server | ||
// does not support persisted queries out of the box, so we should fail | ||
// fast with a clear error saying that we don't support APQs. (A future | ||
// version of Apollo Server may support APQs directly.) | ||
throw new HttpQueryError( | ||
// Return 200 to simplify processing: we want this to be intepreted by | ||
// the client as data worth interpreting, not an error. | ||
200, | ||
JSON.stringify({ | ||
errors: [ | ||
{ | ||
message: 'PersistedQueryNotSupported', | ||
}, | ||
], | ||
}), | ||
true, | ||
{ | ||
'Content-Type': 'application/json', | ||
}, | ||
); | ||
} | ||
if (isGetRequest) { | ||
if (typeof query === 'string') { | ||
// preparse the query incase of GET so we can assert the operation. | ||
// XXX This makes the type of 'query' in this function confused | ||
// which has led to us accidentally supporting GraphQL AST over | ||
// the wire as a valid query, which confuses users. Refactor to | ||
// not do this. Also, for a GET request, query really shouldn't | ||
// ever be anything other than a string or undefined, so this | ||
// set of conditionals doesn't quite make sense. | ||
query = parse(query); | ||
} else if (!query) { | ||
// Note that we've already thrown a different error if it looks like APQ. | ||
throw new HttpQueryError(400, 'Must provide query string.'); | ||
@@ -128,6 +172,9 @@ } | ||
const operationName = requestParams.operationName; | ||
let variables = requestParams.variables; | ||
if (typeof variables === 'string') { | ||
try { | ||
// XXX Really we should only do this for GET requests, but for | ||
// compatibility reasons we'll keep doing this at least for now for | ||
// broken clients that ship variables in a string for no good reason. | ||
variables = JSON.parse(variables); | ||
@@ -158,3 +205,3 @@ } catch (error) { | ||
validationRules: optionsObject.validationRules, | ||
formatError: optionsObject.formatError, | ||
formatError: formatErrorFn, | ||
formatResponse: optionsObject.formatResponse, | ||
@@ -161,0 +208,0 @@ fieldResolver: optionsObject.fieldResolver, |
@@ -121,5 +121,4 @@ /* tslint:disable:no-unused-expression */ | ||
it('sends stack trace to error if in an error occurs and debug mode is set', () => { | ||
it('does not call console.error if in an error occurs and debug mode is set', () => { | ||
const query = `query { testError }`; | ||
const expected = /at resolveFieldValueOrError/; | ||
const logStub = stub(console, 'error'); | ||
@@ -132,8 +131,7 @@ return runQuery({ | ||
logStub.restore(); | ||
expect(logStub.callCount).to.equal(1); | ||
expect(logStub.getCall(0).args[0]).to.match(expected); | ||
expect(logStub.callCount).to.equal(0); | ||
}); | ||
}); | ||
it('does not send stack trace if in an error occurs and not in debug mode', () => { | ||
it('does not call console.error if in an error occurs and not in debug mode', () => { | ||
const query = `query { testError }`; | ||
@@ -296,2 +294,6 @@ const logStub = stub(console, 'error'); | ||
step: LogStep.end, | ||
key: 'response', | ||
data: { | ||
data: expected, | ||
}, | ||
}); | ||
@@ -298,0 +300,0 @@ }); |
@@ -21,9 +21,11 @@ import { | ||
import { TracingExtension } from 'apollo-tracing'; | ||
import { CacheControlExtension } from 'apollo-cache-control'; | ||
import { | ||
CacheControlExtension, | ||
CacheControlExtensionOptions, | ||
} from 'apollo-cache-control'; | ||
fromGraphQLError, | ||
internalFormatError, | ||
ValidationError, | ||
SyntaxError, | ||
} from './errors'; | ||
import { fromGraphQLError, formatError } from './errors'; | ||
export interface GraphQLResponse { | ||
@@ -52,3 +54,3 @@ data?: object; | ||
key?: string; | ||
data?: Object; | ||
data?: any; | ||
} | ||
@@ -77,3 +79,4 @@ | ||
tracing?: boolean; | ||
cacheControl?: boolean | CacheControlExtensionOptions; | ||
// cacheControl?: boolean | CacheControlExtensionOptions; | ||
cacheControl?: boolean | any; | ||
} | ||
@@ -86,6 +89,2 @@ | ||
function printStackTrace(error: Error) { | ||
console.error(error.stack); | ||
} | ||
function format( | ||
@@ -99,3 +98,3 @@ errors: Array<Error>, | ||
const { formatter, debug } = options; | ||
return errors.map(error => formatError(error, debug)).map(error => { | ||
return errors.map(error => internalFormatError(error, debug)).map(error => { | ||
if (formatter !== undefined) { | ||
@@ -108,5 +107,4 @@ try { | ||
new GraphQLError('Internal server error'), | ||
'INTERNAL_ERROR', | ||
); | ||
return formatError(newError, debug); | ||
return internalFormatError(newError, debug); | ||
} | ||
@@ -184,6 +182,13 @@ } else { | ||
return Promise.resolve({ | ||
errors: format([fromGraphQLError(syntaxError, 'MALFORMED_QUERY')], { | ||
formatter: options.formatError, | ||
debug, | ||
}), | ||
errors: format( | ||
[ | ||
fromGraphQLError(syntaxError, { | ||
errorClass: SyntaxError, | ||
}), | ||
], | ||
{ | ||
formatter: options.formatError, | ||
debug, | ||
}, | ||
), | ||
}); | ||
@@ -207,3 +212,3 @@ } | ||
validationErrors.map(err => | ||
fromGraphQLError(err, 'QUERY_VALIDATION_FAILED'), | ||
fromGraphQLError(err, { errorClass: ValidationError }), | ||
), | ||
@@ -236,3 +241,2 @@ { | ||
logFunction({ action: LogAction.execute, step: LogStep.end }); | ||
logFunction({ action: LogAction.request, step: LogStep.end }); | ||
@@ -248,5 +252,2 @@ let response: GraphQLResponse = { | ||
}); | ||
if (debug) { | ||
result.errors.map(printStackTrace); | ||
} | ||
} | ||
@@ -264,2 +265,9 @@ | ||
logFunction({ | ||
action: LogAction.request, | ||
step: LogStep.end, | ||
key: 'response', | ||
data: response, | ||
}); | ||
return response; | ||
@@ -271,3 +279,9 @@ }); | ||
return Promise.resolve({ | ||
errors: format([fromGraphQLError(executionError, 'EXECUTION_ERROR')], { | ||
//TODO accurate code for this error, which describes this error, which | ||
// can occur when: | ||
// * variables incorrectly typed/null when nonnullable | ||
// * unknown operation/operation name invalid | ||
// * operation type is unsupported | ||
// Options: PREPROCESSING_FAILED, GRAPHQL_RUNTIME_CHECK_FAILED | ||
errors: format([fromGraphQLError(executionError)], { | ||
formatter: options.formatError, | ||
@@ -274,0 +288,0 @@ debug, |
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
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
113802
33
2453
0
8
8
7
+ Addedgraphql-subscriptions@^0.5.8
+ Addedgraphql-tools@^2.23.1
+ Addedws@^5.1.1
+ Added@wry/equality@0.1.11(transitive)
+ Addedapollo-link@1.2.14(transitive)
+ Addedapollo-utilities@1.3.4(transitive)
+ Addedasync-limiter@1.0.1(transitive)
+ Addedbacko2@1.0.2(transitive)
+ Addeddeprecated-decorator@0.1.6(transitive)
+ Addedeventemitter3@3.1.2(transitive)
+ Addedfast-json-stable-stringify@2.1.0(transitive)
+ Addedgraphql@14.7.0(transitive)
+ Addedgraphql-subscriptions@0.5.8(transitive)
+ Addedgraphql-tools@2.24.0(transitive)
+ Addedsubscriptions-transport-ws@0.9.19(transitive)
+ Addedsymbol-observable@1.2.0(transitive)
+ Addedts-invariant@0.4.4(transitive)
+ Addedtslib@1.14.1(transitive)
+ Addeduuid@3.4.0(transitive)
+ Addedws@5.2.4(transitive)
+ Addedzen-observable@0.8.15(transitive)
+ Addedzen-observable-ts@0.8.21(transitive)
Updatedapollo-cache-control@^0.1.1