@@ -4,11 +4,15 @@ import * as path from "path"
44import * as util from "util"
55import { Args } from "./cli"
66import { HttpServer } from "./http"
7+ import { paths } from "./util"
78
89/* eslint-disable @typescript-eslint/no-var-requires */
910
1011export type Activate = ( httpServer : HttpServer , args : Args ) => void
1112
13+ /**
14+ * Plugins must implement this interface.
15+ */
1216export interface Plugin {
1317 activate : Activate
1418}
@@ -23,6 +27,9 @@ require("module")._load = function (request: string, parent: object, isMain: boo
2327 return originalLoad . apply ( this , [ request . replace ( / ^ c o d e - s e r v e r / , path . resolve ( __dirname , "../.." ) ) , parent , isMain ] )
2428}
2529
30+ /**
31+ * Load a plugin and run its activation function.
32+ */
2633const loadPlugin = async ( pluginPath : string , httpServer : HttpServer , args : Args ) : Promise < void > => {
2734 try {
2835 const plugin : Plugin = require ( pluginPath )
@@ -37,24 +44,42 @@ const loadPlugin = async (pluginPath: string, httpServer: HttpServer, args: Args
3744 }
3845}
3946
40- const _loadPlugins = async ( httpServer : HttpServer , args : Args ) : Promise < void > => {
41- const pluginPath = path . resolve ( __dirname , "../../plugins" )
42- const files = await util . promisify ( fs . readdir ) ( pluginPath , {
43- withFileTypes : true ,
44- } )
45- await Promise . all ( files . map ( ( file ) => loadPlugin ( path . join ( pluginPath , file . name ) , httpServer , args ) ) )
46- }
47-
48- export const loadPlugins = async ( httpServer : HttpServer , args : Args ) : Promise < void > => {
47+ /**
48+ * Load all plugins in the specified directory.
49+ */
50+ const _loadPlugins = async ( pluginDir : string , httpServer : HttpServer , args : Args ) : Promise < void > => {
4951 try {
50- await _loadPlugins ( httpServer , args )
52+ const files = await util . promisify ( fs . readdir ) ( pluginDir , {
53+ withFileTypes : true ,
54+ } )
55+ await Promise . all ( files . map ( ( file ) => loadPlugin ( path . join ( pluginDir , file . name ) , httpServer , args ) ) )
5156 } catch ( error ) {
5257 if ( error . code !== "ENOENT" ) {
5358 logger . warn ( error . message )
5459 }
5560 }
61+ }
5662
57- if ( process . env . PLUGIN_DIR ) {
58- await loadPlugin ( process . env . PLUGIN_DIR , httpServer , args )
59- }
63+ /**
64+ * Load all plugins from the `plugins` directory and the directory specified by
65+ * `PLUGIN_DIR`.
66+
67+ * Also load any individual plugins found in `PLUGIN_DIRS` (colon-separated).
68+ * This allows you to test and develop plugins without having to move or symlink
69+ * them into one directory.
70+ */
71+ export const loadPlugins = async ( httpServer : HttpServer , args : Args ) : Promise < void > => {
72+ await Promise . all ( [
73+ // Built-in plugins.
74+ _loadPlugins ( path . resolve ( __dirname , "../../plugins" ) , httpServer , args ) ,
75+ // User-added plugins.
76+ _loadPlugins (
77+ path . resolve ( process . env . PLUGIN_DIR || path . join ( paths . data , "code-server-extensions" ) ) ,
78+ httpServer ,
79+ args ,
80+ ) ,
81+ // For development so you don't have to use symlinks.
82+ process . env . PLUGIN_DIRS &&
83+ ( await Promise . all ( process . env . PLUGIN_DIRS . split ( ":" ) . map ( ( dir ) => loadPlugin ( dir , httpServer , args ) ) ) ) ,
84+ ] )
6085}
0 commit comments