mirror of https://github.com/onivim/oni.git
* Add prettierignore * Add yarn * Hook up yarn script to plugin installer * Initial implementation of plugin installer * Fix lint issues
This commit is contained in:
parent
3e397df022
commit
f4e627007e
|
@ -1,2 +1,3 @@
|
|||
package.json
|
||||
vim/core/oni-plugin-typescript/package.json
|
||||
lib/yarn/*
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
* PluginInstaller.ts
|
||||
*
|
||||
* Responsible for installing, updating, and uninstalling plugins.
|
||||
*/
|
||||
|
||||
import * as fs from "fs"
|
||||
import * as path from "path"
|
||||
|
||||
import { Event, IEvent } from "oni-types"
|
||||
|
||||
// import * as Oni from "oni-api"
|
||||
|
||||
import { getUserConfigFolderPath } from "./../Services/Configuration"
|
||||
// import { IContributions } from "./Api/Capabilities"
|
||||
|
||||
// import { AnonymousPlugin } from "./AnonymousPlugin"
|
||||
// import { Plugin } from "./Plugin"
|
||||
|
||||
import { FileSystem, IFileSystem } from "./../Services/Explorer/ExplorerFileSystem"
|
||||
|
||||
import Process from "./Api/Process"
|
||||
|
||||
import * as Log from "./../Log"
|
||||
|
||||
/**
|
||||
* Plugin identifier:
|
||||
* - For _git_, this should be of the form `welle/targets.vim`
|
||||
* - For _npm_, this should be the name of the module, `oni-plugin-tslint`
|
||||
*/
|
||||
export type PluginIdentifier = string
|
||||
|
||||
export interface IPluginInstallerOperationEvent {
|
||||
type: "install" | "uninstall"
|
||||
identifier: string
|
||||
error?: Error
|
||||
}
|
||||
|
||||
export interface IPluginInstaller {
|
||||
onOperationStarted: IEvent<IPluginInstallerOperationEvent>
|
||||
onOperationCompleted: IEvent<IPluginInstallerOperationEvent>
|
||||
onOperationError: IEvent<IPluginInstallerOperationEvent>
|
||||
|
||||
install(pluginInfo: PluginIdentifier): Promise<void>
|
||||
uninstall(pluginInfo: PluginIdentifier): Promise<void>
|
||||
}
|
||||
|
||||
export class YarnPluginInstaller implements IPluginInstaller {
|
||||
private _onOperationStarted = new Event<IPluginInstallerOperationEvent>()
|
||||
private _onOperationCompleted = new Event<IPluginInstallerOperationEvent>()
|
||||
private _onOperationError = new Event<IPluginInstallerOperationEvent>()
|
||||
|
||||
public get onOperationStarted(): IEvent<IPluginInstallerOperationEvent> {
|
||||
return this._onOperationStarted
|
||||
}
|
||||
|
||||
public get onOperationCompleted(): IEvent<IPluginInstallerOperationEvent> {
|
||||
return this._onOperationCompleted
|
||||
}
|
||||
|
||||
public get onOperationError(): IEvent<IPluginInstallerOperationEvent> {
|
||||
return this._onOperationError
|
||||
}
|
||||
|
||||
constructor(private _fileSystem: IFileSystem = new FileSystem(fs)) {}
|
||||
|
||||
public async install(identifier: string): Promise<void> {
|
||||
const eventInfo: IPluginInstallerOperationEvent = {
|
||||
type: "install",
|
||||
identifier,
|
||||
}
|
||||
|
||||
try {
|
||||
this._onOperationStarted.dispatch(eventInfo)
|
||||
await this._ensurePackageJsonIsCreated()
|
||||
await this._runYarnCommand("add", [identifier])
|
||||
this._onOperationCompleted.dispatch(eventInfo)
|
||||
} catch (ex) {
|
||||
this._onOperationError.dispatch({
|
||||
...eventInfo,
|
||||
error: ex,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public async uninstall(identifier: string): Promise<void> {
|
||||
const eventInfo: IPluginInstallerOperationEvent = {
|
||||
type: "uninstall",
|
||||
identifier,
|
||||
}
|
||||
|
||||
try {
|
||||
this._onOperationStarted.dispatch(eventInfo)
|
||||
await this._runYarnCommand("remove", [identifier])
|
||||
this._onOperationCompleted.dispatch(eventInfo)
|
||||
} catch (ex) {
|
||||
this._onOperationError.dispatch({
|
||||
...eventInfo,
|
||||
error: ex,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private async _ensurePackageJsonIsCreated(): Promise<void> {
|
||||
const packageJsonFile = this._getPackageJsonFile()
|
||||
Log.info(
|
||||
`[YarnPluginInstaller::_ensurePackageJsonIsCreated] - checking file: ${packageJsonFile}`,
|
||||
)
|
||||
|
||||
const doesPackageFileExist = await this._fileSystem.exists(packageJsonFile)
|
||||
|
||||
if (!doesPackageFileExist) {
|
||||
Log.info(
|
||||
`[YarnPluginInstaller::_ensurePackageJsonIsCreated] - package file does not exist, initializing.`,
|
||||
)
|
||||
await this._runYarnCommand("init", ["-y"])
|
||||
Log.info(
|
||||
`[YarnPluginInstaller::_ensurePackageJsonIsCreated] - package file created successfully.`,
|
||||
)
|
||||
} else {
|
||||
Log.info(
|
||||
`[YarnPluginInstaller::_ensurePackageJsonIsCreated] - package file is available.`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private async _runYarnCommand(command: string, args: string[]): Promise<void> {
|
||||
const yarnPath = this._getYarnPath()
|
||||
|
||||
const workingDirectory = getUserConfigFolderPath()
|
||||
const pluginDirectory = this._getPluginsFolder()
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
Process.execNodeScript(
|
||||
yarnPath,
|
||||
["--modules-folder", pluginDirectory, "--production", "true", command, ...args],
|
||||
{ cwd: workingDirectory },
|
||||
(err: any, stdout: string, stderr: string) => {
|
||||
if (err) {
|
||||
Log.error("Error installing: " + stderr)
|
||||
reject(err)
|
||||
return
|
||||
}
|
||||
|
||||
resolve()
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
private _getPackageJsonFile(): string {
|
||||
return path.join(getUserConfigFolderPath(), "package.json")
|
||||
}
|
||||
|
||||
private _getPluginsFolder(): string {
|
||||
return path.join(getUserConfigFolderPath(), "plugins")
|
||||
}
|
||||
|
||||
private _getYarnPath(): string {
|
||||
return path.join(__dirname, "lib", "yarn", "yarn-1.5.1.js")
|
||||
}
|
||||
}
|
|
@ -15,16 +15,23 @@ const extensionsRoot = path.join(__dirname, "extensions")
|
|||
|
||||
import { flatMap } from "./../Utility"
|
||||
|
||||
import { IPluginInstaller, YarnPluginInstaller } from "./PluginInstaller"
|
||||
|
||||
export class PluginManager implements Oni.IPluginManager {
|
||||
private _rootPluginPaths: string[] = []
|
||||
private _plugins: Plugin[] = []
|
||||
private _anonymousPlugin: AnonymousPlugin
|
||||
private _pluginsActivated: boolean = false
|
||||
private _installer: IPluginInstaller = new YarnPluginInstaller()
|
||||
|
||||
public get plugins(): Plugin[] {
|
||||
return this._plugins
|
||||
}
|
||||
|
||||
public get installer(): IPluginInstaller {
|
||||
return this._installer
|
||||
}
|
||||
|
||||
constructor(private _config: Configuration) {}
|
||||
|
||||
public discoverPlugins(): void {
|
||||
|
|
|
@ -14,6 +14,7 @@ import { FolderOrFile } from "./ExplorerStore"
|
|||
*/
|
||||
export interface IFileSystem {
|
||||
readdir(fullPath: string): Promise<FolderOrFile[]>
|
||||
exists(fullPath: string): Promise<boolean>
|
||||
}
|
||||
|
||||
export class FileSystem implements IFileSystem {
|
||||
|
@ -40,4 +41,12 @@ export class FileSystem implements IFileSystem {
|
|||
|
||||
return Promise.resolve(filesAndFolders)
|
||||
}
|
||||
|
||||
public exists(fullPath: string): Promise<boolean> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._fs.exists(fullPath, (exists: boolean) => {
|
||||
resolve(exists)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue