UNPKG

17.6 kBJavaScriptView Raw
1"use strict";
2// TODO-MVP: Add custom scalars such as graphql-iso-date
3// import { GraphQLDate, GraphQLDateTime, GraphQLTime } from 'graphql-iso-date';
4var __assign = (this && this.__assign) || function () {
5 __assign = Object.assign || function(t) {
6 for (var s, i = 1, n = arguments.length; i < n; i++) {
7 s = arguments[i];
8 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
9 t[p] = s[p];
10 }
11 return t;
12 };
13 return __assign.apply(this, arguments);
14};
15var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
16 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
17 return new (P || (P = Promise))(function (resolve, reject) {
18 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
19 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
20 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
21 step((generator = generator.apply(thisArg, _arguments || [])).next());
22 });
23};
24var __generator = (this && this.__generator) || function (thisArg, body) {
25 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
26 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
27 function verb(n) { return function (v) { return step([n, v]); }; }
28 function step(op) {
29 if (f) throw new TypeError("Generator is already executing.");
30 while (_) try {
31 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
32 if (y = 0, t) op = [op[0] & 2, t.value];
33 switch (op[0]) {
34 case 0: case 1: t = op; break;
35 case 4: _.label++; return { value: op[1], done: false };
36 case 5: _.label++; y = op[1]; op = [0]; continue;
37 case 7: op = _.ops.pop(); _.trys.pop(); continue;
38 default:
39 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
40 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
41 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
42 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
43 if (t[2]) _.ops.pop();
44 _.trys.pop(); continue;
45 }
46 op = body.call(thisArg, _);
47 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
48 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
49 }
50};
51var __spreadArrays = (this && this.__spreadArrays) || function () {
52 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
53 for (var r = Array(s), k = 0, i = 0; i < il; i++)
54 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
55 r[k] = a[j];
56 return r;
57};
58Object.defineProperty(exports, "__esModule", { value: true });
59exports.App = exports.Server = void 0;
60var apollo_server_express_1 = require("apollo-server-express");
61var express = require("express");
62var graphql_1 = require("graphql");
63var open = require('open'); // eslint-disable-line @typescript-eslint/no-var-requires
64var type_graphql_1 = require("type-graphql"); // formatArgumentValidationError
65var typedi_1 = require("typedi");
66var typeorm_1 = require("typeorm");
67var logger_1 = require("../core/logger");
68var gql_1 = require("../gql");
69var middleware_1 = require("../middleware");
70var torm_1 = require("../torm");
71var code_generator_1 = require("./code-generator");
72var config_1 = require("./config");
73var Debug = require("debug");
74var debug = Debug('warthog:server');
75var Server = /** @class */ (function () {
76 function Server(appOptions, dbOptions) {
77 if (dbOptions === void 0) { dbOptions = {}; }
78 this.appOptions = appOptions;
79 this.dbOptions = dbOptions;
80 if (typeof this.appOptions.host !== 'undefined') {
81 process.env.WARTHOG_APP_HOST = this.appOptions.host;
82 // When we move to v2.0 we'll officially deprecate these config values in favor of ENV vars
83 // throw new Error(
84 // '`host` option has been removed, please set `WARTHOG_APP_HOST` environment variable instead'
85 // );
86 }
87 if (typeof this.appOptions.port !== 'undefined') {
88 process.env.WARTHOG_APP_PORT = this.appOptions.port.toString();
89 }
90 if (typeof this.appOptions.generatedFolder !== 'undefined') {
91 process.env.WARTHOG_GENERATED_FOLDER = this.appOptions.generatedFolder;
92 }
93 if (typeof this.appOptions.introspection !== 'undefined') {
94 process.env.WARTHOG_INTROSPECTION = this.appOptions.introspection ? 'true' : 'false';
95 }
96 if (typeof this.appOptions.openPlayground !== 'undefined') {
97 process.env.WARTHOG_AUTO_OPEN_PLAYGROUND = this.appOptions.openPlayground ? 'true' : 'false';
98 }
99 if (typeof this.appOptions.autoGenerateFiles !== 'undefined') {
100 process.env.WARTHOG_AUTO_GENERATE_FILES = this.appOptions.autoGenerateFiles
101 ? 'true'
102 : 'false';
103 }
104 // Ensure that Warthog, TypeORM and TypeGraphQL are all using the same typedi container
105 this.container = this.appOptions.container || typedi_1.Container;
106 typeorm_1.useContainer(this.container); // TODO: fix any
107 this.authChecker = this.appOptions.authChecker;
108 this.bodyParserConfig = this.appOptions.bodyParserConfig;
109 this.apolloConfig = this.appOptions.apolloConfig || {};
110 this.logger = this.getLogger();
111 // NOTE: this should be after we hard-code the WARTHOG_ env vars above because we want the config
112 // module to think they were set by the user
113 this.config = new config_1.Config({ container: this.container, logger: this.logger });
114 this.expressApp = this.appOptions.expressApp || express();
115 if (!process.env.NODE_ENV) {
116 throw new Error("NODE_ENV must be set - use 'development' locally");
117 }
118 }
119 Server.prototype.getLogger = function () {
120 if (this.appOptions.logger) {
121 return this.appOptions.logger;
122 // } else if (Container.has('warthog.logger')) {
123 // return Container.get('warthog.logger');
124 }
125 return logger_1.logger;
126 };
127 Server.prototype.establishDBConnection = function () {
128 return __awaiter(this, void 0, void 0, function () {
129 var _a;
130 return __generator(this, function (_b) {
131 switch (_b.label) {
132 case 0:
133 if (!!this.connection) return [3 /*break*/, 2];
134 debug('establishDBConnection:start');
135 _a = this;
136 return [4 /*yield*/, torm_1.createDBConnection(this.dbOptions)];
137 case 1:
138 _a.connection = _b.sent();
139 debug('establishDBConnection:end');
140 _b.label = 2;
141 case 2: return [2 /*return*/, this.connection];
142 }
143 });
144 });
145 };
146 Server.prototype.getServerUrl = function () {
147 return this.config.get('APP_PROTOCOL') + "://" + this.config.get('APP_HOST') + ":" + this.config.get('APP_PORT');
148 };
149 Server.prototype.getGraphQLServerUrl = function () {
150 return this.getServerUrl() + "/graphql";
151 };
152 Server.prototype.getBinding = function (options) {
153 if (options === void 0) { options = {}; }
154 return __awaiter(this, void 0, void 0, function () {
155 var binding, error_1, messages;
156 return __generator(this, function (_a) {
157 switch (_a.label) {
158 case 0:
159 _a.trys.push([0, 2, , 3]);
160 return [4 /*yield*/, gql_1.getRemoteBinding(this.getGraphQLServerUrl(), __assign({ origin: 'warthog' }, options))];
161 case 1:
162 binding = _a.sent();
163 return [2 /*return*/, binding];
164 case 2:
165 error_1 = _a.sent();
166 if (error_1.result && error_1.result.errors) {
167 messages = error_1.result.errors.map(function (item) { return item.message; });
168 throw new Error(JSON.stringify(messages));
169 }
170 throw error_1;
171 case 3: return [2 /*return*/];
172 }
173 });
174 });
175 };
176 Server.prototype.buildGraphQLSchema = function () {
177 return __awaiter(this, void 0, void 0, function () {
178 var _a;
179 return __generator(this, function (_b) {
180 switch (_b.label) {
181 case 0:
182 if (!!this.schema) return [3 /*break*/, 2];
183 debug('server:buildGraphQLSchema:start');
184 _a = this;
185 return [4 /*yield*/, type_graphql_1.buildSchema({
186 authChecker: this.authChecker,
187 scalarsMap: [
188 {
189 type: 'ID',
190 scalar: graphql_1.GraphQLID
191 }
192 ],
193 container: this.container,
194 // TODO: ErrorLoggerMiddleware
195 globalMiddlewares: __spreadArrays([middleware_1.DataLoaderMiddleware], (this.appOptions.middlewares || [])),
196 resolvers: this.config.get('RESOLVERS_PATH'),
197 // TODO: scalarsMap: [{ type: GraphQLDate, scalar: GraphQLDate }]
198 validate: this.config.get('VALIDATE_RESOLVERS') === 'true'
199 })];
200 case 1:
201 _a.schema = _b.sent();
202 debug('server:buildGraphQLSchema:end');
203 _b.label = 2;
204 case 2: return [2 /*return*/, this.schema];
205 }
206 });
207 });
208 };
209 Server.prototype.generateFiles = function () {
210 return __awaiter(this, void 0, void 0, function () {
211 return __generator(this, function (_a) {
212 switch (_a.label) {
213 case 0:
214 debug('start:generateFiles:start');
215 return [4 /*yield*/, new code_generator_1.CodeGenerator(this.config.get('GENERATED_FOLDER'), this.config.get('DB_ENTITIES'), {
216 resolversPath: this.config.get('RESOLVERS_PATH'),
217 validateResolvers: this.config.get('VALIDATE_RESOLVERS') === 'true',
218 warthogImportPath: this.config.get('MODULE_IMPORT_PATH')
219 }).generate()];
220 case 1:
221 _a.sent();
222 debug('start:generateFiles:end');
223 return [2 /*return*/];
224 }
225 });
226 });
227 };
228 Server.prototype.startHttpServer = function (url) {
229 var _this = this;
230 var keepAliveTimeout = Number(this.config.get('WARTHOG_KEEP_ALIVE_TIMEOUT_MS'));
231 var headersTimeout = Number(this.config.get('WARTHOG_HEADERS_TIMEOUT_MS'));
232 this.httpServer = this.expressApp.listen({ port: this.config.get('APP_PORT') }, function () {
233 return _this.logger.info("\uD83D\uDE80 Server ready at " + url);
234 });
235 this.httpServer.keepAliveTimeout = keepAliveTimeout;
236 this.httpServer.headersTimeout = headersTimeout;
237 };
238 Server.prototype.start = function () {
239 return __awaiter(this, void 0, void 0, function () {
240 var contextGetter, playgroundOption, introspectionOption, url, process_1;
241 var _this = this;
242 return __generator(this, function (_a) {
243 switch (_a.label) {
244 case 0:
245 debug('start:start');
246 return [4 /*yield*/, this.establishDBConnection()];
247 case 1:
248 _a.sent();
249 if (!(this.config.get('AUTO_GENERATE_FILES') === 'true')) return [3 /*break*/, 3];
250 return [4 /*yield*/, this.generateFiles()];
251 case 2:
252 _a.sent();
253 _a.label = 3;
254 case 3: return [4 /*yield*/, this.buildGraphQLSchema()];
255 case 4:
256 _a.sent();
257 contextGetter = this.appOptions.context ||
258 (function () { return __awaiter(_this, void 0, void 0, function () {
259 return __generator(this, function (_a) {
260 return [2 /*return*/, {}];
261 });
262 }); });
263 debug('start:ApolloServerAllocation:start');
264 playgroundOption = this.config.get('PLAYGROUND') === 'true' ? { playground: true } : {};
265 introspectionOption = this.config.get('INTROSPECTION') === 'true' ? { introspection: true } : {};
266 this.graphQLServer = new apollo_server_express_1.ApolloServer(__assign(__assign(__assign(__assign({ context: function (options) { return __awaiter(_this, void 0, void 0, function () {
267 var consumerCtx;
268 return __generator(this, function (_a) {
269 switch (_a.label) {
270 case 0: return [4 /*yield*/, contextGetter(options.req)];
271 case 1:
272 consumerCtx = _a.sent();
273 return [2 /*return*/, __assign({ connection: this.connection, dataLoader: {
274 initialized: false,
275 loaders: {}
276 }, request: options.req }, consumerCtx)];
277 }
278 });
279 }); } }, playgroundOption), introspectionOption), { schema: this.schema }), this.apolloConfig));
280 debug('start:ApolloServerAllocation:end');
281 this.expressApp.use('/health', middleware_1.healthCheckMiddleware);
282 if (this.appOptions.onBeforeGraphQLMiddleware) {
283 this.appOptions.onBeforeGraphQLMiddleware(this.expressApp);
284 }
285 debug('start:applyMiddleware:start');
286 this.graphQLServer.applyMiddleware({
287 app: this.expressApp,
288 bodyParserConfig: this.bodyParserConfig,
289 path: '/graphql'
290 });
291 debug('start:applyMiddleware:end');
292 if (this.appOptions.onAfterGraphQLMiddleware) {
293 this.appOptions.onAfterGraphQLMiddleware(this.expressApp);
294 }
295 url = this.getGraphQLServerUrl();
296 this.startHttpServer(url);
297 // Open up websocket connection for subscriptions
298 if (this.config.get('SUBSCRIPTIONS') === 'true') {
299 this.graphQLServer.installSubscriptionHandlers(this.httpServer);
300 }
301 // Open playground in the browser
302 if (this.config.get('AUTO_OPEN_PLAYGROUND') === 'true') {
303 process_1 = open(url, { wait: false });
304 debug('process', process_1);
305 }
306 debug('start:end');
307 return [2 /*return*/, this];
308 }
309 });
310 });
311 };
312 Server.prototype.stop = function () {
313 return __awaiter(this, void 0, void 0, function () {
314 return __generator(this, function (_a) {
315 switch (_a.label) {
316 case 0:
317 this.logger.info('Stopping HTTP Server');
318 this.httpServer.close();
319 this.logger.info('Closing DB Connection');
320 return [4 /*yield*/, this.connection.close()];
321 case 1:
322 _a.sent();
323 return [2 /*return*/];
324 }
325 });
326 });
327 };
328 return Server;
329}());
330exports.Server = Server;
331// Backwards compatability. This was renamed.
332exports.App = Server;
333//# sourceMappingURL=server.js.map
\No newline at end of file