1 | "use strict";
|
2 | var __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 | };
|
11 | var __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 | };
|
22 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
23 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
24 | };
|
25 | Object.defineProperty(exports, "__esModule", { value: true });
|
26 | exports.ApolloServerBase = void 0;
|
27 | const graphql_tools_1 = require("graphql-tools");
|
28 | const net_1 = require("net");
|
29 | const tls_1 = require("tls");
|
30 | const loglevel_1 = __importDefault(require("loglevel"));
|
31 | const graphql_1 = require("graphql");
|
32 | const resolvable_1 = __importDefault(require("@josephg/resolvable"));
|
33 | const apollo_server_caching_1 = require("apollo-server-caching");
|
34 | const runtimeSupportsUploads_1 = __importDefault(require("./utils/runtimeSupportsUploads"));
|
35 | const apollo_server_errors_1 = require("apollo-server-errors");
|
36 | const index_1 = require("./index");
|
37 | const playground_1 = require("./playground");
|
38 | const schemaHash_1 = require("./utils/schemaHash");
|
39 | const isDirectiveDefined_1 = require("./utils/isDirectiveDefined");
|
40 | const requestPipeline_1 = require("./requestPipeline");
|
41 | const apollo_server_env_1 = require("apollo-server-env");
|
42 | const apollo_tools_1 = require("@apollographql/apollo-tools");
|
43 | const apollo_tracing_1 = require("apollo-tracing");
|
44 | const apollo_cache_control_1 = require("apollo-cache-control");
|
45 | const runHttpQuery_1 = require("./runHttpQuery");
|
46 | const isNodeLike_1 = __importDefault(require("./utils/isNodeLike"));
|
47 | const determineApolloConfig_1 = require("./determineApolloConfig");
|
48 | const plugin_1 = require("./plugin");
|
49 | const internalPlugin_1 = require("./plugin/internalPlugin");
|
50 | const 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 | });
|
57 | const forbidUploadsForTesting = process && process.env.NODE_ENV === 'test' && !runtimeSupportsUploads_1.default;
|
58 | function approximateObjectSize(obj) {
|
59 | return Buffer.byteLength(JSON.stringify(obj), 'utf8');
|
60 | }
|
61 | class UnreachableCaseError extends Error {
|
62 | constructor(val) {
|
63 | super(`Unreachable case: ${val}`);
|
64 | }
|
65 | }
|
66 | class 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 | }
|
711 | exports.ApolloServerBase = ApolloServerBase;
|
712 | function 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 |
|
\ | No newline at end of file |