UNPKG

21.9 kBJavaScriptView Raw
1"use strict";
2function __export(m) {
3 for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
4}
5var __importDefault = (this && this.__importDefault) || function (mod) {
6 return (mod && mod.__esModule) ? mod : { "default": mod };
7};
8var __importStar = (this && this.__importStar) || function (mod) {
9 if (mod && mod.__esModule) return mod;
10 var result = {};
11 if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
12 result["default"] = mod;
13 return result;
14};
15Object.defineProperty(exports, "__esModule", { value: true });
16if (+process.versions.node.replace(/\.\d+$/, '') < 12)
17 throw new Error(`Required version of node: >=12, current: ${process.versions.node}`);
18const dotenv_1 = __importDefault(require("dotenv"));
19exports.ENV = process.env.NODE_ENV || 'development';
20const envFiles = ['.env', '.env.local', '.env.' + exports.ENV, '.env.' + exports.ENV + '.local'];
21envFiles.forEach(path => Object.assign(process.env, dotenv_1.default.config({ path }).parsed));
22const cors_1 = __importDefault(require("cors"));
23require("deps-check");
24const express_1 = __importDefault(require("express"));
25const express_graphql_1 = __importDefault(require("express-graphql"));
26const express_session_1 = __importDefault(require("express-session"));
27const graphql_1 = require("graphql");
28const path_1 = require("path");
29const ts2graphql_1 = require("ts2graphql");
30const dbInit_1 = require("./dbInit");
31const graphQLUtils_1 = require("./graphQLUtils");
32const bodyparser = __importStar(require("body-parser"));
33const serve_static_1 = __importDefault(require("serve-static"));
34const fs_1 = require("fs");
35const https_1 = __importDefault(require("https"));
36const http_1 = __importDefault(require("http"));
37const logger_1 = require("./logger");
38const find_up_1 = __importDefault(require("find-up"));
39const utils_1 = require("./utils");
40// import * as diskusage from 'diskusage';
41__export(require("./di"));
42__export(require("./graphQLUtils"));
43__export(require("./Orm/PostgresqlDriver"));
44__export(require("./request"));
45__export(require("./testUtils"));
46__export(require("./utils"));
47__export(require("./dateUtils"));
48__export(require("./assert"));
49__export(require("./logger"));
50exports.bodyParser = bodyparser;
51exports.PRODUCTION = exports.ENV === 'production';
52let EXITING = false;
53async function createGraphqApp(options, runMiddlewares) {
54 let db;
55 let dbPool;
56 try {
57 logger_1.logger.info('------------------------ START PROGRAM ----------------------', { pid: process.pid });
58 logger_1.logger.info('ENV', { ENV: exports.ENV });
59 if (options.db) {
60 const dbRes = await dbInit_1.dbInit(projectDir, options.db);
61 db = dbRes.db;
62 dbPool = dbRes.pool;
63 }
64 const express = express_1.default();
65 express.disable('x-powered-by');
66 express.use((_req, res, next) => {
67 if (EXITING) {
68 res.status(503);
69 res.send({ status: 'error', error: { message: 'Service unavailable' } });
70 return;
71 }
72 next();
73 });
74 if (options.session) {
75 express.use(express_session_1.default({
76 name: 'sid',
77 resave: true,
78 saveUninitialized: true,
79 ...options.session,
80 }));
81 }
82 if (options.static) {
83 express.use(serve_static_1.default(options.static.rootDir, options.static.options));
84 }
85 if (!exports.PRODUCTION) {
86 express.use(cors_1.default());
87 }
88 if (options.parcel) {
89 const Bundler = require('parcel-bundler');
90 const bundler = new Bundler(options.parcel.indexFilename, { cache: false });
91 express.use(bundler.middleware());
92 }
93 const schema = ts2graphql_1.createSchema(options.graphql.schema, {
94 customScalarFactory: type => type.type === 'string' && type.rawType !== undefined ? graphQLUtils_1.graphQLBigintTypeFactory(type.rawType) : undefined,
95 });
96 // console.log(printSchema(schema));
97 graphql_1.validateSchema(schema).forEach(err => {
98 throw err;
99 });
100 function handleError(error) {
101 logger_1.logger.error(error);
102 if (error instanceof logger_1.ClientException) {
103 return { error: error.name, status: 400 };
104 }
105 debugger;
106 /* istanbul ignore next */
107 return { error: options.errors.unknown, status: 500 };
108 }
109 // console.log(printSchema(schema));
110 express.get('/api/graphql', express_graphql_1.default({
111 schema: schema,
112 rootValue: options.graphql.resolver,
113 graphiql: true,
114 }));
115 express.post('/api/graphql', (_req, res, next) => {
116 const sendJson = res.json.bind(res);
117 res.json = (json) => {
118 if (json && json.errors) {
119 json.errors = json.errors.map(graphqlError => {
120 const originalError = graphqlError.originalError || graphqlError;
121 if (originalError instanceof graphql_1.GraphQLError) {
122 return originalError;
123 }
124 const { error, status } = handleError(originalError);
125 res.statusCode = status;
126 return error;
127 });
128 }
129 return sendJson(json);
130 };
131 next();
132 }, express_graphql_1.default({
133 schema: schema,
134 rootValue: options.graphql.resolver,
135 ...{ customFormatErrorFn: (err) => err },
136 }));
137 const server = options.https
138 ? https_1.default.createServer({
139 key: fs_1.readFileSync(options.https.privateKeyFile, 'utf8'),
140 cert: fs_1.readFileSync(options.https.certificateFile, 'utf8'),
141 }, express)
142 : http_1.default.createServer(express);
143 const port = options.https ? options.https.port || 4443 : options.port;
144 server.listen(port, () => logger_1.logger.info(`server starts on port`, { port }));
145 const result = {
146 server,
147 express,
148 projectDir,
149 db: db,
150 dbPool: dbPool,
151 };
152 if (runMiddlewares) {
153 await runMiddlewares(result);
154 }
155 /* istanbul ignore next */
156 express.use((err, _, res, next) => {
157 const { error, status } = handleError(err);
158 if (res.headersSent) {
159 return next(err);
160 }
161 res.status(status);
162 res.send({ status: 'error', error: error });
163 });
164 return result;
165 }
166 catch (err) {
167 if (dbPool) {
168 await dbPool.end();
169 }
170 throw err;
171 }
172}
173exports.createGraphqApp = createGraphqApp;
174const packageJsonFile = find_up_1.default.sync('package.json', { cwd: require.main.filename });
175if (!packageJsonFile)
176 throw new logger_1.Exception('package.json is not found');
177const projectDir = path_1.dirname(packageJsonFile);
178const initFile = projectDir + '/.status';
179let activeThreadsCount = 0;
180function asyncThread(fn) {
181 return (req, res, next) => {
182 activeThreadsCount++;
183 fn(req, res)
184 .then(ret => res.send(ret || { status: 'ok' }), next)
185 .finally(() => activeThreadsCount--);
186 };
187}
188exports.asyncThread = asyncThread;
189let lastExitRequestTime = 0;
190[`SIGINT`, `SIGUSR1`, `SIGUSR2`, `SIGTERM`].forEach(eventType => {
191 process.on(eventType, async (code) => {
192 // console.log('exit', {now: Date.now(), lastExitRequestTime, EXITING});
193 if (EXITING && Date.now() - lastExitRequestTime < 10)
194 return;
195 if (EXITING) {
196 logger_1.logger.warn('Force Exit Double SIGINT', { activeThreadsCount });
197 fs_1.writeFileSync(initFile, 'ok');
198 process.exit();
199 }
200 lastExitRequestTime = Date.now();
201 logger_1.logger.info('Exit requested', { eventType, code, activeThreadsCount });
202 EXITING = true;
203 let softExit = false;
204 for (let i = 0; i < 300; i++) {
205 if (activeThreadsCount === 0) {
206 softExit = true;
207 break;
208 }
209 await utils_1.sleep(100);
210 }
211 if (softExit) {
212 logger_1.logger.info('Exit');
213 }
214 else {
215 logger_1.logger.warn('Force Exit', { activeThreadsCount });
216 }
217 fs_1.writeFileSync(initFile, 'ok');
218 process.exit();
219 });
220});
221function round(val, round) {
222 return Math.round(val / round) * round;
223}
224let prevCpuUsage = process.cpuUsage();
225const SYSTEM_HEALTH_INTERVAL = 600000;
226setInterval(() => {
227 const mem = process.memoryUsage();
228 const cpu = process.cpuUsage();
229 const cpuSum = cpu.system - prevCpuUsage.system + (cpu.user - prevCpuUsage.user);
230 const cpuUsage = round((cpuSum / (SYSTEM_HEALTH_INTERVAL * 1000)) * 100, 1) + '%';
231 const headUsage = round(mem.heapUsed / 1024 ** 2, 50) + ' MB';
232 const rss = round(mem.rss / 1024 ** 2, 50) + ' MB';
233 logger_1.logger.info('System health', { headUsage, rss, cpuUsage });
234 prevCpuUsage = cpu;
235}, SYSTEM_HEALTH_INTERVAL).unref();
236// const MIN_AVAILABLE_DISK_SPACE = 1024 ** 3;
237function checkFreeSpace() {
238 // diskusage
239 // .check('/')
240 // .then(res => {
241 // if (res.available < MIN_AVAILABLE_DISK_SPACE) {
242 // const availableSpace = round(res.available / 1024 ** 2, 50) + ' MB';
243 // logger.warn('Low available disk space', { availableSpace });
244 // }
245 // })
246 // .catch(err => logger.error(err));
247 // setTimeout(checkFreeSpace, 600_000).unref();
248}
249checkFreeSpace();
250if (fs_1.existsSync(initFile) && fs_1.readFileSync(initFile, 'utf8') !== 'ok') {
251 setTimeout(() => {
252 logger_1.logger.warn('Last program was killed');
253 });
254}
255fs_1.writeFileSync(initFile, '');
256process.on('unhandledRejection', reason => logger_1.logger.warn('Unhandled Promise rejection', { reason }));
257process.on('uncaughtException', err => logger_1.logger.error('UncaughtException', err));
258process.on('warning', warning => logger_1.logger.warn('Warning', { warning }));
259//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLEdBQUcsRUFBRTtJQUNwRCxNQUFNLElBQUksS0FBSyxDQUFDLDRDQUE0QyxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7QUFFdEYsb0RBQTRCO0FBQ2YsUUFBQSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLElBQUksYUFBYSxDQUFDO0FBQ3pELE1BQU0sUUFBUSxHQUFHLENBQUMsTUFBTSxFQUFFLFlBQVksRUFBRSxPQUFPLEdBQUcsV0FBRyxFQUFFLE9BQU8sR0FBRyxXQUFHLEdBQUcsUUFBUSxDQUFDLENBQUM7QUFDakYsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxnQkFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztBQUVyRixnREFBd0I7QUFDeEIsc0JBQW9CO0FBQ3BCLHNEQUE4QjtBQUM5QixzRUFBMEM7QUFDMUMsc0VBQTBEO0FBQzFELHFDQUF1RDtBQUN2RCwrQkFBK0I7QUFDL0IsMkNBQTBDO0FBQzFDLHFDQUE2QztBQUM3QyxpREFBMEQ7QUFFMUQsd0RBQTBDO0FBQzFDLGdFQUF1QztBQUN2QywyQkFBNkQ7QUFDN0Qsa0RBQTBCO0FBQzFCLGdEQUF3QjtBQUN4QixxQ0FBOEQ7QUFFOUQsc0RBQTZCO0FBQzdCLG1DQUFnQztBQUNoQywwQ0FBMEM7QUFFMUMsMEJBQXFCO0FBQ3JCLG9DQUErQjtBQUMvQiw0Q0FBdUM7QUFDdkMsK0JBQTBCO0FB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
\No newline at end of file