mirror of https://github.com/coder/code-server.git
plugin.ts: Adjust to implement pluginapi.d.ts correctly
This commit is contained in:
parent
fed545e67d
commit
afff86ae9c
|
@ -10,11 +10,11 @@ const fsp = fs.promises
|
||||||
|
|
||||||
interface Plugin extends pluginapi.Plugin {
|
interface Plugin extends pluginapi.Plugin {
|
||||||
/**
|
/**
|
||||||
* These fields are populated from the plugin's package.json.
|
* These fields are populated from the plugin's package.json
|
||||||
|
* and now guaranteed to exist.
|
||||||
*/
|
*/
|
||||||
name: string
|
name: string
|
||||||
version: string
|
version: string
|
||||||
description: string
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* path to the node module on the disk.
|
* path to the node module on the disk.
|
||||||
|
@ -34,7 +34,7 @@ interface Application extends pluginapi.Application {
|
||||||
* Please see that file for details.
|
* Please see that file for details.
|
||||||
*/
|
*/
|
||||||
export class PluginAPI {
|
export class PluginAPI {
|
||||||
private readonly plugins = new Array<Plugin>()
|
private readonly plugins = new Map<string, Plugin>()
|
||||||
private readonly logger: Logger
|
private readonly logger: Logger
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
|
@ -54,7 +54,7 @@ export class PluginAPI {
|
||||||
*/
|
*/
|
||||||
public async applications(): Promise<Application[]> {
|
public async applications(): Promise<Application[]> {
|
||||||
const apps = new Array<Application>()
|
const apps = new Array<Application>()
|
||||||
for (const p of this.plugins) {
|
for (const [_, p] of this.plugins) {
|
||||||
const pluginApps = await p.applications()
|
const pluginApps = await p.applications()
|
||||||
|
|
||||||
// Add plugin key to each app.
|
// Add plugin key to each app.
|
||||||
|
@ -65,8 +65,11 @@ export class PluginAPI {
|
||||||
plugin: {
|
plugin: {
|
||||||
name: p.name,
|
name: p.name,
|
||||||
version: p.version,
|
version: p.version,
|
||||||
description: p.description,
|
|
||||||
modulePath: p.modulePath,
|
modulePath: p.modulePath,
|
||||||
|
|
||||||
|
displayName: p.displayName,
|
||||||
|
description: p.description,
|
||||||
|
path: p.path,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
@ -79,7 +82,7 @@ export class PluginAPI {
|
||||||
* mount mounts all plugin routers onto r.
|
* mount mounts all plugin routers onto r.
|
||||||
*/
|
*/
|
||||||
public mount(r: express.Router): void {
|
public mount(r: express.Router): void {
|
||||||
for (const p of this.plugins) {
|
for (const [_, p] of this.plugins) {
|
||||||
r.use(`/${p.name}`, p.router())
|
r.use(`/${p.name}`, p.router())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,7 +132,7 @@ export class PluginAPI {
|
||||||
encoding: "utf8",
|
encoding: "utf8",
|
||||||
})
|
})
|
||||||
const packageJSON: PackageJSON = JSON.parse(str)
|
const packageJSON: PackageJSON = JSON.parse(str)
|
||||||
for (const p of this.plugins) {
|
for (const [_, p] of this.plugins) {
|
||||||
if (p.name === packageJSON.name) {
|
if (p.name === packageJSON.name) {
|
||||||
this.logger.warn(
|
this.logger.warn(
|
||||||
`ignoring duplicate plugin ${q(p.name)} at ${q(dir)}, using previously loaded ${q(p.modulePath)}`,
|
`ignoring duplicate plugin ${q(p.name)} at ${q(dir)}, using previously loaded ${q(p.modulePath)}`,
|
||||||
|
@ -138,7 +141,7 @@ export class PluginAPI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const p = this._loadPlugin(dir, packageJSON)
|
const p = this._loadPlugin(dir, packageJSON)
|
||||||
this.plugins.push(p)
|
this.plugins.set(p.name, p)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.code !== "ENOENT") {
|
if (err.code !== "ENOENT") {
|
||||||
this.logger.warn(`failed to load plugin: ${err.message}`)
|
this.logger.warn(`failed to load plugin: ${err.message}`)
|
||||||
|
@ -147,6 +150,8 @@ export class PluginAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _loadPlugin(dir: string, packageJSON: PackageJSON): Plugin {
|
private _loadPlugin(dir: string, packageJSON: PackageJSON): Plugin {
|
||||||
|
dir = path.resolve(dir)
|
||||||
|
|
||||||
const logger = this.logger.named(packageJSON.name)
|
const logger = this.logger.named(packageJSON.name)
|
||||||
logger.debug("loading plugin", field("plugin_dir", dir), field("package_json", packageJSON))
|
logger.debug("loading plugin", field("plugin_dir", dir), field("package_json", packageJSON))
|
||||||
|
|
||||||
|
@ -165,11 +170,20 @@ export class PluginAPI {
|
||||||
const p = {
|
const p = {
|
||||||
name: packageJSON.name,
|
name: packageJSON.name,
|
||||||
version: packageJSON.version,
|
version: packageJSON.version,
|
||||||
description: packageJSON.description,
|
|
||||||
modulePath: dir,
|
modulePath: dir,
|
||||||
...require(dir),
|
...require(dir),
|
||||||
} as Plugin
|
} as Plugin
|
||||||
|
|
||||||
|
if (!p.displayName) {
|
||||||
|
throw new Error("plugin missing displayName")
|
||||||
|
}
|
||||||
|
if (!p.description) {
|
||||||
|
throw new Error("plugin missing description")
|
||||||
|
}
|
||||||
|
if (!p.path) {
|
||||||
|
throw new Error("plugin missing path")
|
||||||
|
}
|
||||||
|
|
||||||
p.init({
|
p.init({
|
||||||
logger: logger,
|
logger: logger,
|
||||||
})
|
})
|
||||||
|
@ -183,7 +197,6 @@ export class PluginAPI {
|
||||||
interface PackageJSON {
|
interface PackageJSON {
|
||||||
name: string
|
name: string
|
||||||
version: string
|
version: string
|
||||||
description: string
|
|
||||||
engines: {
|
engines: {
|
||||||
"code-server": string
|
"code-server": string
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,14 +17,20 @@ describe("plugin", () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
name: "goland",
|
name: "test app",
|
||||||
version: "4.0.0",
|
version: "4.0.0",
|
||||||
|
|
||||||
|
description: "my description",
|
||||||
iconPath: "/icon.svg",
|
iconPath: "/icon.svg",
|
||||||
|
|
||||||
plugin: {
|
plugin: {
|
||||||
name: "test-plugin",
|
name: "test-plugin",
|
||||||
version: "1.0.0",
|
version: "1.0.0",
|
||||||
description: "Fake plugin for testing code-server's plugin API",
|
|
||||||
modulePath: path.join(__dirname, "test-plugin"),
|
modulePath: path.join(__dirname, "test-plugin"),
|
||||||
|
|
||||||
|
description: "Plugin used in code-server tests.",
|
||||||
|
displayName: "Test Plugin",
|
||||||
|
path: "/test-plugin",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "test-plugin",
|
"name": "test-plugin",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "Fake plugin for testing code-server's plugin API",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"code-server": "^3.6.0"
|
"code-server": "^3.6.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import * as express from "express"
|
import * as express from "express"
|
||||||
import * as path from "path"
|
import * as fspath from "path"
|
||||||
import * as pluginapi from "../../../typings/pluginapi"
|
import * as pluginapi from "../../../typings/pluginapi"
|
||||||
|
|
||||||
|
export const displayName = "Test Plugin"
|
||||||
|
export const path = "/test-plugin"
|
||||||
|
export const description = "Plugin used in code-server tests."
|
||||||
|
|
||||||
export function init(config: pluginapi.PluginConfig) {
|
export function init(config: pluginapi.PluginConfig) {
|
||||||
config.logger.debug("test-plugin loaded!")
|
config.logger.debug("test-plugin loaded!")
|
||||||
}
|
}
|
||||||
|
@ -9,7 +13,7 @@ export function init(config: pluginapi.PluginConfig) {
|
||||||
export function router(): express.Router {
|
export function router(): express.Router {
|
||||||
const r = express.Router()
|
const r = express.Router()
|
||||||
r.get("/goland/icon.svg", (req, res) => {
|
r.get("/goland/icon.svg", (req, res) => {
|
||||||
res.sendFile(path.resolve(__dirname, "../public/icon.svg"))
|
res.sendFile(fspath.resolve(__dirname, "../public/icon.svg"))
|
||||||
})
|
})
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
@ -17,9 +21,11 @@ export function router(): express.Router {
|
||||||
export function applications(): pluginapi.Application[] {
|
export function applications(): pluginapi.Application[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: "goland",
|
name: "test app",
|
||||||
version: "4.0.0",
|
version: "4.0.0",
|
||||||
iconPath: "/icon.svg",
|
iconPath: "/icon.svg",
|
||||||
|
|
||||||
|
description: "my description",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
"tsBuildInfoFile": "./.cache/tsbuildinfo",
|
"tsBuildInfoFile": "./.cache/tsbuildinfo",
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"rootDir": "./src",
|
"rootDir": "./src",
|
||||||
"typeRoots": ["./node_modules/@types", "./typings"]
|
"typeRoots": ["./node_modules/@types", "./typings"],
|
||||||
|
"downlevelIteration": true
|
||||||
},
|
},
|
||||||
"include": ["./src/**/*.ts"]
|
"include": ["./src/**/*.ts"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,9 +70,14 @@ export interface Plugin {
|
||||||
version?: string
|
version?: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These two are used in the overlay.
|
* Name used in the overlay.
|
||||||
*/
|
*/
|
||||||
displayName: string
|
displayName: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in overlay.
|
||||||
|
* Should be a full sentence describing the plugin.
|
||||||
|
*/
|
||||||
description: string
|
description: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue