Merge pull request #2147 from cdr/multi-plugin
This commit is contained in:
commit
c6c293d53a
|
@ -4,11 +4,15 @@ import * as path from "path"
|
||||||
import * as util from "util"
|
import * as util from "util"
|
||||||
import { Args } from "./cli"
|
import { Args } from "./cli"
|
||||||
import { HttpServer } from "./http"
|
import { HttpServer } from "./http"
|
||||||
|
import { paths } from "./util"
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
|
|
||||||
export type Activate = (httpServer: HttpServer, args: Args) => void
|
export type Activate = (httpServer: HttpServer, args: Args) => void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugins must implement this interface.
|
||||||
|
*/
|
||||||
export interface Plugin {
|
export interface Plugin {
|
||||||
activate: Activate
|
activate: Activate
|
||||||
}
|
}
|
||||||
|
@ -23,38 +27,60 @@ require("module")._load = function (request: string, parent: object, isMain: boo
|
||||||
return originalLoad.apply(this, [request.replace(/^code-server/, path.resolve(__dirname, "../..")), parent, isMain])
|
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<void> => {
|
const loadPlugin = async (pluginPath: string, httpServer: HttpServer, args: Args): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const plugin: Plugin = require(pluginPath)
|
const plugin: Plugin = require(pluginPath)
|
||||||
plugin.activate(httpServer, args)
|
plugin.activate(httpServer, args)
|
||||||
logger.debug("Loaded plugin", field("name", path.basename(pluginPath)))
|
|
||||||
|
const packageJson = require(path.join(pluginPath, "package.json"))
|
||||||
|
logger.debug(
|
||||||
|
"Loaded plugin",
|
||||||
|
field("name", packageJson.name || path.basename(pluginPath)),
|
||||||
|
field("path", pluginPath),
|
||||||
|
field("version", packageJson.version || "n/a"),
|
||||||
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code !== "MODULE_NOT_FOUND") {
|
|
||||||
logger.warn(error.message)
|
|
||||||
} else {
|
|
||||||
logger.error(error.message)
|
logger.error(error.message)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const _loadPlugins = async (httpServer: HttpServer, args: Args): Promise<void> => {
|
/**
|
||||||
const pluginPath = path.resolve(__dirname, "../../plugins")
|
* Load all plugins in the specified directory.
|
||||||
const files = await util.promisify(fs.readdir)(pluginPath, {
|
*/
|
||||||
|
const _loadPlugins = async (pluginDir: string, httpServer: HttpServer, args: Args): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const files = await util.promisify(fs.readdir)(pluginDir, {
|
||||||
withFileTypes: true,
|
withFileTypes: true,
|
||||||
})
|
})
|
||||||
await Promise.all(files.map((file) => loadPlugin(path.join(pluginPath, file.name), httpServer, args)))
|
await Promise.all(files.map((file) => loadPlugin(path.join(pluginDir, file.name), httpServer, args)))
|
||||||
}
|
|
||||||
|
|
||||||
export const loadPlugins = async (httpServer: HttpServer, args: Args): Promise<void> => {
|
|
||||||
try {
|
|
||||||
await _loadPlugins(httpServer, args)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code !== "ENOENT") {
|
if (error.code !== "ENOENT") {
|
||||||
logger.warn(error.message)
|
logger.warn(error.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (process.env.PLUGIN_DIR) {
|
|
||||||
await loadPlugin(process.env.PLUGIN_DIR, httpServer, args)
|
/**
|
||||||
}
|
* 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<void> => {
|
||||||
|
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.
|
||||||
|
_loadPlugins(path.resolve(__dirname, "../../plugins"), httpServer, args),
|
||||||
|
// User-added plugins.
|
||||||
|
...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)),
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue