Skip to content
23 changes: 21 additions & 2 deletions src/server/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1577,7 +1577,7 @@ namespace ts.server {
}
}

protected enablePlugin(pluginConfigEntry: PluginImport, searchPaths: string[], pluginConfigOverrides: Map<any> | undefined) {
protected async enablePlugin(pluginConfigEntry: PluginImport, searchPaths: string[], pluginConfigOverrides: Map<any> | undefined) {
Comment thread
rbuckton marked this conversation as resolved.
Outdated
this.projectService.logger.info(`Enabling plugin ${pluginConfigEntry.name} from candidate paths: ${searchPaths.join(",")}`);
if (!pluginConfigEntry.name || parsePackageName(pluginConfigEntry.name).rest) {
this.projectService.logger.info(`Skipped loading plugin ${pluginConfigEntry.name || JSON.stringify(pluginConfigEntry)} because only package name is allowed plugin name`);
Expand All @@ -1589,8 +1589,27 @@ namespace ts.server {
const logError = (message: string) => {
(errorLogs || (errorLogs = [])).push(message);
};
const resolvedModule = firstDefined(searchPaths, searchPath =>

let resolvedModule: any | undefined;
if (this.projectService.host.importServicePlugin) {
for (const searchPath of searchPaths) {
try {
resolvedModule = await this.projectService.host.importServicePlugin(searchPath, pluginConfigEntry.name);
}
catch (e) {
// TODO: log this?
Comment thread
mjbvz marked this conversation as resolved.
Outdated
continue;
}
if (resolvedModule) {
break;
}
}
}
else {
resolvedModule = firstDefined(searchPaths, searchPath =>
Project.resolveModule(pluginConfigEntry.name, searchPath, this.projectService.host, log, logError) as PluginModuleFactory | undefined);
}

if (resolvedModule) {
const configurationOverride = pluginConfigOverrides && pluginConfigOverrides.get(pluginConfigEntry.name);
if (configurationOverride) {
Expand Down
1 change: 0 additions & 1 deletion src/server/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,6 @@ namespace ts.server {
CommandNames.OrganizeImportsFull,
CommandNames.GetEditsForFileRename,
CommandNames.GetEditsForFileRenameFull,
CommandNames.ConfigurePlugin,
CommandNames.PrepareCallHierarchy,
CommandNames.ProvideCallHierarchyIncomingCalls,
CommandNames.ProvideCallHierarchyOutgoingCalls,
Expand Down
1 change: 1 addition & 0 deletions src/server/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ declare namespace ts.server {
gc?(): void;
trace?(s: string): void;
require?(initialPath: string, moduleName: string): RequireResult;
importServicePlugin?(root: string, moduleName: string): Promise<any>;
Comment thread
mjbvz marked this conversation as resolved.
Outdated
}
}
18 changes: 18 additions & 0 deletions src/webServer/webServer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/*@internal*/
/// <reference lib="dom" />

namespace ts.server {
export interface HostWithWriteMessage {
writeMessage(s: any): void;
Expand Down Expand Up @@ -137,6 +139,22 @@ namespace ts.server {
/* eslint-enable no-restricted-globals */

require: () => ({ module: undefined, error: new Error("Not implemented") }),
importServicePlugin: async (root: string, moduleName: string) => {
Comment thread
rbuckton marked this conversation as resolved.
Outdated
const packageRoot = combinePaths(root, "node_modules", moduleName);

const packageJsonResponse = await fetch(combinePaths(packageRoot, "package.json"));
const packageJson = await packageJsonResponse.json();
const browser = packageJson.browser;
Comment thread
rbuckton marked this conversation as resolved.
if (!browser) {
throw new Error("Could not load plugin. No 'browser' field found in package.json.");
}

const scriptPath = combinePaths(packageRoot, browser);

// TODO: TS rewrites `import(...)` to `require`. Use eval to bypass this
// eslint-disable-next-line no-eval
return (await eval(`import(${JSON.stringify(scriptPath)})`)).default;
Comment thread
rbuckton marked this conversation as resolved.
Outdated
},
exit: notImplemented,

// Debugging related
Expand Down