1 | #!/usr/bin/env node
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | import "source-map-support/register";
|
11 |
|
12 | import * as appRoot from "app-root-path";
|
13 | import * as _ from "lodash";
|
14 | import * as path from "path";
|
15 | import { printError } from "../lib/util/error";
|
16 |
|
17 | async function main(): Promise<void> {
|
18 | try {
|
19 | const logging = require("../lib/util/logger");
|
20 | logging.configureLogging(logging.ClientLogging);
|
21 |
|
22 | let cfg = await require("../lib/configuration").loadConfiguration();
|
23 | cfg = require("../lib/scan").enableDefaultScanning(cfg);
|
24 | cfg.logging.banner.contributors.push(
|
25 | require("../lib/internal/transport/showStartupMessages").DevModeBannerContributor);
|
26 |
|
27 | const automationClient = require("../lib/automationClient").automationClient(cfg);
|
28 | await automationClient.run();
|
29 | const registration = prepareRegistration(cfg);
|
30 |
|
31 | const chokidar = require("chokidar");
|
32 | const watcher = chokidar.watch(["index.js", "lib/*.js", "lib/**/*.js"], { ignored: "\.ts" });
|
33 |
|
34 | const indexPath = path.join(appRoot.path, "index.js");
|
35 | const libPath = path.join(appRoot.path, "lib");
|
36 | const logger = logging.logger;
|
37 |
|
38 | watcher.on("ready", () => {
|
39 | watcher.on("all", async (e, filePath) => {
|
40 | const start = Date.now();
|
41 | logger.warn("Change to '%s' file detected. Attempting reload...", filePath);
|
42 |
|
43 | Object.keys(require.cache).forEach(id => {
|
44 | if (id.startsWith(indexPath) || id.startsWith(libPath)) {
|
45 | delete require.cache[id];
|
46 | }
|
47 | });
|
48 |
|
49 | try {
|
50 | let newCfg = await require("../lib/configuration").loadConfiguration();
|
51 | newCfg = require("../lib/scan").enableDefaultScanning(newCfg);
|
52 |
|
53 | diffRegistration(prepareRegistration(newCfg), registration);
|
54 |
|
55 |
|
56 | automationClient.automationServer.commandHandlers = [];
|
57 | newCfg.commands.forEach(command => automationClient.withCommandHandler(command));
|
58 | automationClient.automationServer.eventHandlers = [];
|
59 | newCfg.events.forEach(event => automationClient.withEventHandler(event));
|
60 |
|
61 | automationClient.configuration = newCfg;
|
62 |
|
63 |
|
64 | if (automationClient.defaultListeners.length > 2) {
|
65 | automationClient.defaultListeners.splice(2);
|
66 | }
|
67 | await automationClient.raiseStartupEvent();
|
68 |
|
69 | logger.warn(`Reload successful in ${((Date.now() - start) / 1000).toFixed(2)}s`);
|
70 | } catch (e) {
|
71 | logger.error("Reload failed");
|
72 | printError(e);
|
73 | }
|
74 | });
|
75 | });
|
76 |
|
77 | } catch (e) {
|
78 | printError(e);
|
79 | process.exit(5);
|
80 | }
|
81 | }
|
82 |
|
83 | function prepareRegistration(configuration: any): any {
|
84 | const automations = new (require("../lib/server/BuildableAutomationServer").BuildableAutomationServer)(configuration);
|
85 | (configuration.commands || []).forEach(c => automations.registerCommandHandler(c));
|
86 | (configuration.events || []).forEach(e => automations.registerEventHandler(e));
|
87 | (configuration.ingesters || []).forEach(i => automations.registerIngester(i));
|
88 | return require("../lib/internal/transport/websocket/payloads")
|
89 | .prepareRegistration(automations.automations, {}, configuration.metadata);
|
90 | }
|
91 |
|
92 | function diffRegistration(newReg: any, oldReg: any): void {
|
93 | if (!_.isEqual(newReg, oldReg)) {
|
94 | const jsonDiff = require("json-diff");
|
95 | const logging = require("../lib/util/logger");
|
96 | logging.logger.error(
|
97 | `Unable to reload. Incompatible changes to registration metadata detected:
|
98 | ${jsonDiff.diffString(newReg, oldReg).trim()}`);
|
99 | logging.logger.error("Exiting...");
|
100 | process.exit(15);
|
101 | }
|
102 | }
|
103 |
|
104 |
|
105 |
|
106 | main()
|
107 | .catch(e => {
|
108 | console.error(`Unhandled exception: ${e.message}`);
|
109 | process.exit(10);
|
110 | });
|