UNPKG

35.1 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4 return new (P || (P = Promise))(function (resolve, reject) {
5 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8 step((generator = generator.apply(thisArg, _arguments || [])).next());
9 });
10};
11var __rest = (this && this.__rest) || function (s, e) {
12 var t = {};
13 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14 t[p] = s[p];
15 if (s != null && typeof Object.getOwnPropertySymbols === "function")
16 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18 t[p[i]] = s[p[i]];
19 }
20 return t;
21};
22var __importDefault = (this && this.__importDefault) || function (mod) {
23 return (mod && mod.__esModule) ? mod : { "default": mod };
24};
25Object.defineProperty(exports, "__esModule", { value: true });
26exports.ApolloServerBase = void 0;
27const graphql_tools_1 = require("graphql-tools");
28const net_1 = require("net");
29const tls_1 = require("tls");
30const loglevel_1 = __importDefault(require("loglevel"));
31const graphql_1 = require("graphql");
32const resolvable_1 = __importDefault(require("@josephg/resolvable"));
33const apollo_server_caching_1 = require("apollo-server-caching");
34const runtimeSupportsUploads_1 = __importDefault(require("./utils/runtimeSupportsUploads"));
35const apollo_server_errors_1 = require("apollo-server-errors");
36const index_1 = require("./index");
37const playground_1 = require("./playground");
38const schemaHash_1 = require("./utils/schemaHash");
39const isDirectiveDefined_1 = require("./utils/isDirectiveDefined");
40const requestPipeline_1 = require("./requestPipeline");
41const apollo_server_env_1 = require("apollo-server-env");
42const apollo_tools_1 = require("@apollographql/apollo-tools");
43const apollo_tracing_1 = require("apollo-tracing");
44const apollo_cache_control_1 = require("apollo-cache-control");
45const runHttpQuery_1 = require("./runHttpQuery");
46const isNodeLike_1 = __importDefault(require("./utils/isNodeLike"));
47const determineApolloConfig_1 = require("./determineApolloConfig");
48const plugin_1 = require("./plugin");
49const internalPlugin_1 = require("./plugin/internalPlugin");
50const NoIntrospection = (context) => ({
51 Field(node) {
52 if (node.name.value === '__schema' || node.name.value === '__type') {
53 context.reportError(new graphql_1.GraphQLError('GraphQL introspection is not allowed by Apollo Server, but the query contained __schema or __type. To enable introspection, pass introspection: true to ApolloServer in production', [node]));
54 }
55 },
56});
57const forbidUploadsForTesting = process && process.env.NODE_ENV === 'test' && !runtimeSupportsUploads_1.default;
58function approximateObjectSize(obj) {
59 return Buffer.byteLength(JSON.stringify(obj), 'utf8');
60}
61class UnreachableCaseError extends Error {
62 constructor(val) {
63 super(`Unreachable case: ${val}`);
64 }
65}
66class ApolloServerBase {
67 constructor(config) {
68 this.graphqlPath = '/graphql';
69 this.requestOptions = Object.create(null);
70 this.plugins = [];
71 this.toDispose = new Set();
72 this.toDisposeLast = new Set();
73 if (!config)
74 throw new Error('ApolloServer requires options.');
75 this.config = config;
76 const { context, resolvers, schema, schemaDirectives, modules, typeDefs, parseOptions = {}, introspection, mocks, mockEntireSchema, extensions, subscriptions, uploads, playground, plugins, gateway, cacheControl, experimental_approximateDocumentStoreMiB, stopOnTerminationSignals, apollo, engine } = config, requestOptions = __rest(config, ["context", "resolvers", "schema", "schemaDirectives", "modules", "typeDefs", "parseOptions", "introspection", "mocks", "mockEntireSchema", "extensions", "subscriptions", "uploads", "playground", "plugins", "gateway", "cacheControl", "experimental_approximateDocumentStoreMiB", "stopOnTerminationSignals", "apollo", "engine"]);
77 if (engine !== undefined && apollo) {
78 throw new Error('You cannot provide both `engine` and `apollo` to `new ApolloServer()`. ' +
79 'For details on how to migrate all of your options out of `engine`, see ' +
80 'https://go.apollo.dev/s/migration-engine-plugins');
81 }
82 if (config.logger) {
83 this.logger = config.logger;
84 }
85 else {
86 const loglevelLogger = loglevel_1.default.getLogger('apollo-server');
87 if (this.config.debug === true) {
88 loglevelLogger.setLevel(loglevel_1.default.levels.DEBUG);
89 }
90 else {
91 loglevelLogger.setLevel(loglevel_1.default.levels.INFO);
92 }
93 this.logger = loglevelLogger;
94 }
95 this.apolloConfig = determineApolloConfig_1.determineApolloConfig(apollo, engine, this.logger);
96 if (gateway && (modules || schema || typeDefs || resolvers)) {
97 throw new Error('Cannot define both `gateway` and any of: `modules`, `schema`, `typeDefs`, or `resolvers`');
98 }
99 this.parseOptions = parseOptions;
100 this.context = context;
101 const isDev = process.env.NODE_ENV !== 'production';
102 if ((typeof introspection === 'boolean' && !introspection) ||
103 (introspection === undefined && !isDev)) {
104 const noIntro = [NoIntrospection];
105 requestOptions.validationRules = requestOptions.validationRules
106 ? requestOptions.validationRules.concat(noIntro)
107 : noIntro;
108 }
109 if (!requestOptions.cache) {
110 requestOptions.cache = new apollo_server_caching_1.InMemoryLRUCache();
111 }
112 if (requestOptions.persistedQueries !== false) {
113 const _a = requestOptions.persistedQueries || Object.create(null), { cache: apqCache = requestOptions.cache } = _a, apqOtherOptions = __rest(_a, ["cache"]);
114 requestOptions.persistedQueries = Object.assign({ cache: new apollo_server_caching_1.PrefixingKeyValueCache(apqCache, requestPipeline_1.APQ_CACHE_PREFIX) }, apqOtherOptions);
115 }
116 else {
117 delete requestOptions.persistedQueries;
118 }
119 this.requestOptions = requestOptions;
120 if (uploads !== false && !forbidUploadsForTesting) {
121 if (this.supportsUploads()) {
122 if (!runtimeSupportsUploads_1.default) {
123 printNodeFileUploadsMessage(this.logger);
124 throw new Error('`graphql-upload` is no longer supported on Node.js < v8.5.0. ' +
125 'See https://bit.ly/gql-upload-node-6.');
126 }
127 if (uploads === true || typeof uploads === 'undefined') {
128 this.uploadsConfig = {};
129 }
130 else {
131 this.uploadsConfig = uploads;
132 }
133 }
134 else if (uploads) {
135 throw new Error('This implementation of ApolloServer does not support file uploads because the environment cannot accept multi-part forms');
136 }
137 }
138 if (gateway && subscriptions !== false) {
139 throw new Error([
140 'Subscriptions are not yet compatible with the gateway.',
141 "Set `subscriptions: false` in Apollo Server's constructor to",
142 'explicitly disable subscriptions (which are on by default)',
143 'and allow for gateway functionality.',
144 ].join(' '));
145 }
146 else if (subscriptions !== false) {
147 if (this.supportsSubscriptions()) {
148 if (subscriptions === true || typeof subscriptions === 'undefined') {
149 this.subscriptionServerOptions = {
150 path: this.graphqlPath,
151 };
152 }
153 else if (typeof subscriptions === 'string') {
154 this.subscriptionServerOptions = { path: subscriptions };
155 }
156 else {
157 this.subscriptionServerOptions = Object.assign({ path: this.graphqlPath }, subscriptions);
158 }
159 this.subscriptionsPath = this.subscriptionServerOptions.path;
160 }
161 else if (subscriptions) {
162 throw new Error('This implementation of ApolloServer does not support GraphQL subscriptions.');
163 }
164 }
165 this.playgroundOptions = playground_1.createPlaygroundOptions(playground);
166 this.ensurePluginInstantiation(plugins);
167 if (typeof stopOnTerminationSignals === 'boolean'
168 ? stopOnTerminationSignals
169 : typeof engine === 'object' &&
170 typeof engine.handleSignals === 'boolean'
171 ? engine.handleSignals
172 : isNodeLike_1.default && process.env.NODE_ENV !== 'test') {
173 const signals = ['SIGINT', 'SIGTERM'];
174 let receivedSignal = false;
175 signals.forEach((signal) => {
176 const handler = () => __awaiter(this, void 0, void 0, function* () {
177 if (receivedSignal) {
178 return;
179 }
180 receivedSignal = true;
181 try {
182 yield this.stop();
183 }
184 catch (e) {
185 this.logger.error(`stop() threw during ${signal} shutdown`);
186 this.logger.error(e);
187 process.exit(1);
188 }
189 process.kill(process.pid, signal);
190 });
191 process.on(signal, handler);
192 this.toDisposeLast.add(() => __awaiter(this, void 0, void 0, function* () {
193 process.removeListener(signal, handler);
194 }));
195 });
196 }
197 if (gateway) {
198 this.state = { phase: 'initialized with gateway', gateway };
199 this.requestOptions.executor = gateway.executor;
200 }
201 else {
202 this.state = {
203 phase: 'initialized with schema',
204 schemaDerivedData: this.generateSchemaDerivedData(this.constructSchema()),
205 };
206 this.schema = this.state.schemaDerivedData.schema;
207 }
208 if (this.serverlessFramework()) {
209 this.ensureStarting();
210 }
211 }
212 setGraphQLPath(path) {
213 this.graphqlPath = path;
214 }
215 start() {
216 return __awaiter(this, void 0, void 0, function* () {
217 if (this.serverlessFramework()) {
218 throw new Error('When using an ApolloServer subclass from a serverless framework ' +
219 "package, you don't need to call start(); just call createHandler().");
220 }
221 return yield this._start();
222 });
223 }
224 _start() {
225 var _a;
226 return __awaiter(this, void 0, void 0, function* () {
227 const initialState = this.state;
228 if (initialState.phase !== 'initialized with gateway' &&
229 initialState.phase !== 'initialized with schema') {
230 throw new Error(`called start() with surprising state ${initialState.phase}`);
231 }
232 const barrier = resolvable_1.default();
233 this.state = { phase: 'starting', barrier };
234 let loadedSchema = false;
235 try {
236 const schemaDerivedData = initialState.phase === 'initialized with schema'
237 ? initialState.schemaDerivedData
238 : this.generateSchemaDerivedData(yield this.startGatewayAndLoadSchema(initialState.gateway));
239 loadedSchema = true;
240 this.state = {
241 phase: 'invoking serverWillStart',
242 barrier,
243 schemaDerivedData,
244 };
245 const service = {
246 logger: this.logger,
247 schema: schemaDerivedData.schema,
248 schemaHash: schemaDerivedData.schemaHash,
249 apollo: this.apolloConfig,
250 serverlessFramework: this.serverlessFramework(),
251 engine: {
252 serviceID: this.apolloConfig.graphId,
253 apiKeyHash: this.apolloConfig.keyHash,
254 },
255 };
256 if ((_a = this.requestOptions.persistedQueries) === null || _a === void 0 ? void 0 : _a.cache) {
257 service.persistedQueries = {
258 cache: this.requestOptions.persistedQueries.cache,
259 };
260 }
261 const serverListeners = (yield Promise.all(this.plugins.map((plugin) => plugin.serverWillStart && plugin.serverWillStart(service)))).filter((maybeServerListener) => typeof maybeServerListener === 'object' &&
262 !!maybeServerListener.serverWillStop);
263 this.toDispose.add(() => __awaiter(this, void 0, void 0, function* () {
264 yield Promise.all(serverListeners.map(({ serverWillStop }) => serverWillStop === null || serverWillStop === void 0 ? void 0 : serverWillStop()));
265 }));
266 this.state = { phase: 'started', schemaDerivedData };
267 }
268 catch (error) {
269 this.state = { phase: 'failed to start', error, loadedSchema };
270 throw error;
271 }
272 finally {
273 barrier.resolve();
274 }
275 });
276 }
277 willStart() {
278 return __awaiter(this, void 0, void 0, function* () {
279 this.ensureStarting();
280 });
281 }
282 ensureStarted() {
283 return __awaiter(this, void 0, void 0, function* () {
284 while (true) {
285 switch (this.state.phase) {
286 case 'initialized with gateway':
287 case 'initialized with schema':
288 try {
289 yield this._start();
290 }
291 catch (_a) {
292 }
293 break;
294 case 'starting':
295 case 'invoking serverWillStart':
296 yield this.state.barrier;
297 break;
298 case 'failed to start':
299 this.logStartupError(this.state.error);
300 throw new Error('This data graph is missing a valid configuration. More details may be available in the server logs.');
301 case 'started':
302 return this.state.schemaDerivedData;
303 case 'stopping':
304 throw new Error('Cannot execute GraphQL operations while the server is stopping.');
305 case 'stopped':
306 throw new Error('Cannot execute GraphQL operations after the server has stopped.');
307 default:
308 throw new UnreachableCaseError(this.state);
309 }
310 }
311 });
312 }
313 ensureStarting() {
314 if (this.state.phase === 'initialized with gateway' ||
315 this.state.phase === 'initialized with schema') {
316 this._start().catch((e) => this.logStartupError(e));
317 }
318 }
319 logStartupError(err) {
320 const prelude = this.serverlessFramework()
321 ? 'An error occurred during Apollo Server startup.'
322 : 'Apollo Server was started implicitly and an error occurred during startup. ' +
323 '(Consider calling `await server.start()` immediately after ' +
324 '`server = new ApolloServer()` so you can handle these errors directly before ' +
325 'starting your web server.)';
326 this.logger.error(prelude +
327 ' All GraphQL requests will now fail. The startup error ' +
328 'was: ' +
329 ((err && err.message) || err));
330 }
331 startGatewayAndLoadSchema(gateway) {
332 return __awaiter(this, void 0, void 0, function* () {
333 const unsubscriber = gateway.onSchemaChange((schema) => {
334 if (this.state.phase === 'started') {
335 this.state.schemaDerivedData = this.generateSchemaDerivedData(schema);
336 }
337 });
338 this.toDispose.add(() => __awaiter(this, void 0, void 0, function* () { return unsubscriber(); }));
339 const engineConfig = this.apolloConfig.keyHash && this.apolloConfig.graphId
340 ? {
341 apiKeyHash: this.apolloConfig.keyHash,
342 graphId: this.apolloConfig.graphId,
343 graphVariant: this.apolloConfig.graphVariant,
344 }
345 : undefined;
346 const config = yield gateway.load({
347 apollo: this.apolloConfig,
348 engine: engineConfig,
349 });
350 this.toDispose.add(() => __awaiter(this, void 0, void 0, function* () { var _a; return yield ((_a = gateway.stop) === null || _a === void 0 ? void 0 : _a.call(gateway)); }));
351 return config.schema;
352 });
353 }
354 constructSchema() {
355 const { schema, modules, typeDefs, resolvers, schemaDirectives, parseOptions, } = this.config;
356 if (schema) {
357 return schema;
358 }
359 if (modules) {
360 const { schema, errors } = apollo_tools_1.buildServiceDefinition(modules);
361 if (errors && errors.length > 0) {
362 throw new Error(errors.map((error) => error.message).join('\n\n'));
363 }
364 return schema;
365 }
366 if (!typeDefs) {
367 throw Error('Apollo Server requires either an existing schema, modules or typeDefs');
368 }
369 const augmentedTypeDefs = Array.isArray(typeDefs) ? typeDefs : [typeDefs];
370 if (!isDirectiveDefined_1.isDirectiveDefined(augmentedTypeDefs, 'cacheControl')) {
371 augmentedTypeDefs.push(index_1.gql `
372 enum CacheControlScope {
373 PUBLIC
374 PRIVATE
375 }
376
377 directive @cacheControl(
378 maxAge: Int
379 scope: CacheControlScope
380 ) on FIELD_DEFINITION | OBJECT | INTERFACE
381 `);
382 }
383 if (this.uploadsConfig) {
384 const { GraphQLUpload } = require('@apollographql/graphql-upload-8-fork');
385 if (Array.isArray(resolvers)) {
386 if (resolvers.every((resolver) => !resolver.Upload)) {
387 resolvers.push({ Upload: GraphQLUpload });
388 }
389 }
390 else {
391 if (resolvers && !resolvers.Upload) {
392 resolvers.Upload = GraphQLUpload;
393 }
394 }
395 augmentedTypeDefs.push(index_1.gql `
396 scalar Upload
397 `);
398 }
399 return graphql_tools_1.makeExecutableSchema({
400 typeDefs: augmentedTypeDefs,
401 schemaDirectives,
402 resolvers,
403 parseOptions,
404 });
405 }
406 generateSchemaDerivedData(schema) {
407 const schemaHash = schemaHash_1.generateSchemaHash(schema);
408 const { mocks, mockEntireSchema, extensions: _extensions } = this.config;
409 if (mocks || (typeof mockEntireSchema !== 'undefined' && mocks !== false)) {
410 graphql_tools_1.addMockFunctionsToSchema({
411 schema,
412 mocks: typeof mocks === 'boolean' || typeof mocks === 'undefined'
413 ? {}
414 : mocks,
415 preserveResolvers: typeof mockEntireSchema === 'undefined' ? false : !mockEntireSchema,
416 });
417 }
418 const extensions = [];
419 extensions.push(...(_extensions || []));
420 const documentStore = this.initializeDocumentStore();
421 return {
422 schema,
423 schemaHash,
424 extensions,
425 documentStore,
426 };
427 }
428 stop() {
429 return __awaiter(this, void 0, void 0, function* () {
430 if (this.state.phase === 'stopped') {
431 if (this.state.stopError) {
432 throw this.state.stopError;
433 }
434 return;
435 }
436 if (this.state.phase === 'stopping') {
437 yield this.state.barrier;
438 const state = this.state;
439 if (state.phase !== 'stopped') {
440 throw Error(`Surprising post-stopping state ${state.phase}`);
441 }
442 if (state.stopError) {
443 throw state.stopError;
444 }
445 return;
446 }
447 this.state = { phase: 'stopping', barrier: resolvable_1.default() };
448 try {
449 yield Promise.all([...this.toDispose].map((dispose) => dispose()));
450 if (this.subscriptionServer)
451 this.subscriptionServer.close();
452 yield Promise.all([...this.toDisposeLast].map((dispose) => dispose()));
453 }
454 catch (stopError) {
455 this.state = { phase: 'stopped', stopError };
456 return;
457 }
458 this.state = { phase: 'stopped', stopError: null };
459 });
460 }
461 installSubscriptionHandlers(server) {
462 if (!this.subscriptionServerOptions) {
463 if (this.config.gateway) {
464 throw Error('Subscriptions are not supported when operating as a gateway');
465 }
466 if (this.supportsSubscriptions()) {
467 throw Error('Subscriptions are disabled, due to subscriptions set to false in the ApolloServer constructor');
468 }
469 else {
470 throw Error('Subscriptions are not supported, choose an integration, such as apollo-server-express that allows persistent connections');
471 }
472 }
473 const { SubscriptionServer } = require('subscriptions-transport-ws');
474 const { onDisconnect, onConnect, keepAlive, path, } = this.subscriptionServerOptions;
475 let schema;
476 switch (this.state.phase) {
477 case 'initialized with schema':
478 case 'invoking serverWillStart':
479 case 'started':
480 schema = this.state.schemaDerivedData.schema;
481 break;
482 case 'initialized with gateway':
483 case 'starting':
484 case 'failed to start':
485 case 'stopping':
486 case 'stopped':
487 throw new Error(`Can't install subscription handlers when state is ${this.state.phase}`);
488 default:
489 throw new UnreachableCaseError(this.state);
490 }
491 this.subscriptionServer = SubscriptionServer.create({
492 schema,
493 execute: graphql_1.execute,
494 subscribe: graphql_1.subscribe,
495 onConnect: onConnect
496 ? onConnect
497 : (connectionParams) => (Object.assign({}, connectionParams)),
498 onDisconnect: onDisconnect,
499 onOperation: (message, connection) => __awaiter(this, void 0, void 0, function* () {
500 connection.formatResponse = (value) => (Object.assign(Object.assign({}, value), { errors: value.errors &&
501 apollo_server_errors_1.formatApolloErrors([...value.errors], {
502 formatter: this.requestOptions.formatError,
503 debug: this.requestOptions.debug,
504 }) }));
505 connection.formatError = this.requestOptions.formatError;
506 let context = this.context ? this.context : { connection };
507 try {
508 context =
509 typeof this.context === 'function'
510 ? yield this.context({ connection, payload: message.payload })
511 : context;
512 }
513 catch (e) {
514 throw apollo_server_errors_1.formatApolloErrors([e], {
515 formatter: this.requestOptions.formatError,
516 debug: this.requestOptions.debug,
517 })[0];
518 }
519 return Object.assign(Object.assign({}, connection), { context });
520 }),
521 keepAlive,
522 validationRules: this.requestOptions.validationRules,
523 }, server instanceof net_1.Server || server instanceof tls_1.Server
524 ? {
525 server,
526 path,
527 }
528 : server);
529 }
530 supportsSubscriptions() {
531 return false;
532 }
533 supportsUploads() {
534 return false;
535 }
536 serverlessFramework() {
537 return false;
538 }
539 ensurePluginInstantiation(plugins = []) {
540 var _a, _b;
541 const pluginsToInit = [];
542 if (this.config.tracing) {
543 pluginsToInit.push(apollo_tracing_1.plugin());
544 }
545 if (this.config.cacheControl !== false) {
546 let cacheControlOptions = {};
547 if (typeof this.config.cacheControl === 'boolean' &&
548 this.config.cacheControl === true) {
549 cacheControlOptions = {
550 stripFormattedExtensions: false,
551 calculateHttpHeaders: false,
552 defaultMaxAge: 0,
553 };
554 }
555 else {
556 cacheControlOptions = Object.assign({ stripFormattedExtensions: true, calculateHttpHeaders: true, defaultMaxAge: 0 }, this.config.cacheControl);
557 }
558 pluginsToInit.push(apollo_cache_control_1.plugin(cacheControlOptions));
559 }
560 pluginsToInit.push(...plugins);
561 this.plugins = pluginsToInit.map((plugin) => {
562 if (typeof plugin === 'function') {
563 return plugin();
564 }
565 return plugin;
566 });
567 const alreadyHavePluginWithInternalId = (id) => this.plugins.some((p) => internalPlugin_1.pluginIsInternal(p) && p.__internal_plugin_id__() === id);
568 {
569 const alreadyHavePlugin = alreadyHavePluginWithInternalId('UsageReporting');
570 const { engine } = this.config;
571 const disabledViaLegacyOption = engine === false ||
572 (typeof engine === 'object' && engine.reportTiming === false);
573 if (alreadyHavePlugin) {
574 if (engine !== undefined) {
575 throw Error("You can't combine the legacy `new ApolloServer({engine})` option with directly " +
576 'creating an ApolloServerPluginUsageReporting plugin. See ' +
577 'https://go.apollo.dev/s/migration-engine-plugins');
578 }
579 }
580 else if (this.apolloConfig.key && !disabledViaLegacyOption) {
581 this.plugins.unshift(typeof engine === 'object'
582 ? plugin_1.ApolloServerPluginUsageReportingFromLegacyOptions(engine)
583 : plugin_1.ApolloServerPluginUsageReporting());
584 }
585 }
586 {
587 const alreadyHavePlugin = alreadyHavePluginWithInternalId('SchemaReporting');
588 const enabledViaEnvVar = process.env.APOLLO_SCHEMA_REPORTING === 'true';
589 const { engine } = this.config;
590 const enabledViaLegacyOption = typeof engine === 'object' &&
591 (engine.reportSchema || engine.experimental_schemaReporting);
592 if (alreadyHavePlugin || enabledViaEnvVar || enabledViaLegacyOption) {
593 if (this.config.gateway) {
594 throw new Error([
595 "Schema reporting is not yet compatible with the gateway. If you're",
596 'interested in using schema reporting with the gateway, please',
597 'contact Apollo support. To set up managed federation, see',
598 'https://go.apollo.dev/s/managed-federation',
599 ].join(' '));
600 }
601 }
602 if (alreadyHavePlugin) {
603 if (engine !== undefined) {
604 throw Error("You can't combine the legacy `new ApolloServer({engine})` option with directly " +
605 'creating an ApolloServerPluginSchemaReporting plugin. See ' +
606 'https://go.apollo.dev/s/migration-engine-plugins');
607 }
608 }
609 else if (!this.apolloConfig.key) {
610 if (enabledViaEnvVar) {
611 throw new Error("You've enabled schema reporting by setting the APOLLO_SCHEMA_REPORTING " +
612 'environment variable to true, but you also need to provide your ' +
613 'Apollo API key, via the APOLLO_KEY environment ' +
614 'variable or via `new ApolloServer({apollo: {key})');
615 }
616 if (enabledViaLegacyOption) {
617 throw new Error("You've enabled schema reporting in the `engine` argument to `new ApolloServer()`, " +
618 'but you also need to provide your Apollo API key, via the APOLLO_KEY environment ' +
619 'variable or via `new ApolloServer({apollo: {key})');
620 }
621 }
622 else if (enabledViaEnvVar || enabledViaLegacyOption) {
623 const options = {};
624 if (typeof engine === 'object') {
625 options.initialDelayMaxMs = (_a = engine.schemaReportingInitialDelayMaxMs) !== null && _a !== void 0 ? _a : engine.experimental_schemaReportingInitialDelayMaxMs;
626 options.overrideReportedSchema = (_b = engine.overrideReportedSchema) !== null && _b !== void 0 ? _b : engine.experimental_overrideReportedSchema;
627 options.endpointUrl = engine.schemaReportingUrl;
628 }
629 this.plugins.push(plugin_1.ApolloServerPluginSchemaReporting(options));
630 }
631 }
632 {
633 const alreadyHavePlugin = alreadyHavePluginWithInternalId('InlineTrace');
634 const { engine } = this.config;
635 if (alreadyHavePlugin) {
636 if (engine !== undefined) {
637 throw Error("You can't combine the legacy `new ApolloServer({engine})` option with directly " +
638 'creating an ApolloServerPluginInlineTrace plugin. See ' +
639 'https://go.apollo.dev/s/migration-engine-plugins');
640 }
641 }
642 else if (this.config.engine !== false) {
643 const options = {
644 __onlyIfSchemaIsFederated: true,
645 };
646 if (typeof engine === 'object') {
647 options.rewriteError = engine.rewriteError;
648 }
649 this.plugins.push(plugin_1.ApolloServerPluginInlineTrace(options));
650 }
651 }
652 }
653 initializeDocumentStore() {
654 return new apollo_server_caching_1.InMemoryLRUCache({
655 maxSize: Math.pow(2, 20) * (this.experimental_approximateDocumentStoreMiB || 30),
656 sizeCalculator: approximateObjectSize,
657 });
658 }
659 graphQLServerOptions(integrationContextArgument) {
660 return __awaiter(this, void 0, void 0, function* () {
661 const { schema, schemaHash, documentStore, extensions, } = yield this.ensureStarted();
662 let context = this.context ? this.context : {};
663 try {
664 context =
665 typeof this.context === 'function'
666 ? yield this.context(integrationContextArgument || {})
667 : context;
668 }
669 catch (error) {
670 context = () => {
671 throw error;
672 };
673 }
674 return Object.assign({ schema,
675 schemaHash, logger: this.logger, plugins: this.plugins, documentStore,
676 extensions,
677 context, persistedQueries: this.requestOptions
678 .persistedQueries, fieldResolver: this.requestOptions.fieldResolver, parseOptions: this.parseOptions }, this.requestOptions);
679 });
680 }
681 executeOperation(request, integrationContextArgument) {
682 return __awaiter(this, void 0, void 0, function* () {
683 const options = yield this.graphQLServerOptions(integrationContextArgument);
684 if (typeof options.context === 'function') {
685 options.context = options.context();
686 }
687 else if (typeof options.context === 'object') {
688 options.context = runHttpQuery_1.cloneObject(options.context);
689 }
690 const requestCtx = {
691 logger: this.logger,
692 schema: options.schema,
693 schemaHash: options.schemaHash,
694 request: Object.assign(Object.assign({}, request), { query: request.query && typeof request.query !== 'string'
695 ? graphql_1.print(request.query)
696 : request.query }),
697 context: options.context || Object.create(null),
698 cache: options.cache,
699 metrics: {},
700 response: {
701 http: {
702 headers: new apollo_server_env_1.Headers(),
703 },
704 },
705 debug: options.debug,
706 };
707 return requestPipeline_1.processGraphQLRequest(options, requestCtx);
708 });
709 }
710}
711exports.ApolloServerBase = ApolloServerBase;
712function printNodeFileUploadsMessage(logger) {
713 logger.error([
714 '*****************************************************************',
715 '* *',
716 '* ERROR! Manual intervention is necessary for Node.js < v8.5.0! *',
717 '* *',
718 '*****************************************************************',
719 '',
720 'The third-party `graphql-upload` package, which is used to implement',
721 'file uploads in Apollo Server 2.x, no longer supports Node.js LTS',
722 'versions prior to Node.js v8.5.0.',
723 '',
724 'Deployments which NEED file upload capabilities should update to',
725 'Node.js >= v8.5.0 to continue using uploads.',
726 '',
727 'If this server DOES NOT NEED file uploads and wishes to continue',
728 'using this version of Node.js, uploads can be disabled by adding:',
729 '',
730 ' uploads: false,',
731 '',
732 '...to the options for Apollo Server and re-deploying the server.',
733 '',
734 'For more information, see https://bit.ly/gql-upload-node-6.',
735 '',
736 ].join('\n'));
737}
738//# sourceMappingURL=ApolloServer.js.map
\No newline at end of file