1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
6 | return new (P || (P = Promise))(function (resolve, reject) {
|
7 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
8 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
9 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
10 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
11 | });
|
12 | };
|
13 | var __generator = (this && this.__generator) || function (thisArg, body) {
|
14 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
15 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
16 | function verb(n) { return function (v) { return step([n, v]); }; }
|
17 | function step(op) {
|
18 | if (f) throw new TypeError("Generator is already executing.");
|
19 | while (_) try {
|
20 | 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;
|
21 | if (y = 0, t) op = [op[0] & 2, t.value];
|
22 | switch (op[0]) {
|
23 | case 0: case 1: t = op; break;
|
24 | case 4: _.label++; return { value: op[1], done: false };
|
25 | case 5: _.label++; y = op[1]; op = [0]; continue;
|
26 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
27 | default:
|
28 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
29 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
30 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
31 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
32 | if (t[2]) _.ops.pop();
|
33 | _.trys.pop(); continue;
|
34 | }
|
35 | op = body.call(thisArg, _);
|
36 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
37 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
38 | }
|
39 | };
|
40 | var __read = (this && this.__read) || function (o, n) {
|
41 | var m = typeof Symbol === "function" && o[Symbol.iterator];
|
42 | if (!m) return o;
|
43 | var i = m.call(o), r, ar = [], e;
|
44 | try {
|
45 | while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
46 | }
|
47 | catch (error) { e = { error: error }; }
|
48 | finally {
|
49 | try {
|
50 | if (r && !r.done && (m = i["return"])) m.call(i);
|
51 | }
|
52 | finally { if (e) throw e.error; }
|
53 | }
|
54 | return ar;
|
55 | };
|
56 | var __spread = (this && this.__spread) || function () {
|
57 | for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
|
58 | return ar;
|
59 | };
|
60 | var __values = (this && this.__values) || function (o) {
|
61 | var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
|
62 | if (m) return m.call(o);
|
63 | return {
|
64 | next: function () {
|
65 | if (o && i >= o.length) o = void 0;
|
66 | return { value: o && o[i++], done: !o };
|
67 | }
|
68 | };
|
69 | };
|
70 | Object.defineProperty(exports, "__esModule", { value: true });
|
71 | var express = require("express");
|
72 | var amqp = require("amqplib");
|
73 | var axios_1 = require("axios");
|
74 | var request = require("request");
|
75 | var utils_1 = require("./utils");
|
76 | exports.asyncHandler = utils_1.asyncHandler;
|
77 | exports.retry = utils_1.retry;
|
78 | exports.sleep = utils_1.sleep;
|
79 | exports.verifyBodyParam = utils_1.verifyBodyParam;
|
80 | exports.verifyQueryParam = utils_1.verifyQueryParam;
|
81 | var morganBody = require('morgan-body');
|
82 | var http = require("http");
|
83 | var bodyParser = require("body-parser");
|
84 | var inProduction = process.env.NODE_ENV === "production";
|
85 | var enableMorgan = !inProduction || process.env.ENABLE_MORGAN === "true";
|
86 |
|
87 |
|
88 |
|
89 | var Log = (function () {
|
90 | function Log() {
|
91 | }
|
92 | |
93 |
|
94 |
|
95 | Log.prototype.warn = function () {
|
96 | var args = [];
|
97 | for (var _i = 0; _i < arguments.length; _i++) {
|
98 | args[_i] = arguments[_i];
|
99 | }
|
100 | console.warn.apply(console, __spread(args));
|
101 | };
|
102 | |
103 |
|
104 |
|
105 | Log.prototype.info = function () {
|
106 | var args = [];
|
107 | for (var _i = 0; _i < arguments.length; _i++) {
|
108 | args[_i] = arguments[_i];
|
109 | }
|
110 | console.log.apply(console, __spread(args));
|
111 | };
|
112 | |
113 |
|
114 |
|
115 | Log.prototype.verbose = function () {
|
116 | var args = [];
|
117 | for (var _i = 0; _i < arguments.length; _i++) {
|
118 | args[_i] = arguments[_i];
|
119 | }
|
120 | console.log.apply(console, __spread(args));
|
121 | };
|
122 | |
123 |
|
124 |
|
125 | Log.prototype.error = function () {
|
126 | var args = [];
|
127 | for (var _i = 0; _i < arguments.length; _i++) {
|
128 | args[_i] = arguments[_i];
|
129 | }
|
130 | console.error.apply(console, __spread(args));
|
131 | };
|
132 | |
133 |
|
134 |
|
135 | Log.prototype.exception = function (err) {
|
136 | var args = [];
|
137 | for (var _i = 1; _i < arguments.length; _i++) {
|
138 | args[_i - 1] = arguments[_i];
|
139 | }
|
140 | console.error("Exception:");
|
141 | console.error(err && err.stack || err);
|
142 | console.error.apply(console, __spread(args));
|
143 | };
|
144 | return Log;
|
145 | }());
|
146 | var defaultConfig = {};
|
147 |
|
148 |
|
149 |
|
150 | var EventHandler = (function () {
|
151 | function EventHandler(eventName, eventHandlerFn) {
|
152 | this.eventName = eventName;
|
153 | this.eventHandlerFn = eventHandlerFn;
|
154 | }
|
155 | return EventHandler;
|
156 | }());
|
157 |
|
158 |
|
159 |
|
160 | var MicroService = (function () {
|
161 | function MicroService(config) {
|
162 | var _this = this;
|
163 |
|
164 |
|
165 |
|
166 |
|
167 | this.registeredEventHandlers = new Set();
|
168 | |
169 |
|
170 |
|
171 |
|
172 | this.log = new Log();
|
173 | |
174 |
|
175 |
|
176 |
|
177 | this.timer = {
|
178 | start: function (timerName) {
|
179 |
|
180 | },
|
181 | stop: function (timerName) {
|
182 |
|
183 | },
|
184 | };
|
185 | |
186 |
|
187 |
|
188 |
|
189 | this.metrics = {
|
190 | discrete: function (name, value) {
|
191 |
|
192 | },
|
193 | continuous: function (name, value) {
|
194 |
|
195 | },
|
196 | };
|
197 | this.config = config || defaultConfig;
|
198 | this.expressApp = express();
|
199 | this.httpServer = new http.Server(this.expressApp);
|
200 | if (!inProduction) {
|
201 | this.expressApp.use(function (req, res, next) {
|
202 | res.header("Access-Control-Allow-Origin", "*");
|
203 | res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
|
204 | next();
|
205 | });
|
206 | }
|
207 | this.expressApp.use(bodyParser.json());
|
208 | if (enableMorgan) {
|
209 | console.log("Enabling Morgan request tracing.");
|
210 | morganBody(this.expressApp, {
|
211 | noColors: true,
|
212 | });
|
213 | }
|
214 | this.expressApp.get("/is-alive", function (req, res) {
|
215 | res.json({ ok: true });
|
216 | });
|
217 | this.rest = {
|
218 | |
219 |
|
220 |
|
221 |
|
222 | get: function (route, requestHandler) {
|
223 | _this.expressApp.get(route, function (req, res) {
|
224 | _this.verbose("Handling GET " + route);
|
225 | requestHandler(req, res)
|
226 | .then(function () {
|
227 | _this.verbose("HTTP GET handler for " + route + " finished.");
|
228 | })
|
229 | .catch(function (err) {
|
230 | console.error("Error from handler: HTTP GET " + route);
|
231 | console.error(err && err.stack || err);
|
232 | res.sendStatus(500);
|
233 | });
|
234 | });
|
235 | },
|
236 | |
237 |
|
238 |
|
239 |
|
240 | post: function (route, requestHandler) {
|
241 | _this.expressApp.post(route, function (req, res) {
|
242 | _this.verbose("Handling POST " + route);
|
243 | requestHandler(req, res)
|
244 | .then(function () {
|
245 | _this.verbose("HTTP POST handler for " + route + " finished.");
|
246 | })
|
247 | .catch(function (err) {
|
248 | console.error("Error from handler: HTTP POST " + route);
|
249 | console.error(err && err.stack || err);
|
250 | res.sendStatus(500);
|
251 | });
|
252 | });
|
253 | },
|
254 | |
255 |
|
256 |
|
257 |
|
258 |
|
259 | static: function (dirPath) {
|
260 | console.log("Serving static files from " + dirPath);
|
261 | _this.expressApp.use(express.static(dirPath));
|
262 | },
|
263 | };
|
264 | this.request = {
|
265 | |
266 |
|
267 |
|
268 |
|
269 |
|
270 |
|
271 |
|
272 | get: function (serviceName, route, body) { return __awaiter(_this, void 0, void 0, function () {
|
273 | var url;
|
274 | return __generator(this, function (_a) {
|
275 | switch (_a.label) {
|
276 | case 0:
|
277 | url = "http://" + serviceName + route;
|
278 | return [4 , axios_1.default.get(url, body)];
|
279 | case 1: return [2 , _a.sent()];
|
280 | }
|
281 | });
|
282 | }); },
|
283 | |
284 |
|
285 |
|
286 |
|
287 |
|
288 |
|
289 |
|
290 | post: function (serviceName, route, body) { return __awaiter(_this, void 0, void 0, function () {
|
291 | var url;
|
292 | return __generator(this, function (_a) {
|
293 | switch (_a.label) {
|
294 | case 0:
|
295 | url = "http://" + serviceName + route;
|
296 | return [4 , axios_1.default.post(url, body)];
|
297 | case 1:
|
298 | _a.sent();
|
299 | return [2 ];
|
300 | }
|
301 | });
|
302 | }); },
|
303 | |
304 |
|
305 |
|
306 |
|
307 |
|
308 |
|
309 |
|
310 |
|
311 |
|
312 | forward: function (serviceName, route, req, res) {
|
313 | var url = "http://" + serviceName + route;
|
314 | req.pipe(request(url)).pipe(res);
|
315 | }
|
316 | };
|
317 | }
|
318 |
|
319 |
|
320 |
|
321 | MicroService.prototype.verbose = function (msg) {
|
322 | if (this.config.verbose) {
|
323 | console.log(msg);
|
324 | }
|
325 | };
|
326 |
|
327 |
|
328 |
|
329 | MicroService.prototype.startHttpServer = function () {
|
330 | return __awaiter(this, void 0, void 0, function () {
|
331 | var _this = this;
|
332 | return __generator(this, function (_a) {
|
333 | return [2 , new Promise(function (resolve, reject) {
|
334 | var host;
|
335 | if (_this.config.host !== undefined) {
|
336 | host = _this.config.host;
|
337 | }
|
338 | else {
|
339 | host = process.env.HOST || '0.0.0.0';
|
340 | }
|
341 | var port;
|
342 | if (_this.config.port !== undefined) {
|
343 | port = _this.config.port;
|
344 | }
|
345 | else {
|
346 | port = (process.env.PORT && parseInt(process.env.PORT)) || 3000;
|
347 | }
|
348 | _this.httpServer.listen(port, host, function (err) {
|
349 | if (err) {
|
350 | reject(err);
|
351 | }
|
352 | else {
|
353 | _this.verbose("Running on http://" + port + ":" + host);
|
354 | resolve();
|
355 | }
|
356 | });
|
357 | })];
|
358 | });
|
359 | });
|
360 | };
|
361 |
|
362 |
|
363 |
|
364 | MicroService.prototype.startMessaging = function () {
|
365 | return __awaiter(this, void 0, void 0, function () {
|
366 | var initMessaging;
|
367 | var _this = this;
|
368 | return __generator(this, function (_a) {
|
369 | switch (_a.label) {
|
370 | case 0:
|
371 | initMessaging = function () { return __awaiter(_this, void 0, void 0, function () {
|
372 | var e_1, _a, messagingHost, _b, _c, _d, _e, eventHandler, e_1_1;
|
373 | var _this = this;
|
374 | return __generator(this, function (_f) {
|
375 | switch (_f.label) {
|
376 | case 0:
|
377 | if (this.config.messagingHost) {
|
378 | messagingHost = this.config.messagingHost;
|
379 | }
|
380 | else {
|
381 | messagingHost = process.env.MESSAGING_HOST || "amqp://guest:guest@localhost:5672";
|
382 | }
|
383 | this.verbose("Connteting to messaging server at: " + messagingHost);
|
384 | _b = this;
|
385 | return [4 , utils_1.retry(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
|
386 | switch (_a.label) {
|
387 | case 0: return [4 , amqp.connect(messagingHost)];
|
388 | case 1: return [2 , _a.sent()];
|
389 | }
|
390 | }); }); }, 10000, 1000)];
|
391 | case 1:
|
392 | _b.messagingConnection = _f.sent();
|
393 | this.messagingConnection.on("error", function (err) {
|
394 | console.error("Error from message system.");
|
395 | console.error(err && err.stack || err);
|
396 | });
|
397 | this.messagingConnection.on("close", function (err) {
|
398 | _this.messagingConnection = undefined;
|
399 | _this.messagingChannel = undefined;
|
400 | console.log("Lost connection to rabbit, waiting for restart.");
|
401 | initMessaging()
|
402 | .then(function () { return console.log("Restarted messaging."); })
|
403 | .catch(function (err) {
|
404 | console.error("Failed to restart messaging.");
|
405 | console.error(err && err.stack || err);
|
406 | });
|
407 | });
|
408 | _c = this;
|
409 | return [4 , this.messagingConnection.createChannel()];
|
410 | case 2:
|
411 | _c.messagingChannel = _f.sent();
|
412 | _f.label = 3;
|
413 | case 3:
|
414 | _f.trys.push([3, 8, 9, 10]);
|
415 | _d = __values(this.registeredEventHandlers.values()), _e = _d.next();
|
416 | _f.label = 4;
|
417 | case 4:
|
418 | if (!!_e.done) return [3 , 7];
|
419 | eventHandler = _e.value;
|
420 | return [4 , this.internalOn(eventHandler)];
|
421 | case 5:
|
422 | _f.sent();
|
423 | _f.label = 6;
|
424 | case 6:
|
425 | _e = _d.next();
|
426 | return [3 , 4];
|
427 | case 7: return [3 , 10];
|
428 | case 8:
|
429 | e_1_1 = _f.sent();
|
430 | e_1 = { error: e_1_1 };
|
431 | return [3 , 10];
|
432 | case 9:
|
433 | try {
|
434 | if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
|
435 | }
|
436 | finally { if (e_1) throw e_1.error; }
|
437 | return [7 ];
|
438 | case 10: return [2 ];
|
439 | }
|
440 | });
|
441 | }); };
|
442 | return [4 , initMessaging()];
|
443 | case 1:
|
444 | _a.sent();
|
445 | return [2 ];
|
446 | }
|
447 | });
|
448 | });
|
449 | };
|
450 | |
451 |
|
452 |
|
453 | MicroService.prototype.isMessagingAvailable = function () {
|
454 | return !!this.messagingConnection;
|
455 | };
|
456 |
|
457 |
|
458 |
|
459 | MicroService.prototype.internalOn = function (eventHandler) {
|
460 | return __awaiter(this, void 0, void 0, function () {
|
461 | var eventName, queueName, messagingChannel, consumeCallback;
|
462 | var _this = this;
|
463 | return __generator(this, function (_a) {
|
464 | switch (_a.label) {
|
465 | case 0:
|
466 | eventName = eventHandler.eventName;
|
467 |
|
468 | return [4 , this.messagingChannel.assertExchange(eventName, "fanout", { durable: true })];
|
469 | case 1:
|
470 |
|
471 | _a.sent();
|
472 | return [4 , this.messagingChannel.assertQueue("", { durable: true, exclusive: true })];
|
473 | case 2:
|
474 | queueName = (_a.sent()).queue;
|
475 | eventHandler.queueName = queueName;
|
476 | console.log('binding queue', queueName, 'to', eventName);
|
477 | this.messagingChannel.bindQueue(queueName, eventName, "");
|
478 | messagingChannel = this.messagingChannel;
|
479 | consumeCallback = function (msg) { return __awaiter(_this, void 0, void 0, function () {
|
480 | var args, eventResponse;
|
481 | return __generator(this, function (_a) {
|
482 | switch (_a.label) {
|
483 | case 0:
|
484 | this.verbose("Handling " + eventName);
|
485 | args = JSON.parse(msg.content.toString());
|
486 | eventResponse = {
|
487 | ack: function () {
|
488 | return __awaiter(this, void 0, void 0, function () {
|
489 | return __generator(this, function (_a) {
|
490 | messagingChannel.ack(msg);
|
491 | return [2 ];
|
492 | });
|
493 | });
|
494 | }
|
495 | };
|
496 | return [4 , eventHandler.eventHandlerFn(args, eventResponse)];
|
497 | case 1:
|
498 | _a.sent();
|
499 | this.verbose(eventName + " handler done.");
|
500 | return [2 ];
|
501 | }
|
502 | });
|
503 | }); };
|
504 | this.verbose("Receiving events on queue " + eventName);
|
505 |
|
506 | this.messagingChannel.consume(queueName, utils_1.asyncHandler(this, "ASYNC: " + eventName, consumeCallback), {
|
507 | noAck: false,
|
508 | });
|
509 | return [2 ];
|
510 | }
|
511 | });
|
512 | });
|
513 | };
|
514 |
|
515 |
|
516 |
|
517 | MicroService.prototype.internalOff = function (eventHandler) {
|
518 | this.messagingChannel.unbindQueue(eventHandler.queueName, eventHandler.eventName, "");
|
519 | delete eventHandler.queueName;
|
520 | };
|
521 | |
522 |
|
523 |
|
524 |
|
525 |
|
526 |
|
527 |
|
528 | MicroService.prototype.on = function (eventName, eventHandlerFn) {
|
529 | return __awaiter(this, void 0, void 0, function () {
|
530 | var eventHandler;
|
531 | return __generator(this, function (_a) {
|
532 | switch (_a.label) {
|
533 | case 0:
|
534 | eventHandler = new EventHandler(eventName, eventHandlerFn);
|
535 | this.registeredEventHandlers.add(eventHandler);
|
536 | if (!this.messagingConnection) return [3 , 2];
|
537 |
|
538 |
|
539 |
|
540 | return [4 , this.internalOn(eventHandler)];
|
541 | case 1:
|
542 |
|
543 |
|
544 |
|
545 | _a.sent();
|
546 | _a.label = 2;
|
547 | case 2: return [2 , eventHandler];
|
548 | }
|
549 | });
|
550 | });
|
551 | };
|
552 | |
553 |
|
554 |
|
555 |
|
556 |
|
557 | MicroService.prototype.off = function (handler) {
|
558 | var eventHandler = handler;
|
559 | if (this.messagingConnection) {
|
560 | this.internalOff(eventHandler);
|
561 | }
|
562 | this.registeredEventHandlers.delete(eventHandler);
|
563 | };
|
564 | |
565 |
|
566 |
|
567 |
|
568 |
|
569 |
|
570 |
|
571 |
|
572 | MicroService.prototype.once = function (eventName, eventHandlerFn) {
|
573 | return __awaiter(this, void 0, void 0, function () {
|
574 | var eventHandler;
|
575 | var _this = this;
|
576 | return __generator(this, function (_a) {
|
577 | switch (_a.label) {
|
578 | case 0: return [4 , this.on(eventName, function (args, res) { return __awaiter(_this, void 0, void 0, function () {
|
579 | return __generator(this, function (_a) {
|
580 | switch (_a.label) {
|
581 | case 0:
|
582 | this.off(eventHandler);
|
583 | return [4 , eventHandlerFn(args, res)];
|
584 | case 1:
|
585 | _a.sent();
|
586 | return [2 ];
|
587 | }
|
588 | });
|
589 | }); })];
|
590 | case 1:
|
591 | eventHandler = _a.sent();
|
592 | return [2 ];
|
593 | }
|
594 | });
|
595 | });
|
596 | };
|
597 | |
598 |
|
599 |
|
600 |
|
601 |
|
602 |
|
603 |
|
604 | MicroService.prototype.waitForOneEvent = function (eventName) {
|
605 | var _this = this;
|
606 | return new Promise(function (resolve) {
|
607 | _this.once(eventName, function (args, res) { return __awaiter(_this, void 0, void 0, function () {
|
608 | return __generator(this, function (_a) {
|
609 | res.ack();
|
610 | resolve(args);
|
611 | return [2 ];
|
612 | });
|
613 | }); });
|
614 | });
|
615 | };
|
616 | |
617 |
|
618 |
|
619 |
|
620 |
|
621 |
|
622 |
|
623 | MicroService.prototype.emit = function (eventName, eventArgs) {
|
624 | return __awaiter(this, void 0, void 0, function () {
|
625 | return __generator(this, function (_a) {
|
626 | switch (_a.label) {
|
627 | case 0:
|
628 | if (!this.messagingConnection) {
|
629 | throw new Error("Messaging system currently unavailable.");
|
630 | }
|
631 |
|
632 | return [4 , this.messagingChannel.assertExchange(eventName, "fanout", { durable: true, })];
|
633 | case 1:
|
634 |
|
635 | _a.sent();
|
636 | console.log('sendMessage:');
|
637 | console.log(" " + eventName);
|
638 | console.log(eventArgs);
|
639 |
|
640 | this.messagingChannel.publish(eventName, '', new Buffer(JSON.stringify(eventArgs)), {
|
641 | persistent: true,
|
642 | });
|
643 | return [2 ];
|
644 | }
|
645 | });
|
646 | });
|
647 | };
|
648 | |
649 |
|
650 |
|
651 |
|
652 | MicroService.prototype.start = function () {
|
653 | return __awaiter(this, void 0, void 0, function () {
|
654 | return __generator(this, function (_a) {
|
655 | switch (_a.label) {
|
656 | case 0: return [4 , this.startHttpServer()];
|
657 | case 1:
|
658 | _a.sent();
|
659 | return [4 , this.startMessaging()];
|
660 | case 2:
|
661 | _a.sent();
|
662 | return [2 ];
|
663 | }
|
664 | });
|
665 | });
|
666 | };
|
667 | return MicroService;
|
668 | }());
|
669 |
|
670 |
|
671 |
|
672 |
|
673 |
|
674 | function micro(config) {
|
675 | return new MicroService(config);
|
676 | }
|
677 | exports.micro = micro;
|
678 |
|
\ | No newline at end of file |