plugins.ts 3.7 KB
Newer Older
E
.  
Eugene Pankov 已提交
1 2
import * as fs from 'fs-promise'
import * as path from 'path'
E
lint  
Eugene Pankov 已提交
3 4
const nodeModule = require('module')
const nodeRequire = (global as any).require
E
.  
Eugene Pankov 已提交
5

E
.  
Eugene Pankov 已提交
6 7
declare function delay (ms: number): Promise<void>

E
.  
Eugene Pankov 已提交
8 9 10 11 12 13 14
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
E
lint  
Eugene Pankov 已提交
15
}
E
.  
Eugene Pankov 已提交
16

E
lint  
Eugene Pankov 已提交
17
nodeRequire.main.paths.map(x => nodeModule.globalPaths.push(normalizePath(x)))
E
.  
Eugene Pankov 已提交
18 19 20 21 22

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

E
wip  
Eugene Pankov 已提交
23
const builtinPluginsPath = path.join(
E
.  
Eugene Pankov 已提交
24
    path.dirname(require('electron').remote.app.getPath('exe')),
E
.  
Eugene Pankov 已提交
25
    (process.platform === 'darwin') ? '../Resources' : 'resources',
E
wip  
Eugene Pankov 已提交
26
    'builtin-plugins',
E
wip  
Eugene Pankov 已提交
27 28 29
)

const userPluginsPath = path.join(
E
.  
Eugene Pankov 已提交
30 31 32
    require('electron').remote.app.getPath('appData'),
    'terminus',
    'plugins',
E
wip  
Eugene Pankov 已提交
33 34 35 36
)

Object.assign(window, { builtinPluginsPath, userPluginsPath })
nodeModule.globalPaths.unshift(builtinPluginsPath)
E
.  
Eugene Pankov 已提交
37
nodeModule.globalPaths.unshift(path.join(userPluginsPath, 'node_modules'))
E
.  
Eugene Pankov 已提交
38 39

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

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

E
wip  
Eugene Pankov 已提交
45
export interface IPluginInfo {
E
.  
Eugene Pankov 已提交
46
    name: string
E
wip  
Eugene Pankov 已提交
47 48 49 50 51 52 53
    description: string
    packageName: string
    isBuiltin: boolean
    version: string
    homepage?: string
    path?: string
    info?: any
E
.  
Eugene Pankov 已提交
54 55
}

E
wip  
Eugene Pankov 已提交
56
export async function findPlugins (): Promise<IPluginInfo[]> {
E
.  
Eugene Pankov 已提交
57
    let paths = nodeModule.globalPaths
E
wip  
Eugene Pankov 已提交
58
    let foundPlugins: IPluginInfo[] = []
E
.  
Eugene Pankov 已提交
59

E
.  
Eugene Pankov 已提交
60
    for (let pluginDir of paths) {
E
.  
Eugene Pankov 已提交
61
        pluginDir = normalizePath(pluginDir)
E
.  
Eugene Pankov 已提交
62 63 64
        if (!await fs.exists(pluginDir)) {
            continue
        }
E
.  
Eugene Pankov 已提交
65
        let pluginNames = await fs.readdir(pluginDir)
E
.  
Eugene Pankov 已提交
66 67 68 69 70 71
        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 已提交
72 73 74 75 76

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

E
.  
Eugene Pankov 已提交
77
            try {
E
wip  
Eugene Pankov 已提交
78 79
                let info = await fs.readJson(infoPath)
                console.log(pluginDir, builtinPluginsPath)
E
.  
Eugene Pankov 已提交
80
                foundPlugins.push({
E
wip  
Eugene Pankov 已提交
81 82 83 84 85
                    name: pluginName.substring('terminus-'.length),
                    packageName: pluginName,
                    isBuiltin: pluginDir === builtinPluginsPath,
                    version: info.version,
                    description: info.description,
E
.  
Eugene Pankov 已提交
86
                    path: pluginPath,
E
wip  
Eugene Pankov 已提交
87
                    info,
E
.  
Eugene Pankov 已提交
88 89 90 91 92
                })
            } catch (error) {
                console.error('Cannot load package info for', pluginName)
            }
        }
E
.  
Eugene Pankov 已提交
93
    }
E
.  
Eugene Pankov 已提交
94

E
wip  
Eugene Pankov 已提交
95
    (window as any).installedPlugins = foundPlugins
E
.  
Eugene Pankov 已提交
96 97 98
    return foundPlugins
}

E
wip  
Eugene Pankov 已提交
99
export async function loadPlugins (foundPlugins: IPluginInfo[], progress: ProgressCallback): Promise<any[]> {
E
.  
Eugene Pankov 已提交
100 101
    let plugins: any[] = []
    progress(0, 1)
E
.  
Eugene Pankov 已提交
102 103
    let index = 0
    for (let foundPlugin of foundPlugins) {
E
lint  
Eugene Pankov 已提交
104
        console.info(`Loading ${foundPlugin.name}: ${nodeRequire.resolve(foundPlugin.path)}`)
E
.  
Eugene Pankov 已提交
105 106
        progress(index, foundPlugins.length)
        try {
E
lint  
Eugene Pankov 已提交
107
            let pluginModule = nodeRequire(foundPlugin.path)
E
.  
Eugene Pankov 已提交
108 109 110 111
            plugins.push(pluginModule)
        } catch (error) {
            console.error(`Could not load ${foundPlugin.name}:`, error)
        }
E
.  
Eugene Pankov 已提交
112 113 114
        await delay(1)
        index++
    }
E
.  
Eugene Pankov 已提交
115
    progress(1, 1)
E
.  
Eugene Pankov 已提交
116 117
    return plugins
}