Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Watch for changes to project and reload everything #142

Open
github-actions bot opened this issue Oct 24, 2020 · 0 comments
Open

Watch for changes to project and reload everything #142

github-actions bot opened this issue Oct 24, 2020 · 0 comments
Labels

Comments

@github-actions
Copy link

Watch for changes to project and reload everything

// TODO: Watch for changes to project and reload everything

import { readFile } from "fs";
import { join } from "path";
import YAML from "yaml";
import { ProjectConfig } from "@twokeys/core/lib/interfaces";
import { loadMainConfig } from "@twokeys/core/lib/config";
import { TWOKEYS_MAIN_CONFIG_DEFAULT_PATH } from "@twokeys/core/lib/constants";
import { AddOnsRegistry } from "@twokeys/addons";
import { loadDetectors } from "../loaders/loadDetectors";
import { loadExecutors } from "../loaders/loadExecutors";
import getTriggerHotkey from "./triggerHotkey";
import { Logger } from "@twokeys/core";

const logger: Logger = new Logger({
	name: "api",
});

const router = Router();

/**
 * Needed so we can use async/await
 */
// TODO: Rate limiting of routes to prevent excessive FS access
// TODO: Remove deprecated routes
export default async function getAPI(projectConfig: ProjectConfig, projectDir: string): Promise<Router> {
	logger.info("Preparing server...");

	// 1: Load config
	// TODO: Watch for changes to project and reload everything
	logger.info("Loading root config...");
	const mainConfig = await loadMainConfig(TWOKEYS_MAIN_CONFIG_DEFAULT_PATH);
	logger.info("Loading add-ons...");
	const registry = new AddOnsRegistry(mainConfig.registry_root);

	// Load add-ons & run startup functions for detectors
	const detectors = await loadDetectors(projectConfig, projectDir, registry);
	const executors = await loadExecutors(registry, projectDir);

	/**
	 * Returns to config for the 2Keys project
	 */
	router.get("/get/config/project", (req, res) => {
		logger.info("Sending a config copy as JSON...");
		// We can rely on hot reload to ensure it is accurate
		res.statusCode = 200;
		res.json(projectConfig);
	});

	/**
	 * Returns config for a detector
	 */
	router.get("/get/config/detectors/:detector", (req, res) => {
		const detectorToGet = req. params.detector;
		logger.info(`Requested config for detector ${detectorToGet}`);
		if (detectors.has(detectorToGet)) {
			res.statusCode = 200;
			res.json(detectors.get(detectorToGet));
		} else {
			logger.info(`${detectorToGet} not found!`);
			res.statusCode = 404;
			res.json({
				message: "Not Found"
			});
		}
	});

	/**
 	 * Returns the config for the 2Keys project
		* @deprecated
 	 */
	router.get("/get/deprecated/config", (req, res, next) => {
		logger.debug("Sending a config copy as JSON...");
		logger.warn("/get/config is deprecated.");
		readFile(join(process.cwd(), "config.yml"), (err, data) => {
			if (err) {
				return next(err);
			}
			const data_to_send = JSON.stringify(YAML.parse(data.toString()));
			res.setHeader("Content-Type", "application/json");
			res.statusCode = 200;
			res.send(data_to_send);
		});
	});

	/**
	 * Trigger a hotkey
	 * 
	 * Provide these property:
	 * ```json
	 * {
	 * 	"hotkey": "^A" // hotkey code to find in keyboard
	 * 	"event": "up" | "down" | "hold" // OPTIONAL event type
	 * }
	 * ```
	 */
	router.post("/post/trigger/:detector/:keyboard", getTriggerHotkey(detectors, executors));

	/**
	 * Trigger a hotkey
	 * Info to send:
	 * - keyboard: The keyboard name that has been pressed
	 * - hotkey: set of keys that have been pressed
	 * @deprecated
	 */
	/*router.post("/post/depreacted/trigger", async (req, res, next) => {*/
	/**
		* 1: Get hotkey function from config
		* 2: Execute C++ bindings with #Include <root of keyboard>; function()
		*/
	// Get vars
	/*const keyboard = req.body.keyboard;
		const hotkey_code = req.body.hotkey;
		const value: EvDevValues = Object.prototype.hasOwnProperty.call(req.body, "value") ? req.body.value : EvDevValues.Down;
		logger.debug(`Got keyboard ${keyboard} and hotkey ${hotkey_code}, with value ${value}`);
		// Parse config
		try {
			const fetched_hotkey = await fetch_hotkey(keyboard, hotkey_code); // Gets hotkey
			let func_to_run: string;

			// Use the value arg to select
			if (typeof fetched_hotkey.func === "object") {
				// Is an object
				logger.debug("Got a multi event hotkey.");
				// Select which function to run
				if (value === EvDevValues.Down) {
					func_to_run = fetched_hotkey.func.down;
				} else if (value === EvDevValues.Up) {
					func_to_run = fetched_hotkey.func.up;
				} else {
					// Stop exec as and error was encountered
					return next(new TypeError(`The request keyboard event value of ${value} is invalid.  Valid event values are: 0 (Up) & 1 (Down)`));
				}

				// Validate a function actually exists
				if (typeof func_to_run === "undefined") {
					// Ignore
					logger.warn(`Ignoring hotkey ${hotkey_code} of value ${value}, as no function to run exists`);
					res.statusCode = 404;
					res.send("Hotkey function not found");
					return;
				}
			} else {
				func_to_run = fetched_hotkey.func;
			}

			// Execute
			run_hotkey(fetched_hotkey.file, func_to_run);

			res.statusCode = 200;
			res.send("OK");
		} catch (err) {
			next(err); // Hand off to error handler
		}
	});*/

	/**
	 * Handles keyboard path update
	 */
	// TODO: Update this route to use whatever new method for config updates we decide on
	/*router.post("/post/update-keyboard-path", (req, res, next) => {
		const { keyboard, path } = req.body;
		logger.info(`Got update for ${keyboard}, path ${path}`);
		config_loader()
			.then((config) => {
				// Make changes
				config.keyboards[keyboard].path = path;
				// Write
				logger.debug("Writing config...");
				writeFile(CONFIG_FILE, YAML.stringify(config), (err) => {
					if (err) {
						return next(err);
					} else {
						res.statusCode = 200;
						res.send("OK");
					}
					res.end();
				});
			});
	});*/
	return router;
}
ew file mode 100644
ndex 0000000..58072f4
++ b/packages/@twokeys/server/src/routes/triggerHotkey.ts

6d63790946a4779392243e50eae045cca48da867

@github-actions github-actions bot added the todo label Oct 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

0 participants