1 | ;
|
2 | function __export(m) {
|
3 | for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
4 | }
|
5 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
6 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
7 | };
|
8 | var __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 | };
|
15 | Object.defineProperty(exports, "__esModule", { value: true });
|
16 | if (+process.versions.node.replace(/\.\d+$/, '') < 12)
|
17 | throw new Error(`Required version of node: >=12, current: ${process.versions.node}`);
|
18 | const dotenv_1 = __importDefault(require("dotenv"));
|
19 | exports.ENV = process.env.NODE_ENV || 'development';
|
20 | const envFiles = ['.env', '.env.local', '.env.' + exports.ENV, '.env.' + exports.ENV + '.local'];
|
21 | envFiles.forEach(path => Object.assign(process.env, dotenv_1.default.config({ path }).parsed));
|
22 | const cors_1 = __importDefault(require("cors"));
|
23 | require("deps-check");
|
24 | const express_1 = __importDefault(require("express"));
|
25 | const express_graphql_1 = __importDefault(require("express-graphql"));
|
26 | const express_session_1 = __importDefault(require("express-session"));
|
27 | const graphql_1 = require("graphql");
|
28 | const path_1 = require("path");
|
29 | const ts2graphql_1 = require("ts2graphql");
|
30 | const dbInit_1 = require("./dbInit");
|
31 | const graphQLUtils_1 = require("./graphQLUtils");
|
32 | const bodyparser = __importStar(require("body-parser"));
|
33 | const serve_static_1 = __importDefault(require("serve-static"));
|
34 | const fs_1 = require("fs");
|
35 | const https_1 = __importDefault(require("https"));
|
36 | const http_1 = __importDefault(require("http"));
|
37 | const logger_1 = require("./logger");
|
38 | const find_up_1 = __importDefault(require("find-up"));
|
39 | const 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"));
|
50 | exports.bodyParser = bodyparser;
|
51 | exports.PRODUCTION = exports.ENV === 'production';
|
52 | let EXITING = false;
|
53 | async 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 | }
|
173 | exports.createGraphqApp = createGraphqApp;
|
174 | const packageJsonFile = find_up_1.default.sync('package.json', { cwd: require.main.filename });
|
175 | if (!packageJsonFile)
|
176 | throw new logger_1.Exception('package.json is not found');
|
177 | const projectDir = path_1.dirname(packageJsonFile);
|
178 | const initFile = projectDir + '/.status';
|
179 | let activeThreadsCount = 0;
|
180 | function 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 | }
|
188 | exports.asyncThread = asyncThread;
|
189 | let 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 | });
|
221 | function round(val, round) {
|
222 | return Math.round(val / round) * round;
|
223 | }
|
224 | let prevCpuUsage = process.cpuUsage();
|
225 | const SYSTEM_HEALTH_INTERVAL = 600000;
|
226 | setInterval(() => {
|
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;
|
237 | function 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 | }
|
249 | checkFreeSpace();
|
250 | if (fs_1.existsSync(initFile) && fs_1.readFileSync(initFile, 'utf8') !== 'ok') {
|
251 | setTimeout(() => {
|
252 | logger_1.logger.warn('Last program was killed');
|
253 | });
|
254 | }
|
255 | fs_1.writeFileSync(initFile, '');
|
256 | process.on('unhandledRejection', reason => logger_1.logger.warn('Unhandled Promise rejection', { reason }));
|
257 | process.on('uncaughtException', err => logger_1.logger.error('UncaughtException', err));
|
258 | process.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 |