velocious 1.0.291 → 1.0.293

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Development-only file watcher that asks the HTTP server to recycle workers
3
+ * when application source files change.
4
+ */
5
+ export default class VelociousHttpServerDevelopmentReloader {
6
+ /**
7
+ * @param {object} args - Options object.
8
+ * @param {import("../configuration.js").default} args.configuration - Configuration instance.
9
+ * @param {function({changedPath: string}) : Promise<void>} args.onReload - Reload callback.
10
+ * @param {number} [args.debounceMs] - Debounce window for grouped changes.
11
+ * @param {typeof fsWatch} [args.watchFactory] - File watch factory.
12
+ * @param {typeof fs.readdir} [args.readdir] - Directory reader.
13
+ * @param {typeof fs.stat} [args.stat] - Stat reader.
14
+ */
15
+ constructor({ configuration, onReload, debounceMs, watchFactory, readdir, stat }: {
16
+ configuration: import("../configuration.js").default;
17
+ onReload: (arg0: {
18
+ changedPath: string;
19
+ }) => Promise<void>;
20
+ debounceMs?: number | undefined;
21
+ watchFactory?: typeof fsWatch | undefined;
22
+ readdir?: typeof fs.readdir | undefined;
23
+ stat?: typeof fs.stat | undefined;
24
+ });
25
+ configuration: import("../configuration.js").default;
26
+ debounceMs: number;
27
+ logger: Logger;
28
+ onReload: (arg0: {
29
+ changedPath: string;
30
+ }) => Promise<void>;
31
+ readdir: typeof fs.readdir;
32
+ stat: typeof fs.stat;
33
+ watchFactory: typeof fsWatch;
34
+ /** @type {ReturnType<typeof setTimeout> | undefined} */
35
+ reloadTimer: ReturnType<typeof setTimeout> | undefined;
36
+ /** @type {string | undefined} */
37
+ pendingChangedPath: string | undefined;
38
+ /** @type {Map<string, import("fs").FSWatcher>} */
39
+ watchers: Map<string, import("fs").FSWatcher>;
40
+ /** @returns {Promise<void>} - Resolves when watching has started. */
41
+ start(): Promise<void>;
42
+ /** @returns {string[]} - Source directories to watch. */
43
+ watchRootPaths(): string[];
44
+ /**
45
+ * @param {string} directoryPath - Directory path.
46
+ * @returns {Promise<void>} - Resolves when child directories are watched.
47
+ */
48
+ watchDirectoryRecursive(directoryPath: string): Promise<void>;
49
+ /**
50
+ * @param {object} args - Options object.
51
+ * @param {string} args.directoryPath - Watched directory path.
52
+ * @param {string} args.eventType - Watch event type.
53
+ * @param {string | Buffer | null} args.fileName - Relative changed filename.
54
+ * @returns {Promise<void>} - Resolves when complete.
55
+ */
56
+ onWatcherEvent({ directoryPath, eventType, fileName }: {
57
+ directoryPath: string;
58
+ eventType: string;
59
+ fileName: string | Buffer | null;
60
+ }): Promise<void>;
61
+ /**
62
+ * @param {object} args - Options object.
63
+ * @param {string} args.changedPath - Changed path.
64
+ * @param {string | Buffer | null} args.fileName - Raw filename from fs.watch.
65
+ * @returns {boolean} - Whether the path should trigger reload.
66
+ */
67
+ shouldReloadPath({ changedPath, fileName }: {
68
+ changedPath: string;
69
+ fileName: string | Buffer | null;
70
+ }): boolean;
71
+ /**
72
+ * @param {string} changedPath - Candidate directory path.
73
+ * @returns {Promise<void>} - Resolves when any new directory watchers are added.
74
+ */
75
+ watchPotentialDirectory(changedPath: string): Promise<void>;
76
+ /**
77
+ * @param {string} changedPath - Changed path.
78
+ * @returns {void} - No return value.
79
+ */
80
+ scheduleReload(changedPath: string): void;
81
+ /** @returns {Promise<void>} - Resolves when the queued reload is handled. */
82
+ flushReload(): Promise<void>;
83
+ /**
84
+ * @param {Error} error - Watcher error.
85
+ * @returns {void} - No return value.
86
+ */
87
+ onWatcherError: (error: Error) => void;
88
+ /** @returns {Promise<void>} - Resolves when watchers are closed. */
89
+ stop(): Promise<void>;
90
+ }
91
+ import Logger from "../logger.js";
92
+ import fs from "fs/promises";
93
+ import { watch as fsWatch } from "fs";
94
+ //# sourceMappingURL=development-reloader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"development-reloader.d.ts","sourceRoot":"","sources":["../../../src/http-server/development-reloader.js"],"names":[],"mappings":"AAeA;;;GAGG;AACH;IACE;;;;;;;;OAQG;IACH,kFAPG;QAAoD,aAAa,EAAzD,OAAO,qBAAqB,EAAE,OAAO;QACiB,QAAQ,EAA9D,CAAS,IAAqB,EAArB;YAAC,WAAW,EAAE,MAAM,CAAA;SAAC,KAAI,OAAO,CAAC,IAAI,CAAC;QACjC,UAAU;QACF,YAAY;QACT,OAAO;QACV,IAAI;KACpC,EAkBA;IAhBC,qDAAkC;IAClC,mBAA4B;IAC5B,eAAgE;IAChE,iBAVkB;QAAC,WAAW,EAAE,MAAM,CAAA;KAAC,KAAI,OAAO,CAAC,IAAI,CAAC,CAUhC;IACxB,2BAAsB;IACtB,qBAAgB;IAChB,6BAAgC;IAEhC,wDAAwD;IACxD,aADW,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,SAAS,CACxB;IAE5B,iCAAiC;IACjC,oBADW,MAAM,GAAG,SAAS,CACM;IAEnC,kDAAkD;IAClD,UADW,GAAG,CAAC,MAAM,EAAE,OAAO,IAAI,EAAE,SAAS,CAAC,CACrB;IAG3B,qEAAqE;IACrE,SADc,OAAO,CAAC,IAAI,CAAC,CAK1B;IAED,yDAAyD;IACzD,kBADc,MAAM,EAAE,CAarB;IAED;;;OAGG;IACH,uCAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAgCzB;IAED;;;;;;OAMG;IACH,uDALG;QAAqB,aAAa,EAA1B,MAAM;QACO,SAAS,EAAtB,MAAM;QACuB,QAAQ,EAArC,MAAM,GAAG,MAAM,GAAG,IAAI;KAC9B,GAAU,OAAO,CAAC,IAAI,CAAC,CAczB;IAED;;;;;OAKG;IACH,4CAJG;QAAqB,WAAW,EAAxB,MAAM;QACuB,QAAQ,EAArC,MAAM,GAAG,MAAM,GAAG,IAAI;KAC9B,GAAU,OAAO,CAQnB;IAED;;;OAGG;IACH,qCAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAczB;IAED;;;OAGG;IACH,4BAHW,MAAM,GACJ,IAAI,CAYhB;IAED,6EAA6E;IAC7E,eADc,OAAO,CAAC,IAAI,CAAC,CAU1B;IAED;;;OAGG;IACH,iBAAkB,OAHP,KAGY,KAFV,IAAI,CAIhB;IAED,oEAAoE;IACpE,QADc,OAAO,CAAC,IAAI,CAAC,CAc1B;CACF;mBA9MkB,cAAc;eADlB,aAAa;iCADG,IAAI"}
@@ -0,0 +1,180 @@
1
+ // @ts-check
2
+ import { watch as fsWatch } from "fs";
3
+ import fs from "fs/promises";
4
+ import Logger from "../logger.js";
5
+ import path from "path";
6
+ const RELOADABLE_EXTENSIONS = new Set([
7
+ ".cjs",
8
+ ".ejs",
9
+ ".js",
10
+ ".json",
11
+ ".mjs"
12
+ ]);
13
+ /**
14
+ * Development-only file watcher that asks the HTTP server to recycle workers
15
+ * when application source files change.
16
+ */
17
+ export default class VelociousHttpServerDevelopmentReloader {
18
+ /**
19
+ * @param {object} args - Options object.
20
+ * @param {import("../configuration.js").default} args.configuration - Configuration instance.
21
+ * @param {function({changedPath: string}) : Promise<void>} args.onReload - Reload callback.
22
+ * @param {number} [args.debounceMs] - Debounce window for grouped changes.
23
+ * @param {typeof fsWatch} [args.watchFactory] - File watch factory.
24
+ * @param {typeof fs.readdir} [args.readdir] - Directory reader.
25
+ * @param {typeof fs.stat} [args.stat] - Stat reader.
26
+ */
27
+ constructor({ configuration, onReload, debounceMs = 75, watchFactory = fsWatch, readdir = fs.readdir, stat = fs.stat }) {
28
+ this.configuration = configuration;
29
+ this.debounceMs = debounceMs;
30
+ this.logger = new Logger("DevelopmentReloader", { configuration });
31
+ this.onReload = onReload;
32
+ this.readdir = readdir;
33
+ this.stat = stat;
34
+ this.watchFactory = watchFactory;
35
+ /** @type {ReturnType<typeof setTimeout> | undefined} */
36
+ this.reloadTimer = undefined;
37
+ /** @type {string | undefined} */
38
+ this.pendingChangedPath = undefined;
39
+ /** @type {Map<string, import("fs").FSWatcher>} */
40
+ this.watchers = new Map();
41
+ }
42
+ /** @returns {Promise<void>} - Resolves when watching has started. */
43
+ async start() {
44
+ for (const rootPath of this.watchRootPaths()) {
45
+ await this.watchDirectoryRecursive(rootPath);
46
+ }
47
+ }
48
+ /** @returns {string[]} - Source directories to watch. */
49
+ watchRootPaths() {
50
+ const rootPaths = new Set();
51
+ const configurationDirectory = this.configuration.getDirectory();
52
+ rootPaths.add(path.join(configurationDirectory, "src"));
53
+ for (const backendProject of this.configuration.getBackendProjects()) {
54
+ if (!backendProject?.path)
55
+ continue;
56
+ rootPaths.add(path.join(backendProject.path, "src"));
57
+ }
58
+ return Array.from(rootPaths);
59
+ }
60
+ /**
61
+ * @param {string} directoryPath - Directory path.
62
+ * @returns {Promise<void>} - Resolves when child directories are watched.
63
+ */
64
+ async watchDirectoryRecursive(directoryPath) {
65
+ const resolvedDirectoryPath = path.resolve(directoryPath);
66
+ if (this.watchers.has(resolvedDirectoryPath))
67
+ return;
68
+ let entries;
69
+ try {
70
+ entries = await this.readdir(resolvedDirectoryPath, { withFileTypes: true });
71
+ }
72
+ catch (error) {
73
+ if ( /** @type {{code?: string}} */(error)?.code === "ENOENT")
74
+ return;
75
+ throw error;
76
+ }
77
+ const watcher = this.watchFactory(resolvedDirectoryPath, (eventType, fileName) => {
78
+ void this.onWatcherEvent({
79
+ directoryPath: resolvedDirectoryPath,
80
+ eventType,
81
+ fileName
82
+ });
83
+ });
84
+ watcher.on("error", this.onWatcherError);
85
+ this.watchers.set(resolvedDirectoryPath, watcher);
86
+ for (const entry of entries) {
87
+ if (!entry.isDirectory())
88
+ continue;
89
+ await this.watchDirectoryRecursive(path.join(resolvedDirectoryPath, entry.name));
90
+ }
91
+ }
92
+ /**
93
+ * @param {object} args - Options object.
94
+ * @param {string} args.directoryPath - Watched directory path.
95
+ * @param {string} args.eventType - Watch event type.
96
+ * @param {string | Buffer | null} args.fileName - Relative changed filename.
97
+ * @returns {Promise<void>} - Resolves when complete.
98
+ */
99
+ async onWatcherEvent({ directoryPath, eventType, fileName }) {
100
+ const changedPath = fileName
101
+ ? path.join(directoryPath, fileName.toString())
102
+ : directoryPath;
103
+ await this.watchPotentialDirectory(changedPath);
104
+ if (!this.shouldReloadPath({ changedPath, fileName }))
105
+ return;
106
+ this.scheduleReload(changedPath);
107
+ await this.logger.debug(() => ["Queued development hot reload", { changedPath, eventType }]);
108
+ }
109
+ /**
110
+ * @param {object} args - Options object.
111
+ * @param {string} args.changedPath - Changed path.
112
+ * @param {string | Buffer | null} args.fileName - Raw filename from fs.watch.
113
+ * @returns {boolean} - Whether the path should trigger reload.
114
+ */
115
+ shouldReloadPath({ changedPath, fileName }) {
116
+ if (!fileName)
117
+ return true;
118
+ const extension = path.extname(changedPath).toLowerCase();
119
+ return RELOADABLE_EXTENSIONS.has(extension);
120
+ }
121
+ /**
122
+ * @param {string} changedPath - Candidate directory path.
123
+ * @returns {Promise<void>} - Resolves when any new directory watchers are added.
124
+ */
125
+ async watchPotentialDirectory(changedPath) {
126
+ try {
127
+ const stat = await this.stat(changedPath);
128
+ if (stat.isDirectory()) {
129
+ await this.watchDirectoryRecursive(changedPath);
130
+ }
131
+ }
132
+ catch (error) {
133
+ if ( /** @type {{code?: string}} */(error)?.code !== "ENOENT") {
134
+ throw error;
135
+ }
136
+ }
137
+ }
138
+ /**
139
+ * @param {string} changedPath - Changed path.
140
+ * @returns {void} - No return value.
141
+ */
142
+ scheduleReload(changedPath) {
143
+ this.pendingChangedPath = changedPath;
144
+ if (this.reloadTimer) {
145
+ clearTimeout(this.reloadTimer);
146
+ }
147
+ this.reloadTimer = setTimeout(() => {
148
+ void this.flushReload();
149
+ }, this.debounceMs);
150
+ }
151
+ /** @returns {Promise<void>} - Resolves when the queued reload is handled. */
152
+ async flushReload() {
153
+ this.reloadTimer = undefined;
154
+ const changedPath = this.pendingChangedPath;
155
+ if (!changedPath)
156
+ return;
157
+ this.pendingChangedPath = undefined;
158
+ await this.onReload({ changedPath });
159
+ }
160
+ /**
161
+ * @param {Error} error - Watcher error.
162
+ * @returns {void} - No return value.
163
+ */
164
+ onWatcherError = (error) => {
165
+ void this.logger.warn("Development hot reload watcher error", error);
166
+ };
167
+ /** @returns {Promise<void>} - Resolves when watchers are closed. */
168
+ async stop() {
169
+ if (this.reloadTimer) {
170
+ clearTimeout(this.reloadTimer);
171
+ this.reloadTimer = undefined;
172
+ }
173
+ this.pendingChangedPath = undefined;
174
+ for (const watcher of this.watchers.values()) {
175
+ watcher.close();
176
+ }
177
+ this.watchers.clear();
178
+ }
179
+ }
180
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV2ZWxvcG1lbnQtcmVsb2FkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaHR0cC1zZXJ2ZXIvZGV2ZWxvcG1lbnQtcmVsb2FkZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sRUFBQyxLQUFLLElBQUksT0FBTyxFQUFDLE1BQU0sSUFBSSxDQUFBO0FBQ25DLE9BQU8sRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUM1QixPQUFPLE1BQU0sTUFBTSxjQUFjLENBQUE7QUFDakMsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBRXZCLE1BQU0scUJBQXFCLEdBQUcsSUFBSSxHQUFHLENBQUM7SUFDcEMsTUFBTTtJQUNOLE1BQU07SUFDTixLQUFLO0lBQ0wsT0FBTztJQUNQLE1BQU07Q0FDUCxDQUFDLENBQUE7QUFFRjs7O0dBR0c7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFPLHNDQUFzQztJQUN6RDs7Ozs7Ozs7T0FRRztJQUNILFlBQVksRUFBQyxhQUFhLEVBQUUsUUFBUSxFQUFFLFVBQVUsR0FBRyxFQUFFLEVBQUUsWUFBWSxHQUFHLE9BQU8sRUFBRSxPQUFPLEdBQUcsRUFBRSxDQUFDLE9BQU8sRUFBRSxJQUFJLEdBQUcsRUFBRSxDQUFDLElBQUksRUFBQztRQUNsSCxJQUFJLENBQUMsYUFBYSxHQUFHLGFBQWEsQ0FBQTtRQUNsQyxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQTtRQUM1QixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLHFCQUFxQixFQUFFLEVBQUMsYUFBYSxFQUFDLENBQUMsQ0FBQTtRQUNoRSxJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQTtRQUN4QixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQTtRQUN0QixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQTtRQUNoQixJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQTtRQUVo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Q0FBQyxXQUFXLEdBQUcsU0FBUyxDQUFBO1FBQzlCLENBQUM7UUFFRCxJQUFJLENBQUMsa0JBQWtCLEdBQUcsU0FBUyxDQUFBO1FBRW5DLEtBQUssTUFBTSxPQUFPLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO1lBQzdDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUNqQixDQUFDO1FBRUQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtJQUN2QixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHt3YXRjaCBhcyBmc1dhdGNofSBmcm9tIFwiZnNcIlxuaW1wb3J0IGZzIGZyb20gXCJmcy9wcm9taXNlc1wiXG5pbXBvcnQgTG9nZ2VyIGZyb20gXCIuLi9sb2dnZXIuanNcIlxuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIlxuXG5jb25zdCBSRUxPQURBQkxFX0VYVEVOU0lPTlMgPSBuZXcgU2V0KFtcbiAgXCIuY2pzXCIsXG4gIFwiLmVqc1wiLFxuICBcIi5qc1wiLFxuICBcIi5qc29uXCIsXG4gIFwiLm1qc1wiXG5dKVxuXG4vKipcbiAqIERldmVsb3BtZW50LW9ubHkgZmlsZSB3YXRjaGVyIHRoYXQgYXNrcyB0aGUgSFRUUCBzZXJ2ZXIgdG8gcmVjeWNsZSB3b3JrZXJzXG4gKiB3aGVuIGFwcGxpY2F0aW9uIHNvdXJjZSBmaWxlcyBjaGFuZ2UuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFZlbG9jaW91c0h0dHBTZXJ2ZXJEZXZlbG9wbWVudFJlbG9hZGVyIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucyBvYmplY3QuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0fSBhcmdzLmNvbmZpZ3VyYXRpb24gLSBDb25maWd1cmF0aW9uIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uKHtjaGFuZ2VkUGF0aDogc3RyaW5nfSkgOiBQcm9taXNlPHZvaWQ+fSBhcmdzLm9uUmVsb2FkIC0gUmVsb2FkIGNhbGxiYWNrLlxuICAgKiBAcGFyYW0ge251bWJlcn0gW2FyZ3MuZGVib3VuY2VNc10gLSBEZWJvdW5jZSB3aW5kb3cgZm9yIGdyb3VwZWQgY2hhbmdlcy5cbiAgICogQHBhcmFtIHt0eXBlb2YgZnNXYXRjaH0gW2FyZ3Mud2F0Y2hGYWN0b3J5XSAtIEZpbGUgd2F0Y2ggZmFjdG9yeS5cbiAgICogQHBhcmFtIHt0eXBlb2YgZnMucmVhZGRpcn0gW2FyZ3MucmVhZGRpcl0gLSBEaXJlY3RvcnkgcmVhZGVyLlxuICAgKiBAcGFyYW0ge3R5cGVvZiBmcy5zdGF0fSBbYXJncy5zdGF0XSAtIFN0YXQgcmVhZGVyLlxuICAgKi9cbiAgY29uc3RydWN0b3Ioe2NvbmZpZ3VyYXRpb24sIG9uUmVsb2FkLCBkZWJvdW5jZU1zID0gNzUsIHdhdGNoRmFjdG9yeSA9IGZzV2F0Y2gsIHJlYWRkaXIgPSBmcy5yZWFkZGlyLCBzdGF0ID0gZnMuc3RhdH0pIHtcbiAgICB0aGlzLmNvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uXG4gICAgdGhpcy5kZWJvdW5jZU1zID0gZGVib3VuY2VNc1xuICAgIHRoaXMubG9nZ2VyID0gbmV3IExvZ2dlcihcIkRldmVsb3BtZW50UmVsb2FkZXJcIiwge2NvbmZpZ3VyYXRpb259KVxuICAgIHRoaXMub25SZWxvYWQgPSBvblJlbG9hZFxuICAgIHRoaXMucmVhZGRpciA9IHJlYWRkaXJcbiAgICB0aGlzLnN0YXQgPSBzdGF0XG4gICAgdGhpcy53YXRjaEZhY3RvcnkgPSB3YXRjaEZhY3RvcnlcblxuICAgIC8qKiBAdHlwZSB7UmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCB1bmRlZmluZWR9ICovXG4gICAgdGhpcy5yZWxvYWRUaW1lciA9IHVuZGVmaW5lZFxuXG4gICAgLyoqIEB0eXBlIHtzdHJpbmcgfCB1bmRlZmluZWR9ICovXG4gICAgdGhpcy5wZW5kaW5nQ2hhbmdlZFBhdGggPSB1bmRlZmluZWRcblxuICAgIC8qKiBAdHlwZSB7TWFwPHN0cmluZywgaW1wb3J0KFwiZnNcIikuRlNXYXRjaGVyPn0gKi9cbiAgICB0aGlzLndhdGNoZXJzID0gbmV3IE1hcCgpXG4gIH1cblxuICAvKiogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiB3YXRjaGluZyBoYXMgc3RhcnRlZC4gKi9cbiAgYXN5bmMgc3RhcnQoKSB7XG4gICAgZm9yIChjb25zdCByb290UGF0aCBvZiB0aGlzLndhdGNoUm9vdFBhdGhzKCkpIHtcbiAgICAgIGF3YWl0IHRoaXMud2F0Y2hEaXJlY3RvcnlSZWN1cnNpdmUocm9vdFBhdGgpXG4gICAgfVxuICB9XG5cbiAgLyoqIEByZXR1cm5zIHtzdHJpbmdbXX0gLSBTb3VyY2UgZGlyZWN0b3JpZXMgdG8gd2F0Y2guICovXG4gIHdhdGNoUm9vdFBhdGhzKCkge1xuICAgIGNvbnN0IHJvb3RQYXRocyA9IG5ldyBTZXQoKVxuICAgIGNvbnN0IGNvbmZpZ3VyYXRpb25EaXJlY3RvcnkgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0RGlyZWN0b3J5KClcblxuICAgIHJvb3RQYXRocy5hZGQocGF0aC5qb2luKGNvbmZpZ3VyYXRpb25EaXJlY3RvcnksIFwic3JjXCIpKVxuXG4gICAgZm9yIChjb25zdCBiYWNrZW5kUHJvamVjdCBvZiB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0QmFja2VuZFByb2plY3RzKCkpIHtcbiAgICAgIGlmICghYmFja2VuZFByb2plY3Q/LnBhdGgpIGNvbnRpbnVlXG4gICAgICByb290UGF0aHMuYWRkKHBhdGguam9pbihiYWNrZW5kUHJvamVjdC5wYXRoLCBcInNyY1wiKSlcbiAgICB9XG5cbiAgICByZXR1cm4gQXJyYXkuZnJvbShyb290UGF0aHMpXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IGRpcmVjdG9yeVBhdGggLSBEaXJlY3RvcnkgcGF0aC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjaGlsZCBkaXJlY3RvcmllcyBhcmUgd2F0Y2hlZC5cbiAgICovXG4gIGFzeW5jIHdhdGNoRGlyZWN0b3J5UmVjdXJzaXZlKGRpcmVjdG9yeVBhdGgpIHtcbiAgICBjb25zdCByZXNvbHZlZERpcmVjdG9yeVBhdGggPSBwYXRoLnJlc29sdmUoZGlyZWN0b3J5UGF0aClcblxuICAgIGlmICh0aGlzLndhdGNoZXJzLmhhcyhyZXNvbHZlZERpcmVjdG9yeVBhdGgpKSByZXR1cm5cblxuICAgIGxldCBlbnRyaWVzXG5cbiAgICB0cnkge1xuICAgICAgZW50cmllcyA9IGF3YWl0IHRoaXMucmVhZGRpcihyZXNvbHZlZERpcmVjdG9yeVBhdGgsIHt3aXRoRmlsZVR5cGVzOiB0cnVlfSlcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKC8qKiBAdHlwZSB7e2NvZGU/OiBzdHJpbmd9fSAqLyAoZXJyb3IpPy5jb2RlID09PSBcIkVOT0VOVFwiKSByZXR1cm5cbiAgICAgIHRocm93IGVycm9yXG4gICAgfVxuXG4gICAgY29uc3Qgd2F0Y2hlciA9IHRoaXMud2F0Y2hGYWN0b3J5KHJlc29sdmVkRGlyZWN0b3J5UGF0aCwgKGV2ZW50VHlwZSwgZmlsZU5hbWUpID0+IHtcbiAgICAgIHZvaWQgdGhpcy5vbldhdGNoZXJFdmVudCh7XG4gICAgICAgIGRpcmVjdG9yeVBhdGg6IHJlc29sdmVkRGlyZWN0b3J5UGF0aCxcbiAgICAgICAgZXZlbnRUeXBlLFxuICAgICAgICBmaWxlTmFtZVxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgd2F0Y2hlci5vbihcImVycm9yXCIsIHRoaXMub25XYXRjaGVyRXJyb3IpXG4gICAgdGhpcy53YXRjaGVycy5zZXQocmVzb2x2ZWREaXJlY3RvcnlQYXRoLCB3YXRjaGVyKVxuXG4gICAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgICBpZiAoIWVudHJ5LmlzRGlyZWN0b3J5KCkpIGNvbnRpbnVlXG5cbiAgICAgIGF3YWl0IHRoaXMud2F0Y2hEaXJlY3RvcnlSZWN1cnNpdmUocGF0aC5qb2luKHJlc29sdmVkRGlyZWN0b3J5UGF0aCwgZW50cnkubmFtZSkpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucyBvYmplY3QuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLmRpcmVjdG9yeVBhdGggLSBXYXRjaGVkIGRpcmVjdG9yeSBwYXRoLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXJncy5ldmVudFR5cGUgLSBXYXRjaCBldmVudCB0eXBlLlxuICAgKiBAcGFyYW0ge3N0cmluZyB8IEJ1ZmZlciB8IG51bGx9IGFyZ3MuZmlsZU5hbWUgLSBSZWxhdGl2ZSBjaGFuZ2VkIGZpbGVuYW1lLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbXBsZXRlLlxuICAgKi9cbiAgYXN5bmMgb25XYXRjaGVyRXZlbnQoe2RpcmVjdG9yeVBhdGgsIGV2ZW50VHlwZSwgZmlsZU5hbWV9KSB7XG4gICAgY29uc3QgY2hhbmdlZFBhdGggPSBmaWxlTmFtZVxuICAgICAgPyBwYXRoLmpvaW4oZGlyZWN0b3J5UGF0aCwgZmlsZU5hbWUudG9TdHJpbmcoKSlcbiAgICAgIDogZGlyZWN0b3J5UGF0aFxuXG4gICAgYXdhaXQgdGhpcy53YXRjaFBvdGVudGlhbERpcmVjdG9yeShjaGFuZ2VkUGF0aClcblxuICAgIGlmICghdGhpcy5zaG91bGRSZWxvYWRQYXRoKHtjaGFuZ2VkUGF0aCwgZmlsZU5hbWV9KSkgcmV0dXJuXG5cbiAgICB0aGlzLnNjaGVkdWxlUmVsb2FkKGNoYW5nZWRQYXRoKVxuXG4gICAgYXdhaXQgdGhpcy5sb2dnZXIuZGVidWcoKCkgPT4gW1wiUXVldWVkIGRldmVsb3BtZW50IGhvdCByZWxvYWRcIiwge2NoYW5nZWRQYXRoLCBldmVudFR5cGV9XSlcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMgb2JqZWN0LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXJncy5jaGFuZ2VkUGF0aCAtIENoYW5nZWQgcGF0aC5cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBCdWZmZXIgfCBudWxsfSBhcmdzLmZpbGVOYW1lIC0gUmF3IGZpbGVuYW1lIGZyb20gZnMud2F0Y2guXG4gICAqIEByZXR1cm5zIHtib29sZWFufSAtIFdoZXRoZXIgdGhlIHBhdGggc2hvdWxkIHRyaWdnZXIgcmVsb2FkLlxuICAgKi9cbiAgc2hvdWxkUmVsb2FkUGF0aCh7Y2hhbmdlZFBhdGgsIGZpbGVOYW1lfSkge1xuICAgIGlmICghZmlsZU5hbWUpIHJldHVybiB0cnVlXG5cbiAgICBjb25zdCBleHRlbnNpb24gPSBwYXRoLmV4dG5hbWUoY2hhbmdlZFBhdGgpLnRvTG93ZXJDYXNlKClcblxuICAgIHJldHVybiBSRUxPQURBQkxFX0VYVEVOU0lPTlMuaGFzKGV4dGVuc2lvbilcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gY2hhbmdlZFBhdGggLSBDYW5kaWRhdGUgZGlyZWN0b3J5IHBhdGguXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gYW55IG5ldyBkaXJlY3Rvcnkgd2F0Y2hlcnMgYXJlIGFkZGVkLlxuICAgKi9cbiAgYXN5bmMgd2F0Y2hQb3RlbnRpYWxEaXJlY3RvcnkoY2hhbmdlZFBhdGgpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3Qgc3RhdCA9IGF3YWl0IHRoaXMuc3RhdChjaGFuZ2VkUGF0aClcblxuICAgICAgaWYgKHN0YXQuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICBhd2FpdCB0aGlzLndhdGNoRGlyZWN0b3J5UmVjdXJzaXZlKGNoYW5nZWRQYXRoKVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoLyoqIEB0eXBlIHt7Y29kZT86IHN0cmluZ319ICovIChlcnJvcik/LmNvZGUgIT09IFwiRU5PRU5UXCIpIHtcbiAgICAgICAgdGhyb3cgZXJyb3JcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNoYW5nZWRQYXRoIC0gQ2hhbmdlZCBwYXRoLlxuICAgKiBAcmV0dXJucyB7dm9pZH0gLSBObyByZXR1cm4gdmFsdWUuXG4gICAqL1xuICBzY2hlZHVsZVJlbG9hZChjaGFuZ2VkUGF0aCkge1xuICAgIHRoaXMucGVuZGluZ0NoYW5nZWRQYXRoID0gY2hhbmdlZFBhdGhcblxuICAgIGlmICh0aGlzLnJlbG9hZFRpbWVyKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGhpcy5yZWxvYWRUaW1lcilcbiAgICB9XG5cbiAgICB0aGlzLnJlbG9hZFRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB2b2lkIHRoaXMuZmx1c2hSZWxvYWQoKVxuICAgIH0sIHRoaXMuZGVib3VuY2VNcylcbiAgfVxuXG4gIC8qKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIHRoZSBxdWV1ZWQgcmVsb2FkIGlzIGhhbmRsZWQuICovXG4gIGFzeW5jIGZsdXNoUmVsb2FkKCkge1xuICAgIHRoaXMucmVsb2FkVGltZXIgPSB1bmRlZmluZWRcblxuICAgIGNvbnN0IGNoYW5nZWRQYXRoID0gdGhpcy5wZW5kaW5nQ2hhbmdlZFBhdGhcblxuICAgIGlmICghY2hhbmdlZFBhdGgpIHJldHVyblxuXG4gICAgdGhpcy5wZW5kaW5nQ2hhbmdlZFBhdGggPSB1bmRlZmluZWRcbiAgICBhd2FpdCB0aGlzLm9uUmVsb2FkKHtjaGFuZ2VkUGF0aH0pXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtFcnJvcn0gZXJyb3IgLSBXYXRjaGVyIGVycm9yLlxuICAgKiBAcmV0dXJucyB7dm9pZH0gLSBObyByZXR1cm4gdmFsdWUuXG4gICAqL1xuICBvbldhdGNoZXJFcnJvciA9IChlcnJvcikgPT4ge1xuICAgIHZvaWQgdGhpcy5sb2dnZXIud2FybihcIkRldmVsb3BtZW50IGhvdCByZWxvYWQgd2F0Y2hlciBlcnJvclwiLCBlcnJvcilcbiAgfVxuXG4gIC8qKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIHdhdGNoZXJzIGFyZSBjbG9zZWQuICovXG4gIGFzeW5jIHN0b3AoKSB7XG4gICAgaWYgKHRoaXMucmVsb2FkVGltZXIpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLnJlbG9hZFRpbWVyKVxuICAgICAgdGhpcy5yZWxvYWRUaW1lciA9IHVuZGVmaW5lZFxuICAgIH1cblxuICAgIHRoaXMucGVuZGluZ0NoYW5nZWRQYXRoID0gdW5kZWZpbmVkXG5cbiAgICBmb3IgKGNvbnN0IHdhdGNoZXIgb2YgdGhpcy53YXRjaGVycy52YWx1ZXMoKSkge1xuICAgICAgd2F0Y2hlci5jbG9zZSgpXG4gICAgfVxuXG4gICAgdGhpcy53YXRjaGVycy5jbGVhcigpXG4gIH1cbn1cbiJdfQ==
@@ -6,13 +6,23 @@ export default class VelociousHttpServer {
6
6
  * @param {boolean} [args.inProcess] - Run HTTP handlers in the main thread instead of worker threads.
7
7
  * @param {number} [args.port] - Port.
8
8
  * @param {number} [args.maxWorkers] - Max workers.
9
+ * @param {function({configuration: import("../configuration.js").default, onReload: function({changedPath: string}) : Promise<void>}) : {start: () => Promise<void>, stop: () => Promise<void>}} [args.developmentReloaderFactory] - Development reloader factory.
9
10
  */
10
- constructor({ configuration, host, inProcess, maxWorkers, port }: {
11
+ constructor({ configuration, developmentReloaderFactory, host, inProcess, maxWorkers, port }: {
11
12
  configuration: import("../configuration.js").default;
12
13
  host?: string | undefined;
13
14
  inProcess?: boolean | undefined;
14
15
  port?: number | undefined;
15
16
  maxWorkers?: number | undefined;
17
+ developmentReloaderFactory?: ((arg0: {
18
+ configuration: import("../configuration.js").default;
19
+ onReload: (arg0: {
20
+ changedPath: string;
21
+ }) => Promise<void>;
22
+ }) => {
23
+ start: () => Promise<void>;
24
+ stop: () => Promise<void>;
25
+ }) | undefined;
16
26
  });
17
27
  clientCount: number;
18
28
  /** @type {Record<string, ServerClient>} */
@@ -22,6 +32,15 @@ export default class VelociousHttpServer {
22
32
  /** @type {Array<WorkerHandler | InProcessHandler>} */
23
33
  workerHandlers: Array<WorkerHandler | InProcessHandler>;
24
34
  configuration: import("../configuration.js").default;
35
+ developmentReloaderFactory: ((arg0: {
36
+ configuration: import("../configuration.js").default;
37
+ onReload: (arg0: {
38
+ changedPath: string;
39
+ }) => Promise<void>;
40
+ }) => {
41
+ start: () => Promise<void>;
42
+ stop: () => Promise<void>;
43
+ }) | undefined;
25
44
  inProcess: boolean;
26
45
  logger: Logger;
27
46
  host: string;
@@ -42,6 +61,11 @@ export default class VelociousHttpServer {
42
61
  stopServer(): Promise<void>;
43
62
  /** @returns {Promise<void>} - Resolves when complete. */
44
63
  stop(): Promise<void>;
64
+ _stopping: boolean | undefined;
65
+ developmentReloader: {
66
+ start: () => Promise<void>;
67
+ stop: () => Promise<void>;
68
+ } | undefined;
45
69
  /** @returns {void} - No return value. */
46
70
  onClose: () => void;
47
71
  /**
@@ -61,8 +85,18 @@ export default class VelociousHttpServer {
61
85
  onClientClose: (client: ServerClient) => void;
62
86
  /** @returns {Promise<void>} - Resolves when complete. */
63
87
  spawnWorker(): Promise<void>;
88
+ /** @returns {Promise<WorkerHandler | InProcessHandler>} - Started worker handler. */
89
+ _buildWorkerHandler(): Promise<WorkerHandler | InProcessHandler>;
64
90
  /** @returns {WorkerHandler | InProcessHandler} - The worker handler to use. */
65
91
  workerHandlerToUse(): WorkerHandler | InProcessHandler;
92
+ /** @returns {boolean} - Whether development worker hot reload should run. */
93
+ shouldUseDevelopmentHotReload(): boolean;
94
+ /** @returns {Promise<void>} - Resolves when watcher setup finishes. */
95
+ _startDevelopmentReloader(): Promise<void>;
96
+ /** @returns {Promise<void>} - Resolves when workers have been refreshed. */
97
+ reloadWorkersForDevelopment(): Promise<void>;
98
+ _reloadWorkersForDevelopmentQueued: boolean | undefined;
99
+ _reloadingWorkersForDevelopment: boolean | undefined;
66
100
  }
67
101
  import ServerClient from "./server-client.js";
68
102
  import WorkerHandler from "./worker-handler/index.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/http-server/index.js"],"names":[],"mappings":"AAUA;IAYE;;;;;;;OAOG;IACH,kEANG;QAAoD,aAAa,EAAzD,OAAO,qBAAqB,EAAE,OAAO;QACvB,IAAI;QACH,SAAS;QACV,IAAI;QACJ,UAAU;KAClC,EAQA;IA1BD,oBAAe;IAEf,4CAA4C;IAC5C,SADW,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAC3B;IAEZ,mEAA2B;IAC3B,oBAAe;IAEf,sDAAsD;IACtD,gBADW,KAAK,CAAC,aAAa,GAAG,gBAAgB,CAAC,CAC/B;IAWjB,qDAAkC;IAClC,mBAAmC;IACnC,eAA8B;IAC9B,aAA6B;IAC7B,aAAwB;IACxB,mBAAkC;IAGpC,0DAA0D;IAC1D,SADc,OAAO,CAAC,IAAI,CAAC,CAQ1B;IALC,kCAAiC;IAOnC,0DAA0D;IAC1D,oBADc,OAAO,CAAC,IAAI,CAAC,CAc1B;IAED,0DAA0D;IAC1D,2BADc,OAAO,CAAC,IAAI,CAAC,CAK1B;IAED,4CAA4C;IAC5C,YADc,OAAO,CAOpB;IAED,0DAA0D;IAC1D,eADc,OAAO,CAAC,IAAI,CAAC,CAW1B;IAED,0DAA0D;IAC1D,cADc,OAAO,CAAC,IAAI,CAAC,CAgB1B;IAED,0DAA0D;IAC1D,QADc,OAAO,CAAC,IAAI,CAAC,CAQ1B;IAED,0CAA0C;IAC1C,eADc,IAAI,CAGjB;IAED;;;OAGG;IACH,gBAAiB,OAHN,KAGW,KAFT,IAAI,CAIhB;IAED;;;OAGG;IACH,eAAgB,QAHL,OAAO,KAAK,EAAE,MAGH,KAFT,IAAI,CA8BhB;IAED;;;OAGG;IACH,gBAAiB,QAHN,YAGY,KAFV,IAAI,CAahB;IAED,0DAA0D;IAC1D,eADc,OAAO,CAAC,IAAI,CAAC,CAc1B;IAED,+EAA+E;IAC/E,sBADc,aAAa,GAAG,gBAAgB,CAY7C;CACF;yBAhNwB,oBAAoB;0BACnB,2BAA2B;6BAJxB,gCAAgC;mBAC1C,cAAc;gBACjB,KAAK"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/http-server/index.js"],"names":[],"mappings":"AAWA;IAYE;;;;;;;;OAQG;IACH,8FAPG;QAAoD,aAAa,EAAzD,OAAO,qBAAqB,EAAE,OAAO;QACvB,IAAI;QACH,SAAS;QACV,IAAI;QACJ,UAAU;QACqK,0BAA0B,WAA9M;YAAC,aAAa,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC;YAAC,QAAQ,EAAE,CAAS,IAAqB,EAArB;gBAAC,WAAW,EAAE,MAAM,CAAA;aAAC,KAAI,OAAO,CAAC,IAAI,CAAC,CAAA;SAAC,KAAI;YAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;YAAC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;SAAC;KAC/L,EASA;IA5BD,oBAAe;IAEf,4CAA4C;IAC5C,SADW,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAC3B;IAEZ,mEAA2B;IAC3B,oBAAe;IAEf,sDAAsD;IACtD,gBADW,KAAK,CAAC,aAAa,GAAG,gBAAgB,CAAC,CAC/B;IAYjB,qDAAkC;IAClC,oCAJkB;QAAC,aAAa,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,CAAS,IAAqB,EAArB;YAAC,WAAW,EAAE,MAAM,CAAA;SAAC,KAAI,OAAO,CAAC,IAAI,CAAC,CAAA;KAAC,KAAI;QAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAAC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAC,cAIlI;IAC5D,mBAAmC;IACnC,eAA8B;IAC9B,aAA6B;IAC7B,aAAwB;IACxB,mBAAkC;IAGpC,0DAA0D;IAC1D,SADc,OAAO,CAAC,IAAI,CAAC,CAS1B;IALC,kCAAiC;IAOnC,0DAA0D;IAC1D,oBADc,OAAO,CAAC,IAAI,CAAC,CAc1B;IAED,0DAA0D;IAC1D,2BADc,OAAO,CAAC,IAAI,CAAC,CAK1B;IAED,4CAA4C;IAC5C,YADc,OAAO,CAOpB;IAED,0DAA0D;IAC1D,eADc,OAAO,CAAC,IAAI,CAAC,CAW1B;IAED,0DAA0D;IAC1D,cADc,OAAO,CAAC,IAAI,CAAC,CAgB1B;IAED,0DAA0D;IAC1D,QADc,OAAO,CAAC,IAAI,CAAC,CAW1B;IATC,+BAAqB;IAErB;eA1F+I,MAAM,OAAO,CAAC,IAAI,CAAC;cAAQ,MAAM,OAAO,CAAC,IAAI,CAAC;kBA0FzJ;IAStC,0CAA0C;IAC1C,eADc,IAAI,CAGjB;IAED;;;OAGG;IACH,gBAAiB,OAHN,KAGW,KAFT,IAAI,CAIhB;IAED;;;OAGG;IACH,eAAgB,QAHL,OAAO,KAAK,EAAE,MAGH,KAFT,IAAI,CA8BhB;IAED;;;OAGG;IACH,gBAAiB,QAHN,YAGY,KAFV,IAAI,CAahB;IAED,0DAA0D;IAC1D,eADc,OAAO,CAAC,IAAI,CAAC,CAK1B;IAED,qFAAqF;IACrF,uBADc,OAAO,CAAC,aAAa,GAAG,gBAAgB,CAAC,CAetD;IAED,+EAA+E;IAC/E,sBADc,aAAa,GAAG,gBAAgB,CAY7C;IAED,6EAA6E;IAC7E,iCADc,OAAO,CAGpB;IAED,uEAAuE;IACvE,6BADc,OAAO,CAAC,IAAI,CAAC,CAiB1B;IAED,4EAA4E;IAC5E,+BADc,OAAO,CAAC,IAAI,CAAC,CAyB1B;IApBG,wDAA8C;IAIhD,qDAA2C;CAiB9C;yBAjRwB,oBAAoB;0BACnB,2BAA2B;6BAJxB,gCAAgC;mBAC1C,cAAc;gBACjB,KAAK"}
@@ -1,5 +1,6 @@
1
1
  // @ts-check
2
2
  import { digg } from "diggerize";
3
+ import DevelopmentReloader from "./development-reloader.js";
3
4
  import EventEmitter from "../utils/event-emitter.js";
4
5
  import InProcessHandler from "./worker-handler/in-process.js";
5
6
  import Logger from "../logger.js";
@@ -21,9 +22,11 @@ export default class VelociousHttpServer {
21
22
  * @param {boolean} [args.inProcess] - Run HTTP handlers in the main thread instead of worker threads.
22
23
  * @param {number} [args.port] - Port.
23
24
  * @param {number} [args.maxWorkers] - Max workers.
25
+ * @param {function({configuration: import("../configuration.js").default, onReload: function({changedPath: string}) : Promise<void>}) : {start: () => Promise<void>, stop: () => Promise<void>}} [args.developmentReloaderFactory] - Development reloader factory.
24
26
  */
25
- constructor({ configuration, host, inProcess, maxWorkers, port }) {
27
+ constructor({ configuration, developmentReloaderFactory, host, inProcess, maxWorkers, port }) {
26
28
  this.configuration = configuration;
29
+ this.developmentReloaderFactory = developmentReloaderFactory;
27
30
  this.inProcess = inProcess || false;
28
31
  this.logger = new Logger(this);
29
32
  this.host = host || "0.0.0.0";
@@ -33,6 +36,7 @@ export default class VelociousHttpServer {
33
36
  /** @returns {Promise<void>} - Resolves when complete. */
34
37
  async start() {
35
38
  await this._ensureAtLeastOneWorker();
39
+ await this._startDevelopmentReloader();
36
40
  this.netServer = new Net.Server();
37
41
  this.netServer.on("close", this.onClose);
38
42
  this.netServer.on("connection", this.onConnection);
@@ -96,6 +100,9 @@ export default class VelociousHttpServer {
96
100
  }
97
101
  /** @returns {Promise<void>} - Resolves when complete. */
98
102
  async stop() {
103
+ this._stopping = true;
104
+ await this.developmentReloader?.stop();
105
+ this.developmentReloader = undefined;
99
106
  await this.stopClients();
100
107
  await this.stopServer();
101
108
  const stopTasks = this.workerHandlers.map((handler) => handler.stop());
@@ -158,6 +165,11 @@ export default class VelociousHttpServer {
158
165
  };
159
166
  /** @returns {Promise<void>} - Resolves when complete. */
160
167
  async spawnWorker() {
168
+ const workerHandler = await this._buildWorkerHandler();
169
+ this.workerHandlers.push(workerHandler);
170
+ }
171
+ /** @returns {Promise<WorkerHandler | InProcessHandler>} - Started worker handler. */
172
+ async _buildWorkerHandler() {
161
173
  const workerCount = this.workerCount;
162
174
  this.workerCount++;
163
175
  const Handler = this.inProcess ? InProcessHandler : WorkerHandler;
@@ -166,7 +178,7 @@ export default class VelociousHttpServer {
166
178
  workerCount
167
179
  });
168
180
  await workerHandler.start();
169
- this.workerHandlers.push(workerHandler);
181
+ return workerHandler;
170
182
  }
171
183
  /** @returns {WorkerHandler | InProcessHandler} - The worker handler to use. */
172
184
  workerHandlerToUse() {
@@ -178,5 +190,48 @@ export default class VelociousHttpServer {
178
190
  }
179
191
  return workerHandler;
180
192
  }
193
+ /** @returns {boolean} - Whether development worker hot reload should run. */
194
+ shouldUseDevelopmentHotReload() {
195
+ return !this.inProcess && this.configuration.getEnvironment() === "development";
196
+ }
197
+ /** @returns {Promise<void>} - Resolves when watcher setup finishes. */
198
+ async _startDevelopmentReloader() {
199
+ if (!this.shouldUseDevelopmentHotReload())
200
+ return;
201
+ if (this.developmentReloader)
202
+ return;
203
+ const createDevelopmentReloader = this.developmentReloaderFactory
204
+ || ((args) => new DevelopmentReloader(args));
205
+ this.developmentReloader = createDevelopmentReloader({
206
+ configuration: this.configuration,
207
+ onReload: async ({ changedPath }) => {
208
+ await this.logger.info(`Development hot reload detected change in ${changedPath}`);
209
+ await this.reloadWorkersForDevelopment();
210
+ }
211
+ });
212
+ await this.developmentReloader.start();
213
+ }
214
+ /** @returns {Promise<void>} - Resolves when workers have been refreshed. */
215
+ async reloadWorkersForDevelopment() {
216
+ if (this._stopping)
217
+ return;
218
+ if (this._reloadingWorkersForDevelopment) {
219
+ this._reloadWorkersForDevelopmentQueued = true;
220
+ return;
221
+ }
222
+ this._reloadingWorkersForDevelopment = true;
223
+ try {
224
+ do {
225
+ this._reloadWorkersForDevelopmentQueued = false;
226
+ const oldWorkerHandlers = [...this.workerHandlers];
227
+ const newWorkerHandler = await this._buildWorkerHandler();
228
+ this.workerHandlers = [newWorkerHandler];
229
+ await Promise.all(oldWorkerHandlers.map((workerHandler) => workerHandler.stop()));
230
+ } while (this._reloadWorkersForDevelopmentQueued && !this._stopping);
231
+ }
232
+ finally {
233
+ this._reloadingWorkersForDevelopment = false;
234
+ }
235
+ }
181
236
  }
182
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaHR0cC1zZXJ2ZXIvaW5kZXguanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sRUFBQyxJQUFJLEVBQUMsTUFBTSxXQUFXLENBQUE7QUFDOUIsT0FBTyxZQUFZLE1BQU0sMkJBQTJCLENBQUE7QUFDcEQsT0FBTyxnQkFBZ0IsTUFBTSxnQ0FBZ0MsQ0FBQTtBQUM3RCxPQUFPLE1BQU0sTUFBTSxjQUFjLENBQUE7QUFDakMsT0FBTyxHQUFHLE1BQU0sS0FBSyxDQUFBO0FBQ3JCLE9BQU8sWUFBWSxNQUFNLG9CQUFvQixDQUFBO0FBQzdDLE9BQU8sYUFBYSxNQUFNLDJCQUEyQixDQUFBO0FBRXJELE1BQU0sQ0FBQyxPQUFPLE9BQU8sbUJBQW1CO0lBQ3RDLFdBQVcsR0FBRyxDQUFDLENBQUE7SUFFZiw0Q0FBNEM7SUFDNUMsT0FBTyxHQUFHLEVBQUUsQ0FBQTtJQUVaLE1BQU0sR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFBO0lBQzNCLFdBQVcsR0FBRyxDQUFDLENBQUE7SUFFZixzREFBc0Q7SUFDdEQsY0FBYyxHQUFHLEVBQUUsQ0FBQTtJQUVuQjs7Ozs7OztPQU9HO0lBQ0gsWUFBWSxFQUFDLGFBQWEsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUM7UUFDNUQsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUE7UUFDbEMsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLElBQUksS0FBSyxDQUFBO1FBQ25DLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDOUIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLElBQUksU0FBUyxDQUFBO1FBQzdCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxJQUFJLElBQUksQ0FBQTtRQUN4QixJQUFJLENBQUMsVUFBVSxHQUFHLFVB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Q0FBQyxjQUFjLENBQUMsa0JBQWtCLENBQUMsQ0FBQTtRQUU3RCxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDbkIsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQ0FBb0Msa0JBQWtCLEVBQUUsQ0FBQyxDQUFBO1FBQzNFLENBQUM7UUFFRCxPQUFPLGFBQWEsQ0FBQTtJQUN0QixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHtkaWdnfSBmcm9tIFwiZGlnZ2VyaXplXCJcbmltcG9ydCBFdmVudEVtaXR0ZXIgZnJvbSBcIi4uL3V0aWxzL2V2ZW50LWVtaXR0ZXIuanNcIlxuaW1wb3J0IEluUHJvY2Vzc0hhbmRsZXIgZnJvbSBcIi4vd29ya2VyLWhhbmRsZXIvaW4tcHJvY2Vzcy5qc1wiXG5pbXBvcnQgTG9nZ2VyIGZyb20gXCIuLi9sb2dnZXIuanNcIlxuaW1wb3J0IE5ldCBmcm9tIFwibmV0XCJcbmltcG9ydCBTZXJ2ZXJDbGllbnQgZnJvbSBcIi4vc2VydmVyLWNsaWVudC5qc1wiXG5pbXBvcnQgV29ya2VySGFuZGxlciBmcm9tIFwiLi93b3JrZXItaGFuZGxlci9pbmRleC5qc1wiXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFZlbG9jaW91c0h0dHBTZXJ2ZXIge1xuICBjbGllbnRDb3VudCA9IDBcblxuICAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIFNlcnZlckNsaWVudD59ICAqL1xuICBjbGllbnRzID0ge31cblxuICBldmVudHMgPSBuZXcgRXZlbnRFbWl0dGVyKClcbiAgd29ya2VyQ291bnQgPSAwXG5cbiAgLyoqIEB0eXBlIHtBcnJheTxXb3JrZXJIYW5kbGVyIHwgSW5Qcm9jZXNzSGFuZGxlcj59ICovXG4gIHdvcmtlckhhbmRsZXJzID0gW11cblxuICAvKipcbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zIG9iamVjdC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9IGFyZ3MuY29uZmlndXJhdGlvbiAtIENvbmZpZ3VyYXRpb24gaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYXJncy5ob3N0XSAtIEhvc3QuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2FyZ3MuaW5Qcm9jZXNzXSAtIFJ1biBIVFRQIGhhbmRsZXJzIGluIHRoZSBtYWluIHRocmVhZCBpbnN0ZWFkIG9mIHdvcmtlciB0aHJlYWRzLlxuICAgKiBAcGFyYW0ge251bWJlcn0gW2FyZ3MucG9ydF0gLSBQb3J0LlxuICAgKiBAcGFyYW0ge251bWJlcn0gW2FyZ3MubWF4V29ya2Vyc10gLSBNYXggd29ya2Vycy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHtjb25maWd1cmF0aW9uLCBob3N0LCBpblByb2Nlc3MsIG1heFdvcmtlcnMsIHBvcnR9KSB7XG4gICAgdGhpcy5jb25maWd1cmF0aW9uID0gY29uZmlndXJhdGlvblxuICAgIHRoaXMuaW5Qcm9jZXNzID0gaW5Qcm9jZXNzIHx8IGZhbHNlXG4gICAgdGhpcy5sb2dnZXIgPSBuZXcgTG9nZ2VyKHRoaXMpXG4gICAgdGhpcy5ob3N0ID0gaG9zdCB8fCBcIjAuMC4wLjBcIlxuICAgIHRoaXMucG9ydCA9IHBvcnQgfHwgMzAwNlxuICAgIHRoaXMubWF4V29ya2VycyA9IG1heFdvcmtlcnMgfHwgMTZcbiAgfVxuXG4gIC8qKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbXBsZXRlLiAgKi9cbiAgYXN5bmMgc3RhcnQoKSB7XG4gICAgYXdhaXQgdGhpcy5fZW5zdXJlQXRMZWFzdE9uZVdvcmtlcigpXG4gICAgdGhpcy5uZXRTZXJ2ZXIgPSBuZXcgTmV0LlNlcnZlcigpXG4gICAgdGhpcy5uZXRTZXJ2ZXIub24oXCJjbG9zZVwiLCB0aGlzLm9uQ2xvc2UpXG4gICAgdGhpcy5uZXRTZXJ2ZXIub24oXCJjb25uZWN0aW9uXCIsIHRoaXMub25Db25uZWN0aW9uKVxuICAgIHRoaXMubmV0U2VydmVyLm9uKFwiZXJyb3JcIiwgdGhpcy5vblNlcnZlckVycm9yKVxuICAgIGF3YWl0IHRoaXMuX25ldFNlcnZlckxpc3RlbigpXG4gIH1cblxuICAvKiogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS4gICovXG4gIF9uZXRTZXJ2ZXJMaXN0ZW4oKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGlmICghdGhpcy5uZXRTZXJ2ZXIpIHRocm93IG5ldyBFcnJvcihcIk5vIG5ldFNlcnZlclwiKVxuXG4gICAgICB0cnkge1xuICAgICAgICB0aGlzLm5ldFNlcnZlci5saXN0ZW4odGhpcy5wb3J0LCB0aGlzLmhvc3QsICgpID0+IHtcbiAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhgVmVsb2Npb3VzIGxpc3RlbmluZyBvbiAke3RoaXMuaG9zdH06JHt0aGlzLnBvcnR9YClcbiAgICAgICAgICByZXNvbHZlKHVuZGVmaW5lZClcbiAgICAgICAgfSlcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHJlamVjdChlcnJvcilcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgLyoqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuICAqL1xuICBhc3luYyBfZW5zdXJlQXRMZWFzdE9uZVdvcmtlcigpIHtcbiAgICBpZiAodGhpcy53b3JrZXJIYW5kbGVycy5sZW5ndGggPT0gMCkge1xuICAgICAgYXdhaXQgdGhpcy5zcGF3bldvcmtlcigpXG4gICAgfVxuICB9XG5cbiAgLyoqIEByZXR1cm5zIHtib29sZWFufSAtIFdoZXRoZXIgYWN0aXZlLiAgKi9cbiAgaXNBY3RpdmUoKSB7XG4gICAgaWYgKHRoaXMubmV0U2VydmVyKSB7XG4gICAgICByZXR1cm4gdGhpcy5uZXRTZXJ2ZXIubGlzdGVuaW5nXG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICAvKiogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS4gICovXG4gIGFzeW5jIHN0b3BDbGllbnRzKCkge1xuICAgIGNvbnN0IHByb21pc2VzID0gW11cblxuICAgIGZvciAoY29uc3QgY2xpZW50Q291bnQgaW4gdGhpcy5jbGllbnRzKSB7XG4gICAgICBjb25zdCBjbGllbnQgPSB0aGlzLmNsaWVudHNbY2xpZW50Q291bnRdXG5cbiAgICAgIHByb21pc2VzLnB1c2goY2xpZW50LmVuZCgpKVxuICAgIH1cblxuICAgIGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKVxuICB9XG5cbiAgLyoqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuICAqL1xuICBzdG9wU2VydmVyKCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBpZiAoIXRoaXMubmV0U2VydmVyIHx8ICF0aGlzLm5ldFNlcnZlci5saXN0ZW5pbmcpIHtcbiAgICAgICAgcmVzb2x2ZSh1bmRlZmluZWQpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICB0aGlzLm5ldFNlcnZlci5jbG9zZSgoZXJyb3IpID0+IHtcbiAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUodW5kZWZpbmVkKVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH0pXG4gIH1cblxuICAvKiogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS4gICovXG4gIGFzeW5jIHN0b3AoKSB7XG4gICAgYXdhaXQgdGhpcy5zdG9wQ2xpZW50cygpXG4gICAgYXdhaXQgdGhpcy5zdG9wU2VydmVyKClcblxuICAgIGNvbnN0IHN0b3BUYXNrcyA9IHRoaXMud29ya2VySGFuZGxlcnMubWFwKChoYW5kbGVyKSA9PiBoYW5kbGVyLnN0b3AoKSlcbiAgICBhd2FpdCBQcm9taXNlLmFsbChzdG9wVGFza3MpXG4gICAgdGhpcy53b3JrZXJIYW5kbGVycyA9IFtdXG4gIH1cblxuICAvKiogQHJldHVybnMge3ZvaWR9IC0gTm8gcmV0dXJuIHZhbHVlLiAgKi9cbiAgb25DbG9zZSA9ICgpID0+IHtcbiAgICB0aGlzLmV2ZW50cy5lbWl0KFwiY2xvc2VcIilcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0Vycm9yfSBlcnJvciAtIFNlcnZlciBzb2NrZXQgZXJyb3IuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIG9uU2VydmVyRXJyb3IgPSAoZXJyb3IpID0+IHtcbiAgICB0aGlzLmxvZ2dlci5lcnJvcihgVmVsb2Npb3VzIEhUVFAgc2VydmVyIHNvY2tldCBlcnJvciBvbiAke3RoaXMuaG9zdH06JHt0aGlzLnBvcnR9YCwgZXJyb3IpXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCJuZXRcIikuU29ja2V0fSBzb2NrZXQgLSBTb2NrZXQgaW5zdGFuY2UuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIG9uQ29ubmVjdGlvbiA9IChzb2NrZXQpID0+IHtcbiAgICBjb25zdCBjbGllbnRDb3VudCA9IHRoaXMuY2xpZW50Q291bnRcblxuICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcIk5ldyBjbGllbnRcIiwge1xuICAgICAgY2xpZW50Q291bnQsXG4gICAgICByZW1vdGVBZGRyZXNzOiBzb2NrZXQucmVtb3RlQWRkcmVzcyxcbiAgICAgIHJlbW90ZUZhbWlseTogc29ja2V0LnJlbW90ZUZhbWlseSxcbiAgICAgIHJlbW90ZVBvcnQ6IHNvY2tldC5yZW1vdGVQb3J0XG4gICAgfV0pXG4gICAgdGhpcy5jbGllbnRDb3VudCsrXG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qgd29ya2VySGFuZGxlciA9IHRoaXMud29ya2VySGFuZGxlclRvVXNlKClcbiAgICAgIGNvbnN0IGNsaWVudCA9IG5ldyBTZXJ2ZXJDbGllbnQoe1xuICAgICAgICBjbGllbnRDb3VudCxcbiAgICAgICAgY29uZmlndXJhdGlvbjogdGhpcy5jb25maWd1cmF0aW9uLFxuICAgICAgICBzb2NrZXRcbiAgICAgIH0pXG5cbiAgICAgIGNsaWVudC5ldmVudHMub24oXCJjbG9zZVwiLCB0aGlzLm9uQ2xpZW50Q2xvc2UpXG5cbiAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKGBHYXZlIGNsaWVudCAke2NsaWVudENvdW50fSB0byB3b3JrZXIgJHt3b3JrZXJIYW5kbGVyLndvcmtlckNvdW50fWApXG4gICAgICB3b3JrZXJIYW5kbGVyLmFkZFNvY2tldENvbm5lY3Rpb24oY2xpZW50KVxuICAgICAgdGhpcy5jbGllbnRzW2NsaWVudENvdW50XSA9IGNsaWVudFxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihgRmFpbGVkIHRvIGluaXRpYWxpemUgY2xpZW50ICR7Y2xpZW50Q291bnR9IG9uIG5ldyBjb25uZWN0aW9uYCwgZXJyb3IpXG4gICAgICBzb2NrZXQuZGVzdHJveSgpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U2VydmVyQ2xpZW50fSBjbGllbnQgLSBDbGllbnQgaW5zdGFuY2UuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIG9uQ2xpZW50Q2xvc2UgPSAoY2xpZW50KSA9PiB7XG4gICAgY29uc3QgY2xpZW50Q291bnQgPSBkaWdnKGNsaWVudCwgXCJjbGllbnRDb3VudFwiKVxuICAgIGNvbnN0IG9sZENsaWVudHNMZW5ndGggPSBPYmplY3Qua2V5cyh0aGlzLmNsaWVudHMpLmxlbmd0aFxuXG4gICAgZGVsZXRlIHRoaXMuY2xpZW50c1tjbGllbnRDb3VudF1cblxuICAgIGNvbnN0IG5ld0NsaWVudHNMZW5ndGggPSBPYmplY3Qua2V5cyh0aGlzLmNsaWVudHMpLmxlbmd0aFxuXG4gICAgaWYgKG5ld0NsaWVudHNMZW5ndGggIT0gKG9sZENsaWVudHNMZW5ndGggLSAxKSkge1xuICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoYEV4cGVjdGVkIGNsaWVudCB0byBoYXZlIGJlZW4gcmVtb3ZlZCBidXQgbGVuZ3RoIGRpZG4ndCBjaGFuZ2UgZnJvbSAke29sZENsaWVudHNMZW5ndGh9IHRvICR7b2xkQ2xpZW50c0xlbmd0aCAtIDF9YClcbiAgICB9XG4gIH1cblxuICAvKiogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS4gICovXG4gIGFzeW5jIHNwYXduV29ya2VyKCkge1xuICAgIGNvbnN0IHdvcmtlckNvdW50ID0gdGhpcy53b3JrZXJDb3VudFxuXG4gICAgdGhpcy53b3JrZXJDb3VudCsrXG5cbiAgICBjb25zdCBIYW5kbGVyID0gdGhpcy5pblByb2Nlc3MgPyBJblByb2Nlc3NIYW5kbGVyIDogV29ya2VySGFuZGxlclxuICAgIGNvbnN0IHdvcmtlckhhbmRsZXIgPSBuZXcgSGFuZGxlcih7XG4gICAgICBjb25maWd1cmF0aW9uOiB0aGlzLmNvbmZpZ3VyYXRpb24sXG4gICAgICB3b3JrZXJDb3VudFxuICAgIH0pXG5cbiAgICBhd2FpdCB3b3JrZXJIYW5kbGVyLnN0YXJ0KClcbiAgICB0aGlzLndvcmtlckhhbmRsZXJzLnB1c2god29ya2VySGFuZGxlcilcbiAgfVxuXG4gIC8qKiBAcmV0dXJucyB7V29ya2VySGFuZGxlciB8IEluUHJvY2Vzc0hhbmRsZXJ9IC0gVGhlIHdvcmtlciBoYW5kbGVyIHRvIHVzZS4gKi9cbiAgd29ya2VySGFuZGxlclRvVXNlKCkge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKGBXb3JrZXIgaGFuZGxlcnMgbGVuZ3RoOiAke3RoaXMud29ya2VySGFuZGxlcnMubGVuZ3RofWApXG5cbiAgICBjb25zdCByYW5kb21Xb3JrZXJOdW1iZXIgPSBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiB0aGlzLndvcmtlckhhbmRsZXJzLmxlbmd0aClcbiAgICBjb25zdCB3b3JrZXJIYW5kbGVyID0gdGhpcy53b3JrZXJIYW5kbGVyc1tyYW5kb21Xb3JrZXJOdW1iZXJdXG5cbiAgICBpZiAoIXdvcmtlckhhbmRsZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gd29ya2VySGFuZGxlciBieSB0aGF0IG51bWJlcjogJHtyYW5kb21Xb3JrZXJOdW1iZXJ9YClcbiAgICB9XG5cbiAgICByZXR1cm4gd29ya2VySGFuZGxlclxuICB9XG59XG4iXX0=
237
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaHR0cC1zZXJ2ZXIvaW5kZXguanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sRUFBQyxJQUFJLEVBQUMsTUFBTSxXQUFXLENBQUE7QUFDOUIsT0FBTyxtQkFBbUIsTUFBTSwyQkFBMkIsQ0FBQTtBQUMzRCxPQUFPLFlBQVksTUFBTSwyQkFBMkIsQ0FBQTtBQUNwRCxPQUFPLGdCQUFnQixNQUFNLGdDQUFnQyxDQUFBO0FBQzdELE9BQU8sTUFBTSxNQUFNLGNBQWMsQ0FBQTtBQUNqQyxPQUFPLEdBQUcsTUFBTSxLQUFLLENBQUE7QUFDckIsT0FBTyxZQUFZLE1BQU0sb0JBQW9CLENBQUE7QUFDN0MsT0FBTyxhQUFhLE1BQU0sMkJBQTJCLENBQUE7QUFFckQsTUFBTSxDQUFDLE9BQU8sT0FBTyxtQkFBbUI7SUFDdEMsV0FBVyxHQUFHLENBQUMsQ0FBQTtJQUVmLDRDQUE0QztJQUM1QyxPQUFPLEdBQUcsRUFBRSxDQUFBO0lBRVosTUFBTSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUE7SUFDM0IsV0FBVyxHQUFHLENBQUMsQ0FBQTtJQUVmLHNEQUFzRDtJQUN0RCxjQUFjLEdBQUcsRUFBRSxDQUFBO0lBRW5COzs7Ozs7OztPQVFHO0lBQ0gsWUFBWSxFQUFDLGFBQWEsRUFBRSwwQkFBMEIsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUM7UUFDeEYsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUE7UUFDbEMsSUFBSSxDQUFDLDBCQUEwQixHQUFHLDBCQUEwQixDQUFBO1FBQzVELElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxJQUFJLEtBQUssQ0FBQTtRQUNuQyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQzlCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxJ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QVMsRUFBQztRQUN0RSxDQUFDO2dCQUFTLENBQUM7WUFDVCxJQUFJLENBQUMsK0JBQStCLEdBQUcsS0FBSyxDQUFBO1FBQzlDLENBQUM7SUFDSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHtkaWdnfSBmcm9tIFwiZGlnZ2VyaXplXCJcbmltcG9ydCBEZXZlbG9wbWVudFJlbG9hZGVyIGZyb20gXCIuL2RldmVsb3BtZW50LXJlbG9hZGVyLmpzXCJcbmltcG9ydCBFdmVudEVtaXR0ZXIgZnJvbSBcIi4uL3V0aWxzL2V2ZW50LWVtaXR0ZXIuanNcIlxuaW1wb3J0IEluUHJvY2Vzc0hhbmRsZXIgZnJvbSBcIi4vd29ya2VyLWhhbmRsZXIvaW4tcHJvY2Vzcy5qc1wiXG5pbXBvcnQgTG9nZ2VyIGZyb20gXCIuLi9sb2dnZXIuanNcIlxuaW1wb3J0IE5ldCBmcm9tIFwibmV0XCJcbmltcG9ydCBTZXJ2ZXJDbGllbnQgZnJvbSBcIi4vc2VydmVyLWNsaWVudC5qc1wiXG5pbXBvcnQgV29ya2VySGFuZGxlciBmcm9tIFwiLi93b3JrZXItaGFuZGxlci9pbmRleC5qc1wiXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFZlbG9jaW91c0h0dHBTZXJ2ZXIge1xuICBjbGllbnRDb3VudCA9IDBcblxuICAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIFNlcnZlckNsaWVudD59ICAqL1xuICBjbGllbnRzID0ge31cblxuICBldmVudHMgPSBuZXcgRXZlbnRFbWl0dGVyKClcbiAgd29ya2VyQ291bnQgPSAwXG5cbiAgLyoqIEB0eXBlIHtBcnJheTxXb3JrZXJIYW5kbGVyIHwgSW5Qcm9jZXNzSGFuZGxlcj59ICovXG4gIHdvcmtlckhhbmRsZXJzID0gW11cblxuICAvKipcbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zIG9iamVjdC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9IGFyZ3MuY29uZmlndXJhdGlvbiAtIENvbmZpZ3VyYXRpb24gaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYXJncy5ob3N0XSAtIEhvc3QuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2FyZ3MuaW5Qcm9jZXNzXSAtIFJ1biBIVFRQIGhhbmRsZXJzIGluIHRoZSBtYWluIHRocmVhZCBpbnN0ZWFkIG9mIHdvcmtlciB0aHJlYWRzLlxuICAgKiBAcGFyYW0ge251bWJlcn0gW2FyZ3MucG9ydF0gLSBQb3J0LlxuICAgKiBAcGFyYW0ge251bWJlcn0gW2FyZ3MubWF4V29ya2Vyc10gLSBNYXggd29ya2Vycy5cbiAgICogQHBhcmFtIHtmdW5jdGlvbih7Y29uZmlndXJhdGlvbjogaW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0LCBvblJlbG9hZDogZnVuY3Rpb24oe2NoYW5nZWRQYXRoOiBzdHJpbmd9KSA6IFByb21pc2U8dm9pZD59KSA6IHtzdGFydDogKCkgPT4gUHJvbWlzZTx2b2lkPiwgc3RvcDogKCkgPT4gUHJvbWlzZTx2b2lkPn19IFthcmdzLmRldmVsb3BtZW50UmVsb2FkZXJGYWN0b3J5XSAtIERldmVsb3BtZW50IHJlbG9hZGVyIGZhY3RvcnkuXG4gICAqL1xuICBjb25zdHJ1Y3Rvcih7Y29uZmlndXJhdGlvbiwgZGV2ZWxvcG1lbnRSZWxvYWRlckZhY3RvcnksIGhvc3QsIGluUHJvY2VzcywgbWF4V29ya2VycywgcG9ydH0pIHtcbiAgICB0aGlzLmNvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uXG4gICAgdGhpcy5kZXZlbG9wbWVudFJlbG9hZGVyRmFjdG9yeSA9IGRldmVsb3BtZW50UmVsb2FkZXJGYWN0b3J5XG4gICAgdGhpcy5pblByb2Nlc3MgPSBpblByb2Nlc3MgfHwgZmFsc2VcbiAgICB0aGlzLmxvZ2dlciA9IG5ldyBMb2dnZXIodGhpcylcbiAgICB0aGlzLmhvc3QgPSBob3N0IHx8IFwiMC4wLjAuMFwiXG4gICAgdGhpcy5wb3J0ID0gcG9ydCB8fCAzMDA2XG4gICAgdGhpcy5tYXhXb3JrZXJzID0gbWF4V29ya2VycyB8fCAxNlxuICB9XG5cbiAgLyoqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuICAqL1xuICBhc3luYyBzdGFydCgpIHtcbiAgICBhd2FpdCB0aGlzLl9lbnN1cmVBdExlYXN0T25lV29ya2VyKClcbiAgICBhd2FpdCB0aGlzLl9zdGFydERldmVsb3BtZW50UmVsb2FkZXIoKVxuICAgIHRoaXMubmV0U2VydmVyID0gbmV3IE5ldC5TZXJ2ZXIoKVxuICAgIHRoaXMubmV0U2VydmVyLm9uKFwiY2xvc2VcIiwgdGhpcy5vbkNsb3NlKVxuICAgIHRoaXMubmV0U2VydmVyLm9uKFwiY29ubmVjdGlvblwiLCB0aGlzLm9uQ29ubmVjdGlvbilcbiAgICB0aGlzLm5ldFNlcnZlci5vbihcImVycm9yXCIsIHRoaXMub25TZXJ2ZXJFcnJvcilcbiAgICBhd2FpdCB0aGlzLl9uZXRTZXJ2ZXJMaXN0ZW4oKVxuICB9XG5cbiAgLyoqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuICAqL1xuICBfbmV0U2VydmVyTGlzdGVuKCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBpZiAoIXRoaXMubmV0U2VydmVyKSB0aHJvdyBuZXcgRXJyb3IoXCJObyBuZXRTZXJ2ZXJcIilcblxuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy5uZXRTZXJ2ZXIubGlzdGVuKHRoaXMucG9ydCwgdGhpcy5ob3N0LCAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoYFZlbG9jaW91cyBsaXN0ZW5pbmcgb24gJHt0aGlzLmhvc3R9OiR7dGhpcy5wb3J0fWApXG4gICAgICAgICAgcmVzb2x2ZSh1bmRlZmluZWQpXG4gICAgICAgIH0pXG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICByZWplY3QoZXJyb3IpXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIC8qKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbXBsZXRlLiAgKi9cbiAgYXN5bmMgX2Vuc3VyZUF0TGVhc3RPbmVXb3JrZXIoKSB7XG4gICAgaWYgKHRoaXMud29ya2VySGFuZGxlcnMubGVuZ3RoID09IDApIHtcbiAgICAgIGF3YWl0IHRoaXMuc3Bhd25Xb3JrZXIoKVxuICAgIH1cbiAgfVxuXG4gIC8qKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBXaGV0aGVyIGFjdGl2ZS4gICovXG4gIGlzQWN0aXZlKCkge1xuICAgIGlmICh0aGlzLm5ldFNlcnZlcikge1xuICAgICAgcmV0dXJuIHRoaXMubmV0U2VydmVyLmxpc3RlbmluZ1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgLyoqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuICAqL1xuICBhc3luYyBzdG9wQ2xpZW50cygpIHtcbiAgICBjb25zdCBwcm9taXNlcyA9IFtdXG5cbiAgICBmb3IgKGNvbnN0IGNsaWVudENvdW50IGluIHRoaXMuY2xpZW50cykge1xuICAgICAgY29uc3QgY2xpZW50ID0gdGhpcy5jbGllbnRzW2NsaWVudENvdW50XVxuXG4gICAgICBwcm9taXNlcy5wdXNoKGNsaWVudC5lbmQoKSlcbiAgICB9XG5cbiAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcylcbiAgfVxuXG4gIC8qKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbXBsZXRlLiAgKi9cbiAgc3RvcFNlcnZlcigpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgaWYgKCF0aGlzLm5ldFNlcnZlciB8fCAhdGhpcy5uZXRTZXJ2ZXIubGlzdGVuaW5nKSB7XG4gICAgICAgIHJlc29sdmUodW5kZWZpbmVkKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgdGhpcy5uZXRTZXJ2ZXIuY2xvc2UoKGVycm9yKSA9PiB7XG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgIHJlamVjdChlcnJvcilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHVuZGVmaW5lZClcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9KVxuICB9XG5cbiAgLyoqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuICAqL1xuICBhc3luYyBzdG9wKCkge1xuICAgIHRoaXMuX3N0b3BwaW5nID0gdHJ1ZVxuICAgIGF3YWl0IHRoaXMuZGV2ZWxvcG1lbnRSZWxvYWRlcj8uc3RvcCgpXG4gICAgdGhpcy5kZXZlbG9wbWVudFJlbG9hZGVyID0gdW5kZWZpbmVkXG4gICAgYXdhaXQgdGhpcy5zdG9wQ2xpZW50cygpXG4gICAgYXdhaXQgdGhpcy5zdG9wU2VydmVyKClcblxuICAgIGNvbnN0IHN0b3BUYXNrcyA9IHRoaXMud29ya2VySGFuZGxlcnMubWFwKChoYW5kbGVyKSA9PiBoYW5kbGVyLnN0b3AoKSlcbiAgICBhd2FpdCBQcm9taXNlLmFsbChzdG9wVGFza3MpXG4gICAgdGhpcy53b3JrZXJIYW5kbGVycyA9IFtdXG4gIH1cblxuICAvKiogQHJldHVybnMge3ZvaWR9IC0gTm8gcmV0dXJuIHZhbHVlLiAgKi9cbiAgb25DbG9zZSA9ICgpID0+IHtcbiAgICB0aGlzLmV2ZW50cy5lbWl0KFwiY2xvc2VcIilcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0Vycm9yfSBlcnJvciAtIFNlcnZlciBzb2NrZXQgZXJyb3IuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIG9uU2VydmVyRXJyb3IgPSAoZXJyb3IpID0+IHtcbiAgICB0aGlzLmxvZ2dlci5lcnJvcihgVmVsb2Npb3VzIEhUVFAgc2VydmVyIHNvY2tldCBlcnJvciBvbiAke3RoaXMuaG9zdH06JHt0aGlzLnBvcnR9YCwgZXJyb3IpXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCJuZXRcIikuU29ja2V0fSBzb2NrZXQgLSBTb2NrZXQgaW5zdGFuY2UuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIG9uQ29ubmVjdGlvbiA9IChzb2NrZXQpID0+IHtcbiAgICBjb25zdCBjbGllbnRDb3VudCA9IHRoaXMuY2xpZW50Q291bnRcblxuICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcIk5ldyBjbGllbnRcIiwge1xuICAgICAgY2xpZW50Q291bnQsXG4gICAgICByZW1vdGVBZGRyZXNzOiBzb2NrZXQucmVtb3RlQWRkcmVzcyxcbiAgICAgIHJlbW90ZUZhbWlseTogc29ja2V0LnJlbW90ZUZhbWlseSxcbiAgICAgIHJlbW90ZVBvcnQ6IHNvY2tldC5yZW1vdGVQb3J0XG4gICAgfV0pXG4gICAgdGhpcy5jbGllbnRDb3VudCsrXG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qgd29ya2VySGFuZGxlciA9IHRoaXMud29ya2VySGFuZGxlclRvVXNlKClcbiAgICAgIGNvbnN0IGNsaWVudCA9IG5ldyBTZXJ2ZXJDbGllbnQoe1xuICAgICAgICBjbGllbnRDb3VudCxcbiAgICAgICAgY29uZmlndXJhdGlvbjogdGhpcy5jb25maWd1cmF0aW9uLFxuICAgICAgICBzb2NrZXRcbiAgICAgIH0pXG5cbiAgICAgIGNsaWVudC5ldmVudHMub24oXCJjbG9zZVwiLCB0aGlzLm9uQ2xpZW50Q2xvc2UpXG5cbiAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKGBHYXZlIGNsaWVudCAke2NsaWVudENvdW50fSB0byB3b3JrZXIgJHt3b3JrZXJIYW5kbGVyLndvcmtlckNvdW50fWApXG4gICAgICB3b3JrZXJIYW5kbGVyLmFkZFNvY2tldENvbm5lY3Rpb24oY2xpZW50KVxuICAgICAgdGhpcy5jbGllbnRzW2NsaWVudENvdW50XSA9IGNsaWVudFxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihgRmFpbGVkIHRvIGluaXRpYWxpemUgY2xpZW50ICR7Y2xpZW50Q291bnR9IG9uIG5ldyBjb25uZWN0aW9uYCwgZXJyb3IpXG4gICAgICBzb2NrZXQuZGVzdHJveSgpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U2VydmVyQ2xpZW50fSBjbGllbnQgLSBDbGllbnQgaW5zdGFuY2UuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIG9uQ2xpZW50Q2xvc2UgPSAoY2xpZW50KSA9PiB7XG4gICAgY29uc3QgY2xpZW50Q291bnQgPSBkaWdnKGNsaWVudCwgXCJjbGllbnRDb3VudFwiKVxuICAgIGNvbnN0IG9sZENsaWVudHNMZW5ndGggPSBPYmplY3Qua2V5cyh0aGlzLmNsaWVudHMpLmxlbmd0aFxuXG4gICAgZGVsZXRlIHRoaXMuY2xpZW50c1tjbGllbnRDb3VudF1cblxuICAgIGNvbnN0IG5ld0NsaWVudHNMZW5ndGggPSBPYmplY3Qua2V5cyh0aGlzLmNsaWVudHMpLmxlbmd0aFxuXG4gICAgaWYgKG5ld0NsaWVudHNMZW5ndGggIT0gKG9sZENsaWVudHNMZW5ndGggLSAxKSkge1xuICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoYEV4cGVjdGVkIGNsaWVudCB0byBoYXZlIGJlZW4gcmVtb3ZlZCBidXQgbGVuZ3RoIGRpZG4ndCBjaGFuZ2UgZnJvbSAke29sZENsaWVudHNMZW5ndGh9IHRvICR7b2xkQ2xpZW50c0xlbmd0aCAtIDF9YClcbiAgICB9XG4gIH1cblxuICAvKiogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS4gICovXG4gIGFzeW5jIHNwYXduV29ya2VyKCkge1xuICAgIGNvbnN0IHdvcmtlckhhbmRsZXIgPSBhd2FpdCB0aGlzLl9idWlsZFdvcmtlckhhbmRsZXIoKVxuXG4gICAgdGhpcy53b3JrZXJIYW5kbGVycy5wdXNoKHdvcmtlckhhbmRsZXIpXG4gIH1cblxuICAvKiogQHJldHVybnMge1Byb21pc2U8V29ya2VySGFuZGxlciB8IEluUHJvY2Vzc0hhbmRsZXI+fSAtIFN0YXJ0ZWQgd29ya2VyIGhhbmRsZXIuICovXG4gIGFzeW5jIF9idWlsZFdvcmtlckhhbmRsZXIoKSB7XG4gICAgY29uc3Qgd29ya2VyQ291bnQgPSB0aGlzLndvcmtlckNvdW50XG5cbiAgICB0aGlzLndvcmtlckNvdW50KytcblxuICAgIGNvbnN0IEhhbmRsZXIgPSB0aGlzLmluUHJvY2VzcyA/IEluUHJvY2Vzc0hhbmRsZXIgOiBXb3JrZXJIYW5kbGVyXG4gICAgY29uc3Qgd29ya2VySGFuZGxlciA9IG5ldyBIYW5kbGVyKHtcbiAgICAgIGNvbmZpZ3VyYXRpb246IHRoaXMuY29uZmlndXJhdGlvbixcbiAgICAgIHdvcmtlckNvdW50XG4gICAgfSlcblxuICAgIGF3YWl0IHdvcmtlckhhbmRsZXIuc3RhcnQoKVxuXG4gICAgcmV0dXJuIHdvcmtlckhhbmRsZXJcbiAgfVxuXG4gIC8qKiBAcmV0dXJucyB7V29ya2VySGFuZGxlciB8IEluUHJvY2Vzc0hhbmRsZXJ9IC0gVGhlIHdvcmtlciBoYW5kbGVyIHRvIHVzZS4gKi9cbiAgd29ya2VySGFuZGxlclRvVXNlKCkge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKGBXb3JrZXIgaGFuZGxlcnMgbGVuZ3RoOiAke3RoaXMud29ya2VySGFuZGxlcnMubGVuZ3RofWApXG5cbiAgICBjb25zdCByYW5kb21Xb3JrZXJOdW1iZXIgPSBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiB0aGlzLndvcmtlckhhbmRsZXJzLmxlbmd0aClcbiAgICBjb25zdCB3b3JrZXJIYW5kbGVyID0gdGhpcy53b3JrZXJIYW5kbGVyc1tyYW5kb21Xb3JrZXJOdW1iZXJdXG5cbiAgICBpZiAoIXdvcmtlckhhbmRsZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gd29ya2VySGFuZGxlciBieSB0aGF0IG51bWJlcjogJHtyYW5kb21Xb3JrZXJOdW1iZXJ9YClcbiAgICB9XG5cbiAgICByZXR1cm4gd29ya2VySGFuZGxlclxuICB9XG5cbiAgLyoqIEByZXR1cm5zIHtib29sZWFufSAtIFdoZXRoZXIgZGV2ZWxvcG1lbnQgd29ya2VyIGhvdCByZWxvYWQgc2hvdWxkIHJ1bi4gKi9cbiAgc2hvdWxkVXNlRGV2ZWxvcG1lbnRIb3RSZWxvYWQoKSB7XG4gICAgcmV0dXJuICF0aGlzLmluUHJvY2VzcyAmJiB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0RW52aXJvbm1lbnQoKSA9PT0gXCJkZXZlbG9wbWVudFwiXG4gIH1cblxuICAvKiogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiB3YXRjaGVyIHNldHVwIGZpbmlzaGVzLiAqL1xuICBhc3luYyBfc3RhcnREZXZlbG9wbWVudFJlbG9hZGVyKCkge1xuICAgIGlmICghdGhpcy5zaG91bGRVc2VEZXZlbG9wbWVudEhvdFJlbG9hZCgpKSByZXR1cm5cbiAgICBpZiAodGhpcy5kZXZlbG9wbWVudFJlbG9hZGVyKSByZXR1cm5cblxuICAgIGNvbnN0IGNyZWF0ZURldmVsb3BtZW50UmVsb2FkZXIgPSB0aGlzLmRldmVsb3BtZW50UmVsb2FkZXJGYWN0b3J5XG4gICAgICB8fCAoKGFyZ3MpID0+IG5ldyBEZXZlbG9wbWVudFJlbG9hZGVyKGFyZ3MpKVxuXG4gICAgdGhpcy5kZXZlbG9wbWVudFJlbG9hZGVyID0gY3JlYXRlRGV2ZWxvcG1lbnRSZWxvYWRlcih7XG4gICAgICBjb25maWd1cmF0aW9uOiB0aGlzLmNvbmZpZ3VyYXRpb24sXG4gICAgICBvblJlbG9hZDogYXN5bmMgKHtjaGFuZ2VkUGF0aH0pID0+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5sb2dnZXIuaW5mbyhgRGV2ZWxvcG1lbnQgaG90IHJlbG9hZCBkZXRlY3RlZCBjaGFuZ2UgaW4gJHtjaGFuZ2VkUGF0aH1gKVxuICAgICAgICBhd2FpdCB0aGlzLnJlbG9hZFdvcmtlcnNGb3JEZXZlbG9wbWVudCgpXG4gICAgICB9XG4gICAgfSlcblxuICAgIGF3YWl0IHRoaXMuZGV2ZWxvcG1lbnRSZWxvYWRlci5zdGFydCgpXG4gIH1cblxuICAvKiogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiB3b3JrZXJzIGhhdmUgYmVlbiByZWZyZXNoZWQuICovXG4gIGFzeW5jIHJlbG9hZFdvcmtlcnNGb3JEZXZlbG9wbWVudCgpIHtcbiAgICBpZiAodGhpcy5fc3RvcHBpbmcpIHJldHVyblxuXG4gICAgaWYgKHRoaXMuX3JlbG9hZGluZ1dvcmtlcnNGb3JEZXZlbG9wbWVudCkge1xuICAgICAgdGhpcy5fcmVsb2FkV29ya2Vyc0ZvckRldmVsb3BtZW50UXVldWVkID0gdHJ1ZVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgdGhpcy5fcmVsb2FkaW5nV29ya2Vyc0ZvckRldmVsb3BtZW50ID0gdHJ1ZVxuXG4gICAgdHJ5IHtcbiAgICAgIGRvIHtcbiAgICAgICAgdGhpcy5fcmVsb2FkV29ya2Vyc0ZvckRldmVsb3BtZW50UXVldWVkID0gZmFsc2VcblxuICAgICAgICBjb25zdCBvbGRXb3JrZXJIYW5kbGVycyA9IFsuLi50aGlzLndvcmtlckhhbmRsZXJzXVxuICAgICAgICBjb25zdCBuZXdXb3JrZXJIYW5kbGVyID0gYXdhaXQgdGhpcy5fYnVpbGRXb3JrZXJIYW5kbGVyKClcblxuICAgICAgICB0aGlzLndvcmtlckhhbmRsZXJzID0gW25ld1dvcmtlckhhbmRsZXJdXG5cbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwob2xkV29ya2VySGFuZGxlcnMubWFwKCh3b3JrZXJIYW5kbGVyKSA9PiB3b3JrZXJIYW5kbGVyLnN0b3AoKSkpXG4gICAgICB9IHdoaWxlICh0aGlzLl9yZWxvYWRXb3JrZXJzRm9yRGV2ZWxvcG1lbnRRdWV1ZWQgJiYgIXRoaXMuX3N0b3BwaW5nKVxuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLl9yZWxvYWRpbmdXb3JrZXJzRm9yRGV2ZWxvcG1lbnQgPSBmYWxzZVxuICAgIH1cbiAgfVxufVxuIl19