aboutsummaryrefslogtreecommitdiff
path: root/src/server/DashSession/Session
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/DashSession/Session')
-rw-r--r--src/server/DashSession/Session/agents/applied_session_agent.ts23
-rw-r--r--src/server/DashSession/Session/agents/monitor.ts48
-rw-r--r--src/server/DashSession/Session/agents/process_message_router.ts12
-rw-r--r--src/server/DashSession/Session/agents/promisified_ipc_manager.ts56
-rw-r--r--src/server/DashSession/Session/agents/server_worker.ts46
-rw-r--r--src/server/DashSession/Session/utilities/repl.ts76
-rw-r--r--src/server/DashSession/Session/utilities/session_config.ts104
-rw-r--r--src/server/DashSession/Session/utilities/utilities.ts43
8 files changed, 202 insertions, 206 deletions
diff --git a/src/server/DashSession/Session/agents/applied_session_agent.ts b/src/server/DashSession/Session/agents/applied_session_agent.ts
index 2037e93e5..c42ba95cc 100644
--- a/src/server/DashSession/Session/agents/applied_session_agent.ts
+++ b/src/server/DashSession/Session/agents/applied_session_agent.ts
@@ -1,13 +1,13 @@
-import * as _cluster from "cluster";
-import { Monitor } from "./monitor";
-import { ServerWorker } from "./server_worker";
+import * as _cluster from 'cluster';
+import { Monitor } from './monitor';
+import { ServerWorker } from './server_worker';
+
const cluster = _cluster as any;
const isMaster = cluster.isPrimary;
export type ExitHandler = (reason: Error | boolean) => void | Promise<void>;
export abstract class AppliedSessionAgent {
-
// the following two methods allow the developer to create a custom
// session and use the built in customization options for each thread
protected abstract initializeMonitor(monitor: Monitor): Promise<string>;
@@ -18,15 +18,15 @@ export abstract class AppliedSessionAgent {
public killSession = (reason: string, graceful = true, errorCode = 0) => {
const target = cluster.default.isPrimary ? this.sessionMonitor : this.serverWorker;
target.killSession(reason, graceful, errorCode);
- }
+ };
private sessionMonitorRef: Monitor | undefined;
public get sessionMonitor(): Monitor {
if (!cluster.default.isPrimary) {
- this.serverWorker.emit("kill", {
+ this.serverWorker.emit('kill', {
graceful: false,
- reason: "Cannot access the session monitor directly from the server worker thread.",
- errorCode: 1
+ reason: 'Cannot access the session monitor directly from the server worker thread.',
+ errorCode: 1,
});
throw new Error();
}
@@ -36,7 +36,7 @@ export abstract class AppliedSessionAgent {
private serverWorkerRef: ServerWorker | undefined;
public get serverWorker(): ServerWorker {
if (isMaster) {
- throw new Error("Cannot access the server worker directly from the session monitor thread");
+ throw new Error('Cannot access the server worker directly from the session monitor thread');
}
return this.serverWorkerRef!;
}
@@ -52,8 +52,7 @@ export abstract class AppliedSessionAgent {
this.serverWorkerRef = await this.initializeServerWorker();
}
} else {
- throw new Error("Cannot launch a session thread more than once per process.");
+ throw new Error('Cannot launch a session thread more than once per process.');
}
}
-
-} \ No newline at end of file
+}
diff --git a/src/server/DashSession/Session/agents/monitor.ts b/src/server/DashSession/Session/agents/monitor.ts
index a6fde4356..6cdad46c2 100644
--- a/src/server/DashSession/Session/agents/monitor.ts
+++ b/src/server/DashSession/Session/agents/monitor.ts
@@ -1,21 +1,19 @@
-import { ExitHandler } from './applied_session_agent';
-import { Configuration, configurationSchema, defaultConfig, Identifiers, colorMapping } from '../utilities/session_config';
-import Repl, { ReplAction } from '../utilities/repl';
+import { ExecOptions, exec } from 'child_process';
import * as _cluster from 'cluster';
import { Worker } from 'cluster';
-import { manage, MessageHandler, ErrorLike } from './promisified_ipc_manager';
-import { red, cyan, white, yellow, blue } from 'colors';
-import { exec, ExecOptions } from 'child_process';
-import { validate, ValidationError } from 'jsonschema';
-import { Utilities } from '../utilities/utilities';
+import { blue, cyan, red, white, yellow } from 'colors';
import { readFileSync } from 'fs';
+import { ValidationError, validate } from 'jsonschema';
+import Repl, { ReplAction } from '../utilities/repl';
+import { Configuration, Identifiers, colorMapping, configurationSchema, defaultConfig } from '../utilities/session_config';
+import { Utilities } from '../utilities/utilities';
+import { ExitHandler } from './applied_session_agent';
import IPCMessageReceiver from './process_message_router';
+import { ErrorLike, MessageHandler, manage } from './promisified_ipc_manager';
import { ServerWorker } from './server_worker';
+
const cluster = _cluster as any;
-const isWorker = cluster.isWorker;
-const setupMaster = cluster.setupPrimary;
-const on = cluster.on;
-const fork = cluster.fork;
+const { isWorker, setupMaster, on, fork } = cluster;
/**
* Validates and reads the configuration file, accordingly builds a child process factory
@@ -41,9 +39,8 @@ export class Monitor extends IPCMessageReceiver {
} else if (++Monitor.count > 1) {
console.error(red('cannot create more than one monitor.'));
process.exit(1);
- } else {
- return new Monitor();
}
+ return new Monitor();
}
private constructor() {
@@ -128,25 +125,25 @@ export class Monitor extends IPCMessageReceiver {
this.repl.registerCommand(basename, argPatterns, action);
};
- public exec = (command: string, options?: ExecOptions) => {
- return new Promise<void>(resolve => {
+ public exec = (command: string, options?: ExecOptions) =>
+ new Promise<void>(resolve => {
exec(command, { ...options, encoding: 'utf8' }, (error, stdout, stderr) => {
if (error) {
this.execLog(red(`unable to execute ${white(command)}`));
error.message.split('\n').forEach(line => line.length && this.execLog(red(`(error) ${line}`)));
} else {
- let outLines: string[], errorLines: string[];
- if ((outLines = stdout.split('\n').filter(line => line.length)).length) {
+ const outLines = stdout.split('\n').filter(line => line.length);
+ if (outLines.length) {
outLines.forEach(line => line.length && this.execLog(cyan(`(stdout) ${line}`)));
}
- if ((errorLines = stderr.split('\n').filter(line => line.length)).length) {
+ const errorLines = stderr.split('\n').filter(line => line.length);
+ if (errorLines.length) {
errorLines.forEach(line => line.length && this.execLog(yellow(`(stderr) ${line}`)));
}
}
resolve();
});
});
- };
/**
* Generates a blue UTC string associated with the time
@@ -226,12 +223,10 @@ export class Monitor extends IPCMessageReceiver {
const newPollingIntervalSeconds = Math.floor(Number(args[1]));
if (newPollingIntervalSeconds < 0) {
this.mainLog(red('the polling interval must be a non-negative integer'));
- } else {
- if (newPollingIntervalSeconds !== this.config.polling.intervalSeconds) {
- this.config.polling.intervalSeconds = newPollingIntervalSeconds;
- if (args[2] === 'true') {
- Monitor.IPCManager.emit('updatePollingInterval', { newPollingIntervalSeconds });
- }
+ } else if (newPollingIntervalSeconds !== this.config.polling.intervalSeconds) {
+ this.config.polling.intervalSeconds = newPollingIntervalSeconds;
+ if (args[2] === 'true') {
+ Monitor.IPCManager.emit('updatePollingInterval', { newPollingIntervalSeconds });
}
}
});
@@ -297,6 +292,7 @@ export class Monitor extends IPCMessageReceiver {
};
}
+// eslint-disable-next-line no-redeclare
export namespace Monitor {
export enum IntrinsicEvents {
KeyGenerated = 'key_generated',
diff --git a/src/server/DashSession/Session/agents/process_message_router.ts b/src/server/DashSession/Session/agents/process_message_router.ts
index 0745ea455..3e2b7d8d0 100644
--- a/src/server/DashSession/Session/agents/process_message_router.ts
+++ b/src/server/DashSession/Session/agents/process_message_router.ts
@@ -1,7 +1,6 @@
-import { MessageHandler, PromisifiedIPCManager, HandlerMap } from "./promisified_ipc_manager";
+import { MessageHandler, PromisifiedIPCManager, HandlerMap } from './promisified_ipc_manager';
export default abstract class IPCMessageReceiver {
-
protected static IPCManager: PromisifiedIPCManager;
protected handlers: HandlerMap = {};
@@ -18,7 +17,7 @@ export default abstract class IPCMessageReceiver {
} else {
handlers.push(handler);
}
- }
+ };
/**
* Unregister a given listener at this message.
@@ -31,11 +30,10 @@ export default abstract class IPCMessageReceiver {
handlers.splice(index, 1);
}
}
- }
+ };
- /**
+ /**
* Unregister all listeners at this message.
*/
public clearMessageListeners = (...names: string[]) => names.map(name => delete this.handlers[name]);
-
-} \ No newline at end of file
+}
diff --git a/src/server/DashSession/Session/agents/promisified_ipc_manager.ts b/src/server/DashSession/Session/agents/promisified_ipc_manager.ts
index 76e218977..fc870d003 100644
--- a/src/server/DashSession/Session/agents/promisified_ipc_manager.ts
+++ b/src/server/DashSession/Session/agents/promisified_ipc_manager.ts
@@ -1,13 +1,14 @@
-import { Utilities } from '../utilities/utilities';
import { ChildProcess } from 'child_process';
+import { Utilities } from '../utilities/utilities';
/**
- * Convenience constructor
- * @param target the process / worker to which to attach the specialized listeners
+ * Specifies a general message format for this API
*/
-export function manage(target: IPCTarget, handlers?: HandlerMap) {
- return new PromisifiedIPCManager(target, handlers);
-}
+export type Message<T = any> = {
+ name: string;
+ args?: T;
+};
+export type MessageHandler<T = any> = (args: T) => any | Promise<any>;
/**
* Captures the logic to execute upon receiving a message
@@ -22,15 +23,10 @@ export type HandlerMap = { [name: string]: MessageHandler[] };
*/
export type IPCTarget = NodeJS.Process | ChildProcess;
-/**
- * Specifies a general message format for this API
- */
-export type Message<T = any> = {
- name: string;
- args?: T;
-};
-export type MessageHandler<T = any> = (args: T) => any | Promise<any>;
-
+interface Metadata {
+ isResponse: boolean;
+ id: string;
+}
/**
* When a message is emitted, it is embedded with private metadata
* to facilitate the resolution of promises, etc.
@@ -38,10 +34,6 @@ export type MessageHandler<T = any> = (args: T) => any | Promise<any>;
interface InternalMessage extends Message {
metadata: Metadata;
}
-interface Metadata {
- isResponse: boolean;
- id: string;
-}
/**
* Allows for the transmission of the error's key features over IPC.
@@ -95,11 +87,11 @@ export class PromisifiedIPCManager {
}
return new Promise<Response<T>>(resolve => {
const messageId = Utilities.guid();
- type InternalMessageHandler = (message: any /* MessageListener*/) => any | Promise<any>;
- const responseHandler: InternalMessageHandler = ({ metadata: { id, isResponse }, args }) => {
+ type InternalMessageHandler = (message: any /* MessageListener */) => any | Promise<any>;
+ const responseHandler: InternalMessageHandler = ({ metadata: { id, isResponse }, args: hargs }) => {
if (isResponse && id === messageId) {
this.target.removeListener('message', responseHandler);
- resolve(args);
+ resolve(hargs);
}
};
this.target.addListener('message', responseHandler);
@@ -118,8 +110,9 @@ export class PromisifiedIPCManager {
* completion response for each of the pending messages, allowing their
* promises in the caller to resolve.
*/
- public destroy = () => {
- return new Promise<void>(async resolve => {
+ public destroy = () =>
+ // eslint-disable-next-line no-async-promise-executor
+ new Promise<void>(async resolve => {
if (this.callerIsTarget) {
this.destroyHelper();
} else {
@@ -127,7 +120,6 @@ export class PromisifiedIPCManager {
}
resolve();
});
- };
/**
* Dispatches the dummy responses and sets the isDestroyed flag to true.
@@ -168,12 +160,20 @@ export class PromisifiedIPCManager {
error = e;
}
if (!this.isDestroyed && this.target.send) {
- const metadata = { id, isResponse: true };
+ const metadataRes = { id, isResponse: true };
const response: Response = { results, error };
- const message = { name, args: response, metadata };
+ const messageRes = { name, args: response, metadata: metadataRes };
delete this.pendingMessages[id];
- this.target.send(message);
+ this.target.send(messageRes);
}
}
};
}
+
+/**
+ * Convenience constructor
+ * @param target the process / worker to which to attach the specialized listeners
+ */
+export function manage(target: IPCTarget, handlers?: HandlerMap) {
+ return new PromisifiedIPCManager(target, handlers);
+}
diff --git a/src/server/DashSession/Session/agents/server_worker.ts b/src/server/DashSession/Session/agents/server_worker.ts
index d8b3ee80b..85e1b31d6 100644
--- a/src/server/DashSession/Session/agents/server_worker.ts
+++ b/src/server/DashSession/Session/agents/server_worker.ts
@@ -1,10 +1,10 @@
-import cluster from "cluster";
-import { green, red, white, yellow } from "colors";
-import { get } from "request-promise";
-import { ExitHandler } from "./applied_session_agent";
-import { Monitor } from "./monitor";
-import IPCMessageReceiver from "./process_message_router";
-import { ErrorLike, manage } from "./promisified_ipc_manager";
+import cluster from 'cluster';
+import { green, red, white, yellow } from 'colors';
+import { get } from 'request-promise';
+import { ExitHandler } from './applied_session_agent';
+import { Monitor } from './monitor';
+import IPCMessageReceiver from './process_message_router';
+import { ErrorLike, manage } from './promisified_ipc_manager';
/**
* Effectively, each worker repairs the connection to the server by reintroducing a consistent state
@@ -23,18 +23,17 @@ export class ServerWorker extends IPCMessageReceiver {
private isInitialized = false;
public static Create(work: Function) {
if (cluster.isPrimary) {
- console.error(red("cannot create a worker on the monitor process."));
+ console.error(red('cannot create a worker on the monitor process.'));
process.exit(1);
} else if (++ServerWorker.count > 1) {
- ServerWorker.IPCManager.emit("kill", {
- reason: "cannot create more than one worker on a given worker process.",
+ ServerWorker.IPCManager.emit('kill', {
+ reason: 'cannot create more than one worker on a given worker process.',
graceful: false,
- errorCode: 1
+ errorCode: 1,
});
process.exit(1);
- } else {
- return new ServerWorker(work);
}
+ return new ServerWorker(work);
}
/**
@@ -48,7 +47,7 @@ export class ServerWorker extends IPCMessageReceiver {
* server worker (child process). This will also kill
* this process (child process).
*/
- public killSession = (reason: string, graceful = true, errorCode = 0) => this.emit<never>("kill", { reason, graceful, errorCode });
+ public killSession = (reason: string, graceful = true, errorCode = 0) => this.emit<never>('kill', { reason, graceful, errorCode });
/**
* A convenience wrapper to tell the session monitor (parent process)
@@ -60,7 +59,7 @@ export class ServerWorker extends IPCMessageReceiver {
super();
this.configureInternalHandlers();
ServerWorker.IPCManager = manage(process, this.handlers);
- this.lifecycleNotification(green(`initializing process... ${white(`[${process.execPath} ${process.execArgv.join(" ")}]`)}`));
+ this.lifecycleNotification(green(`initializing process... ${white(`[${process.execPath} ${process.execArgv.join(' ')}]`)}`));
const { pollingRoute, serverPort, pollingIntervalSeconds, pollingFailureTolerance } = process.env;
this.serverPort = Number(serverPort);
@@ -78,8 +77,10 @@ export class ServerWorker extends IPCMessageReceiver {
*/
protected configureInternalHandlers = () => {
// updates the local values of variables to the those sent from master
- this.on("updatePollingInterval", ({ newPollingIntervalSeconds }) => this.pollingIntervalSeconds = newPollingIntervalSeconds);
- this.on("manualExit", async ({ isSessionEnd }) => {
+ this.on('updatePollingInterval', ({ newPollingIntervalSeconds }) => {
+ this.pollingIntervalSeconds = newPollingIntervalSeconds;
+ });
+ this.on('manualExit', async ({ isSessionEnd }) => {
await ServerWorker.IPCManager.destroy();
await this.executeExitHandlers(isSessionEnd);
process.exit(0);
@@ -91,7 +92,7 @@ export class ServerWorker extends IPCMessageReceiver {
const appropriateError = reason instanceof Error ? reason : new Error(`unhandled rejection: ${reason}`);
this.proactiveUnplannedExit(appropriateError);
});
- }
+ };
/**
* Execute the list of functions registered to be called
@@ -102,7 +103,7 @@ export class ServerWorker extends IPCMessageReceiver {
/**
* Notify master thread (which will log update in the console) of initialization via IPC.
*/
- public lifecycleNotification = (event: string) => this.emit("lifecycle", { event });
+ public lifecycleNotification = (event: string) => this.emit('lifecycle', { event });
/**
* Called whenever the process has a reason to terminate, either through an uncaught exception
@@ -120,11 +121,11 @@ export class ServerWorker extends IPCMessageReceiver {
this.lifecycleNotification(red(error.message));
await ServerWorker.IPCManager.destroy();
process.exit(1);
- }
+ };
/**
* This monitors the health of the server by submitting a get request to whatever port / route specified
- * by the configuration every n seconds, where n is also given by the configuration.
+ * by the configuration every n seconds, where n is also given by the configuration.
*/
private pollServer = async (): Promise<void> => {
await new Promise<void>(resolve => {
@@ -156,6 +157,5 @@ export class ServerWorker extends IPCMessageReceiver {
});
// controlled, asynchronous infinite recursion achieves a persistent poll that does not submit a new request until the previous has completed
this.pollServer();
- }
-
+ };
}
diff --git a/src/server/DashSession/Session/utilities/repl.ts b/src/server/DashSession/Session/utilities/repl.ts
index 643141286..5d9f15e4c 100644
--- a/src/server/DashSession/Session/utilities/repl.ts
+++ b/src/server/DashSession/Session/utilities/repl.ts
@@ -1,5 +1,5 @@
-import { createInterface, Interface } from "readline";
-import { red, green, white } from "colors";
+import { createInterface, Interface } from 'readline';
+import { red, green, white } from 'colors';
export interface Configuration {
identifier: () => string | string;
@@ -32,76 +32,82 @@ export default class Repl {
this.interface = createInterface(process.stdin, process.stdout).on('line', this.considerInput);
}
- private resolvedIdentifier = () => typeof this.identifier === "string" ? this.identifier : this.identifier();
+ private resolvedIdentifier = () => (typeof this.identifier === 'string' ? this.identifier : this.identifier());
private usage = (command: string, validCommand: boolean) => {
if (validCommand) {
const formatted = white(command);
- const patterns = green(this.commandMap.get(command)!.map(({ argPatterns }) => `${formatted} ${argPatterns.join(" ")}`).join('\n'));
+ const patterns = green(
+ this.commandMap
+ .get(command)!
+ .map(({ argPatterns }) => `${formatted} ${argPatterns.join(' ')}`)
+ .join('\n')
+ );
return `${this.resolvedIdentifier()}\nthe given arguments do not match any registered patterns for ${formatted}\nthe list of valid argument patterns is given by:\n${patterns}`;
- } else {
- const resolved = this.keys;
- if (resolved) {
- return resolved;
- }
- const members: string[] = [];
- const keys = this.commandMap.keys();
- let next: IteratorResult<string>;
- while (!(next = keys.next()).done) {
- members.push(next.value);
- }
- return `${this.resolvedIdentifier()} commands: { ${members.sort().join(", ")} }`;
}
- }
+ const resolved = this.keys;
+ if (resolved) {
+ return resolved;
+ }
+ const members: string[] = [];
+ const keys = this.commandMap.keys();
+ let next: IteratorResult<string>;
+ // eslint-disable-next-line no-cond-assign
+ while (!(next = keys.next()).done) {
+ members.push(next.value);
+ }
+ return `${this.resolvedIdentifier()} commands: { ${members.sort().join(', ')} }`;
+ };
private success = (command: string) => `${this.resolvedIdentifier()} completed local execution of ${white(command)}`;
public registerCommand = (basename: string, argPatterns: (RegExp | string)[], action: ReplAction) => {
const existing = this.commandMap.get(basename);
- const converted = argPatterns.map(input => input instanceof RegExp ? input : new RegExp(input));
+ const converted = argPatterns.map(input => (input instanceof RegExp ? input : new RegExp(input)));
const registration = { argPatterns: converted, action };
if (existing) {
existing.push(registration);
} else {
this.commandMap.set(basename, [registration]);
}
- }
+ };
private invalid = (command: string, validCommand: boolean) => {
- console.log(red(typeof this.onInvalid === "string" ? this.onInvalid : this.onInvalid(command, validCommand)));
+ console.log(red(typeof this.onInvalid === 'string' ? this.onInvalid : this.onInvalid(command, validCommand)));
this.busy = false;
- }
+ };
private valid = (command: string) => {
- console.log(green(typeof this.onValid === "string" ? this.onValid : this.onValid(command)));
+ console.log(green(typeof this.onValid === 'string' ? this.onValid : this.onValid(command)));
this.busy = false;
- }
+ };
- private considerInput = async (line: string) => {
+ private considerInput = async (lineIn: string) => {
if (this.busy) {
- console.log(red("Busy"));
+ console.log(red('Busy'));
return;
}
this.busy = true;
- line = line.trim();
+ let line = lineIn.trim();
if (this.isCaseSensitive) {
line = line.toLowerCase();
}
const [command, ...args] = line.split(/\s+/g);
if (!command) {
- return this.invalid(command, false);
+ this.invalid(command, false);
+ return;
}
const registered = this.commandMap.get(command);
if (registered) {
const { length } = args;
const candidates = registered.filter(({ argPatterns: { length: count } }) => count === length);
- for (const { argPatterns, action } of candidates) {
+ candidates.forEach(({ argPatterns, action }: { argPatterns: any; action: any }) => {
const parsed: string[] = [];
let matched = true;
if (length) {
for (let i = 0; i < length; i++) {
- let matches: RegExpExecArray | null;
- if ((matches = argPatterns[i].exec(args[i])) === null) {
+ const matches = argPatterns[i].exec(args[i]);
+ if (matches === null) {
matched = false;
break;
}
@@ -110,19 +116,17 @@ export default class Repl {
}
if (!length || matched) {
const result = action(parsed);
- const resolve = () => this.valid(`${command} ${parsed.join(" ")}`);
+ const resolve = () => this.valid(`${command} ${parsed.join(' ')}`);
if (result instanceof Promise) {
result.then(resolve);
} else {
resolve();
}
- return;
}
- }
+ });
this.invalid(command, true);
} else {
this.invalid(command, false);
}
- }
-
-} \ No newline at end of file
+ };
+}
diff --git a/src/server/DashSession/Session/utilities/session_config.ts b/src/server/DashSession/Session/utilities/session_config.ts
index 266759929..b42c1a3c7 100644
--- a/src/server/DashSession/Session/utilities/session_config.ts
+++ b/src/server/DashSession/Session/utilities/session_config.ts
@@ -1,85 +1,85 @@
-import { Schema } from "jsonschema";
-import { yellow, red, cyan, green, blue, magenta, Color, grey, gray, white, black } from "colors";
+import { Schema } from 'jsonschema';
+import { yellow, red, cyan, green, blue, magenta, Color, grey, gray, white, black } from 'colors';
const colorPattern = /black|red|green|yellow|blue|magenta|cyan|white|gray|grey/;
const identifierProperties: Schema = {
- type: "object",
+ type: 'object',
properties: {
text: {
- type: "string",
- minLength: 1
+ type: 'string',
+ minLength: 1,
},
color: {
- type: "string",
- pattern: colorPattern
- }
- }
+ type: 'string',
+ pattern: colorPattern,
+ },
+ },
};
const portProperties: Schema = {
- type: "number",
+ type: 'number',
minimum: 443,
- maximum: 65535
+ maximum: 65535,
};
export const configurationSchema: Schema = {
- id: "/configuration",
- type: "object",
+ id: '/configuration',
+ type: 'object',
properties: {
- showServerOutput: { type: "boolean" },
+ showServerOutput: { type: 'boolean' },
ports: {
- type: "object",
+ type: 'object',
properties: {
server: portProperties,
- socket: portProperties
+ socket: portProperties,
},
- required: ["server"],
- additionalProperties: true
+ required: ['server'],
+ additionalProperties: true,
},
identifiers: {
- type: "object",
+ type: 'object',
properties: {
master: identifierProperties,
worker: identifierProperties,
- exec: identifierProperties
- }
+ exec: identifierProperties,
+ },
},
polling: {
- type: "object",
+ type: 'object',
additionalProperties: false,
properties: {
intervalSeconds: {
- type: "number",
+ type: 'number',
minimum: 1,
- maximum: 86400
+ maximum: 86400,
},
route: {
- type: "string",
- pattern: /\/[a-zA-Z]*/g
+ type: 'string',
+ pattern: /\/[a-zA-Z]*/g,
},
failureTolerance: {
- type: "number",
+ type: 'number',
minimum: 0,
- }
- }
+ },
+ },
},
- }
+ },
};
-type ColorLabel = "yellow" | "red" | "cyan" | "green" | "blue" | "magenta" | "grey" | "gray" | "white" | "black";
+type ColorLabel = 'yellow' | 'red' | 'cyan' | 'green' | 'blue' | 'magenta' | 'grey' | 'gray' | 'white' | 'black';
export const colorMapping: Map<ColorLabel, Color> = new Map([
- ["yellow", yellow],
- ["red", red],
- ["cyan", cyan],
- ["green", green],
- ["blue", blue],
- ["magenta", magenta],
- ["grey", grey],
- ["gray", gray],
- ["white", white],
- ["black", black]
+ ['yellow', yellow],
+ ['red', red],
+ ['cyan', cyan],
+ ['green', green],
+ ['blue', blue],
+ ['magenta', magenta],
+ ['grey', grey],
+ ['gray', gray],
+ ['white', white],
+ ['black', black],
]);
interface Identifier {
@@ -108,22 +108,22 @@ export const defaultConfig: Configuration = {
showServerOutput: false,
identifiers: {
master: {
- text: "__monitor__",
- color: "yellow"
+ text: '__monitor__',
+ color: 'yellow',
},
worker: {
- text: "__server__",
- color: "magenta"
+ text: '__server__',
+ color: 'magenta',
},
exec: {
- text: "__exec__",
- color: "green"
- }
+ text: '__exec__',
+ color: 'green',
+ },
},
ports: { server: 1050 },
polling: {
- route: "/",
+ route: '/',
intervalSeconds: 30,
- failureTolerance: 0
- }
-}; \ No newline at end of file
+ failureTolerance: 0,
+ },
+};
diff --git a/src/server/DashSession/Session/utilities/utilities.ts b/src/server/DashSession/Session/utilities/utilities.ts
index eb8de9d7e..a2ba29c67 100644
--- a/src/server/DashSession/Session/utilities/utilities.ts
+++ b/src/server/DashSession/Session/utilities/utilities.ts
@@ -1,31 +1,16 @@
-import { v4 } from "uuid";
+import { v4 } from 'uuid';
export namespace Utilities {
-
export function guid() {
return v4();
}
- /**
- * At any arbitrary layer of nesting within the configuration objects, any single value that
- * is not specified by the configuration is given the default counterpart. If, within an object,
- * one peer is given by configuration and two are not, the one is preserved while the two are given
- * the default value.
- * @returns the composition of all of the assigned objects, much like Object.assign(), but with more
- * granularity in the overwriting of nested objects
- */
- export function preciseAssign(target: any, ...sources: any[]): any {
- for (const source of sources) {
- preciseAssignHelper(target, source);
- }
- return target;
- }
-
export function preciseAssignHelper(target: any, source: any) {
- Array.from(new Set([...Object.keys(target), ...Object.keys(source)])).map(property => {
- let targetValue: any, sourceValue: any;
- if (sourceValue = source[property]) {
- if (typeof sourceValue === "object" && typeof (targetValue = target[property]) === "object") {
+ Array.from(new Set([...Object.keys(target), ...Object.keys(source)])).forEach(property => {
+ const targetValue = target[property];
+ const sourceValue = source[property];
+ if (sourceValue) {
+ if (typeof sourceValue === 'object' && typeof targetValue === 'object') {
preciseAssignHelper(targetValue, sourceValue);
} else {
target[property] = sourceValue;
@@ -34,4 +19,18 @@ export namespace Utilities {
});
}
-} \ No newline at end of file
+ /**
+ * At any arbitrary layer of nesting within the configuration objects, any single value that
+ * is not specified by the configuration is given the default counterpart. If, within an object,
+ * one peer is given by configuration and two are not, the one is preserved while the two are given
+ * the default value.
+ * @returns the composition of all of the assigned objects, much like Object.assign(), but with more
+ * granularity in the overwriting of nested objects
+ */
+ export function preciseAssign(target: any, ...sources: any[]): any {
+ sources.forEach(source => {
+ preciseAssignHelper(target, source);
+ });
+ return target;
+ }
+}