plugins.ts 2.9 KB
Newer Older
E
.  
Eugene Pankov 已提交
1 2
import * as fs from 'fs-promise'
import * as path from 'path'
E
.  
Eugene Pankov 已提交
3 4 5 6 7 8 9 10 11 12 13 14
const nodeModule = (<any>global).require('module')

function normalizePath (path: string): string {
    const cygwinPrefix = '/cygdrive/'
    if (path.startsWith(cygwinPrefix)) {
        path = path.substring(cygwinPrefix.length).replace('/', '\\')
        path = path[0] + ':' + path.substring(1)
    }
    return path
};

(<any>global).require.main.paths.map(x => nodeModule.globalPaths.push(normalizePath(x)))
E
.  
Eugene Pankov 已提交
15 16 17 18 19 20 21 22 23 24 25 26 27 28

if (process.env.DEV) {
    nodeModule.globalPaths.unshift(path.dirname(require('electron').remote.app.getAppPath()))
}

nodeModule.globalPaths.unshift(path.join(
    path.dirname(require('electron').remote.app.getPath('exe')),
    'resources/builtin-plugins/node_modules',
))
nodeModule.globalPaths.unshift(path.join(
    require('electron').remote.app.getPath('appData'),
    'terminus',
    'plugins',
))
E
.  
Eugene Pankov 已提交
29 30

if (process.env.TERMINUS_PLUGINS) {
E
.  
Eugene Pankov 已提交
31
    process.env.TERMINUS_PLUGINS.split(':').map(x => nodeModule.globalPaths.unshift(normalizePath(x)))
E
.  
Eugene Pankov 已提交
32 33
}

E
.  
Eugene Pankov 已提交
34 35
export declare type ProgressCallback = (current, total) => void

E
.  
Eugene Pankov 已提交
36
interface IPluginEntry {
E
.  
Eugene Pankov 已提交
37 38
    name: string
    path: string
E
.  
Eugene Pankov 已提交
39
    info: any
E
.  
Eugene Pankov 已提交
40 41
}

E
.  
Eugene Pankov 已提交
42
export async function findPlugins (): Promise<IPluginEntry[]> {
E
.  
Eugene Pankov 已提交
43
    let paths = nodeModule.globalPaths
E
.  
Eugene Pankov 已提交
44
    let foundPlugins: IPluginEntry[] = []
E
.  
Eugene Pankov 已提交
45

E
.  
Eugene Pankov 已提交
46
    for (let pluginDir of paths) {
E
.  
Eugene Pankov 已提交
47
        pluginDir = normalizePath(pluginDir)
E
.  
Eugene Pankov 已提交
48 49 50
        if (!await fs.exists(pluginDir)) {
            continue
        }
E
.  
Eugene Pankov 已提交
51
        let pluginNames = await fs.readdir(pluginDir)
E
.  
Eugene Pankov 已提交
52 53 54 55 56 57
        for (let pluginName of pluginNames.filter(x => /^terminus-/.exec(x))) {
            let pluginPath = path.join(pluginDir, pluginName)
            let infoPath = path.join(pluginPath, 'package.json')
            if (!await fs.exists(infoPath)) {
                continue
            }
E
.  
Eugene Pankov 已提交
58 59 60 61 62

            if (foundPlugins.some(x => x.name === pluginName)) {
                console.info(`Plugin ${pluginName} already exists`)
            }

E
.  
Eugene Pankov 已提交
63 64 65 66 67 68 69 70 71 72
            try {
                foundPlugins.push({
                    name: pluginName,
                    path: pluginPath,
                    info: await fs.readJson(infoPath),
                })
            } catch (error) {
                console.error('Cannot load package info for', pluginName)
            }
        }
E
.  
Eugene Pankov 已提交
73
    }
E
.  
Eugene Pankov 已提交
74 75 76 77

    return foundPlugins
}

E
.  
Eugene Pankov 已提交
78
export async function loadPlugins (foundPlugins: IPluginEntry[], progress: ProgressCallback): Promise<any[]> {
E
.  
Eugene Pankov 已提交
79 80
    let plugins: any[] = []
    progress(0, 1)
E
.  
Eugene Pankov 已提交
81 82
    let index = 0
    for (let foundPlugin of foundPlugins) {
E
.  
Eugene Pankov 已提交
83 84 85 86 87 88 89 90
        console.info(`Loading ${foundPlugin.name}: ${(<any>global).require.resolve(foundPlugin.path)}`)
        progress(index, foundPlugins.length)
        try {
            let pluginModule = (<any>global).require(foundPlugin.path)
            plugins.push(pluginModule)
        } catch (error) {
            console.error(`Could not load ${foundPlugin.name}:`, error)
        }
E
.  
Eugene Pankov 已提交
91 92 93
        await delay(1)
        index++
    }
E
.  
Eugene Pankov 已提交
94
    progress(1, 1)
E
.  
Eugene Pankov 已提交
95 96
    return plugins
}