@@ -4,11 +4,15 @@ import * as path from "path"
4
4
import * as util from "util"
5
5
import { Args } from "./cli"
6
6
import { HttpServer } from "./http"
7
+ import { paths } from "./util"
7
8
8
9
/* eslint-disable @typescript-eslint/no-var-requires */
9
10
10
11
export type Activate = ( httpServer : HttpServer , args : Args ) => void
11
12
13
+ /**
14
+ * Plugins must implement this interface.
15
+ */
12
16
export interface Plugin {
13
17
activate : Activate
14
18
}
@@ -23,38 +27,60 @@ require("module")._load = function (request: string, parent: object, isMain: boo
23
27
return originalLoad . apply ( this , [ request . replace ( / ^ c o d e - s e r v e r / , path . resolve ( __dirname , "../.." ) ) , parent , isMain ] )
24
28
}
25
29
30
+ /**
31
+ * Load a plugin and run its activation function.
32
+ */
26
33
const loadPlugin = async ( pluginPath : string , httpServer : HttpServer , args : Args ) : Promise < void > => {
27
34
try {
28
35
const plugin : Plugin = require ( pluginPath )
29
36
plugin . activate ( httpServer , args )
30
- logger . debug ( "Loaded plugin" , field ( "name" , path . basename ( pluginPath ) ) )
37
+
38
+ const packageJson = require ( path . join ( pluginPath , "package.json" ) )
39
+ logger . debug (
40
+ "Loaded plugin" ,
41
+ field ( "name" , packageJson . name || path . basename ( pluginPath ) ) ,
42
+ field ( "path" , pluginPath ) ,
43
+ field ( "version" , packageJson . version || "n/a" ) ,
44
+ )
31
45
} catch ( error ) {
32
- if ( error . code !== "MODULE_NOT_FOUND" ) {
33
- logger . warn ( error . message )
34
- } else {
35
- logger . error ( error . message )
36
- }
46
+ logger . error ( error . message )
37
47
}
38
48
}
39
49
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 > => {
50
+ /**
51
+ * Load all plugins in the specified directory.
52
+ */
53
+ const _loadPlugins = async ( pluginDir : string , httpServer : HttpServer , args : Args ) : Promise < void > => {
49
54
try {
50
- await _loadPlugins ( httpServer , args )
55
+ const files = await util . promisify ( fs . readdir ) ( pluginDir , {
56
+ withFileTypes : true ,
57
+ } )
58
+ await Promise . all ( files . map ( ( file ) => loadPlugin ( path . join ( pluginDir , file . name ) , httpServer , args ) ) )
51
59
} catch ( error ) {
52
60
if ( error . code !== "ENOENT" ) {
53
61
logger . warn ( error . message )
54
62
}
55
63
}
64
+ }
56
65
57
- if ( process . env . PLUGIN_DIR ) {
58
- await loadPlugin ( process . env . PLUGIN_DIR , httpServer , args )
59
- }
66
+ /**
67
+ * Load all plugins from the `plugins` directory, directories specified by
68
+ * `CS_PLUGIN_PATH` (colon-separated), and individual plugins specified by
69
+ * `CS_PLUGIN` (also colon-separated).
70
+ */
71
+ export const loadPlugins = async ( httpServer : HttpServer , args : Args ) : Promise < void > => {
72
+ const pluginPath = process . env . CS_PLUGIN_PATH || `${ path . join ( paths . data , "plugins" ) } :/usr/share/code-server/plugins`
73
+ const plugin = process . env . CS_PLUGIN || ""
74
+ await Promise . all ( [
75
+ // Built-in plugins.
76
+ _loadPlugins ( path . resolve ( __dirname , "../../plugins" ) , httpServer , args ) ,
77
+ // User-added plugins.
78
+ ...pluginPath . split ( ":" ) . map ( ( dir ) => _loadPlugins ( path . resolve ( dir ) , httpServer , args ) ) ,
79
+ // Individual plugins so you don't have to symlink or move them into a
80
+ // directory specifically for plugins. This lets you load plugins that are
81
+ // on the same level as other directories that are not plugins (if you tried
82
+ // to use CS_PLUGIN_PATH code-server would try to load those other
83
+ // directories as plugins). Intended for development.
84
+ ...plugin . split ( ":" ) . map ( ( dir ) => loadPlugin ( path . resolve ( dir ) , httpServer , args ) ) ,
85
+ ] )
60
86
}
0 commit comments