From e64b186527a7a0a2585fe5cd3aefb5de5f1b90dc Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 30 Sep 2020 15:22:54 -0500 Subject: [PATCH 1/6] Add variables to better customize plugin directories --- src/node/plugin.ts | 53 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/node/plugin.ts b/src/node/plugin.ts index 54f7f2b76..d1d71518e 100644 --- a/src/node/plugin.ts +++ b/src/node/plugin.ts @@ -4,11 +4,15 @@ import * as path from "path" import * as util from "util" import { Args } from "./cli" import { HttpServer } from "./http" +import { paths } from "./util" /* eslint-disable @typescript-eslint/no-var-requires */ export type Activate = (httpServer: HttpServer, args: Args) => void +/** + * Plugins must implement this interface. + */ export interface Plugin { activate: Activate } @@ -23,6 +27,9 @@ require("module")._load = function (request: string, parent: object, isMain: boo return originalLoad.apply(this, [request.replace(/^code-server/, path.resolve(__dirname, "../..")), parent, isMain]) } +/** + * Load a plugin and run its activation function. + */ const loadPlugin = async (pluginPath: string, httpServer: HttpServer, args: Args): Promise => { try { const plugin: Plugin = require(pluginPath) @@ -37,24 +44,42 @@ const loadPlugin = async (pluginPath: string, httpServer: HttpServer, args: Args } } -const _loadPlugins = async (httpServer: HttpServer, args: Args): Promise => { - const pluginPath = path.resolve(__dirname, "../../plugins") - const files = await util.promisify(fs.readdir)(pluginPath, { - withFileTypes: true, - }) - await Promise.all(files.map((file) => loadPlugin(path.join(pluginPath, file.name), httpServer, args))) -} - -export const loadPlugins = async (httpServer: HttpServer, args: Args): Promise => { +/** + * Load all plugins in the specified directory. + */ +const _loadPlugins = async (pluginDir: string, httpServer: HttpServer, args: Args): Promise => { try { - await _loadPlugins(httpServer, args) + const files = await util.promisify(fs.readdir)(pluginDir, { + withFileTypes: true, + }) + await Promise.all(files.map((file) => loadPlugin(path.join(pluginDir, file.name), httpServer, args))) } catch (error) { if (error.code !== "ENOENT") { logger.warn(error.message) } } - - if (process.env.PLUGIN_DIR) { - await loadPlugin(process.env.PLUGIN_DIR, httpServer, args) - } +} + +/** + * Load all plugins from the `plugins` directory and the directory specified by + * `PLUGIN_DIR`. + + * Also load any individual plugins found in `PLUGIN_DIRS` (colon-separated). + * This allows you to test and develop plugins without having to move or symlink + * them into one directory. + */ +export const loadPlugins = async (httpServer: HttpServer, args: Args): Promise => { + await Promise.all([ + // Built-in plugins. + _loadPlugins(path.resolve(__dirname, "../../plugins"), httpServer, args), + // User-added plugins. + _loadPlugins( + path.resolve(process.env.PLUGIN_DIR || path.join(paths.data, "code-server-extensions")), + httpServer, + args, + ), + // For development so you don't have to use symlinks. + process.env.PLUGIN_DIRS && + (await Promise.all(process.env.PLUGIN_DIRS.split(":").map((dir) => loadPlugin(dir, httpServer, args)))), + ]) } From 7a982555a837f8eab064c89414c24b13ef33d1b3 Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 30 Sep 2020 15:43:43 -0500 Subject: [PATCH 2/6] Add version to plugin load log --- src/node/plugin.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/node/plugin.ts b/src/node/plugin.ts index d1d71518e..299862191 100644 --- a/src/node/plugin.ts +++ b/src/node/plugin.ts @@ -34,7 +34,12 @@ const loadPlugin = async (pluginPath: string, httpServer: HttpServer, args: Args try { const plugin: Plugin = require(pluginPath) plugin.activate(httpServer, args) - logger.debug("Loaded plugin", field("name", path.basename(pluginPath))) + + logger.debug( + "Loaded plugin", + field("name", path.basename(pluginPath)), + field("version", require(path.join(pluginPath, "package.json")).version || "n/a"), + ) } catch (error) { if (error.code !== "MODULE_NOT_FOUND") { logger.warn(error.message) From ddda280df4ed90519a675b85e2854dc7d6c6d8e6 Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 7 Oct 2020 12:13:12 -0500 Subject: [PATCH 3/6] Rename plugin vars and make both colon-separated Only one was colon separated but now they both are. --- src/node/plugin.ts | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/node/plugin.ts b/src/node/plugin.ts index 299862191..5a8d777cd 100644 --- a/src/node/plugin.ts +++ b/src/node/plugin.ts @@ -66,25 +66,23 @@ const _loadPlugins = async (pluginDir: string, httpServer: HttpServer, args: Arg } /** - * Load all plugins from the `plugins` directory and the directory specified by - * `PLUGIN_DIR`. - - * Also load any individual plugins found in `PLUGIN_DIRS` (colon-separated). - * This allows you to test and develop plugins without having to move or symlink - * them into one directory. + * Load all plugins from the `plugins` directory, directories specified by + * `CS_PLUGIN_PATH` (colon-separated), and individual plugins specified by + * `CS_PLUGIN` (also colon-separated). */ export const loadPlugins = async (httpServer: HttpServer, args: Args): Promise => { + const pluginPath = process.env.CS_PLUGIN_PATH || `${path.join(paths.data, "plugins")}:/etc/code-server/plugins` + const plugin = process.env.CS_PLUGIN || "" await Promise.all([ // Built-in plugins. _loadPlugins(path.resolve(__dirname, "../../plugins"), httpServer, args), // User-added plugins. - _loadPlugins( - path.resolve(process.env.PLUGIN_DIR || path.join(paths.data, "code-server-extensions")), - httpServer, - args, - ), - // For development so you don't have to use symlinks. - process.env.PLUGIN_DIRS && - (await Promise.all(process.env.PLUGIN_DIRS.split(":").map((dir) => loadPlugin(dir, httpServer, args)))), + ...pluginPath.split(":").map((dir) => _loadPlugins(path.resolve(dir), httpServer, args)), + // Individual plugins so you don't have to symlink or move them into a + // directory specifically for plugins. This lets you load plugins that are + // on the same level as other directories that are not plugins (if you tried + // to use CS_PLUGIN_PATH code-server would try to load those other + // directories as plugins). Intended for development. + ...plugin.split(":").map((dir) => loadPlugin(path.resolve(dir), httpServer, args)), ]) } From c2ac126a501622947d8c644a6a2bb1e8c751a017 Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 7 Oct 2020 12:25:23 -0500 Subject: [PATCH 4/6] Log all plugin errors as errors --- src/node/plugin.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/node/plugin.ts b/src/node/plugin.ts index 5a8d777cd..2860763ad 100644 --- a/src/node/plugin.ts +++ b/src/node/plugin.ts @@ -41,11 +41,7 @@ const loadPlugin = async (pluginPath: string, httpServer: HttpServer, args: Args field("version", require(path.join(pluginPath, "package.json")).version || "n/a"), ) } catch (error) { - if (error.code !== "MODULE_NOT_FOUND") { - logger.warn(error.message) - } else { - logger.error(error.message) - } + logger.error(error.message) } } From a44b4455f5f633bfaa66882d1e71777105c38134 Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 7 Oct 2020 12:54:40 -0500 Subject: [PATCH 5/6] Read plugin name from package.json --- src/node/plugin.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/node/plugin.ts b/src/node/plugin.ts index 2860763ad..bd3765b6a 100644 --- a/src/node/plugin.ts +++ b/src/node/plugin.ts @@ -35,10 +35,12 @@ const loadPlugin = async (pluginPath: string, httpServer: HttpServer, args: Args const plugin: Plugin = require(pluginPath) plugin.activate(httpServer, args) + const packageJson = require(path.join(pluginPath, "package.json")) logger.debug( "Loaded plugin", - field("name", path.basename(pluginPath)), - field("version", require(path.join(pluginPath, "package.json")).version || "n/a"), + field("name", packageJson.name || path.basename(pluginPath)), + field("path", pluginPath), + field("version", packageJson.version || "n/a"), ) } catch (error) { logger.error(error.message) From c86d7398abdace6a593853e9accdbf66aab04ec2 Mon Sep 17 00:00:00 2001 From: Asher Date: Thu, 8 Oct 2020 16:18:00 -0500 Subject: [PATCH 6/6] Use system data directory for plugins --- src/node/plugin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node/plugin.ts b/src/node/plugin.ts index bd3765b6a..e17a9909c 100644 --- a/src/node/plugin.ts +++ b/src/node/plugin.ts @@ -69,7 +69,7 @@ const _loadPlugins = async (pluginDir: string, httpServer: HttpServer, args: Arg * `CS_PLUGIN` (also colon-separated). */ export const loadPlugins = async (httpServer: HttpServer, args: Args): Promise => { - const pluginPath = process.env.CS_PLUGIN_PATH || `${path.join(paths.data, "plugins")}:/etc/code-server/plugins` + const pluginPath = process.env.CS_PLUGIN_PATH || `${path.join(paths.data, "plugins")}:/usr/share/code-server/plugins` const plugin = process.env.CS_PLUGIN || "" await Promise.all([ // Built-in plugins.