Skip to content

Commit

Permalink
Implement plugin loading
Browse files Browse the repository at this point in the history
  • Loading branch information
ShishKabab committed Apr 5, 2020
1 parent 82ed2b9 commit 1140866
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 7 deletions.
7 changes: 7 additions & 0 deletions ts/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ import { TypeORMStorageBackend } from "@worldbrain/storex-backend-typeorm";
import { Application, ApplicationOptions } from "./application";
import { BcryptAccessTokenManager } from "./access-tokens";
import { createHttpServer } from "./server";
import { PluginManager } from './plugins/manager';

export async function main() {
const application = await setupApplication()
await startServer(application)

const storage = await application.storage
const pluginManager = new PluginManager({
pluginManagementStorage: storage.systemModules.plugins,
})
await pluginManager.setup(() => application.api())
}

export async function setupApplication() {
Expand Down
4 changes: 2 additions & 2 deletions ts/plugins/discovery/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ function validatePluginInfo(untrusted: any): PluginInfo | null {
async function main() {
const args = parseArgs()
const pluginDirGlob = args.pluginGlobPattern.replace('<node_modules>', NODE_MODULES_DIR)
const pluginDirs = await fastGlob([pluginDirGlob], {
const pluginDirs = (await fastGlob([pluginDirGlob], {
onlyDirectories: true
})
})).map(dir => path.resolve(dir))

const application = await setupApplication()
const storage = await application.storage
Expand Down
53 changes: 53 additions & 0 deletions ts/plugins/manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { PluginManagementStorage } from "./storage";
import { PluginInfo, PluginEntryFunction, PluginInterface } from "./types";
import { StorexHubApi_v0 } from "../public-api";

export class PluginManager {
constructor(private options: {
pluginManagementStorage: PluginManagementStorage
}) {

}

async setup(createAPI: () => Promise<StorexHubApi_v0>) {
const enabledPlugins = await this.options.pluginManagementStorage.getInfoForEnabledPlugins()
for (const pluginInfo of enabledPlugins) {
(async () => {
const plugin = await this._loadPlugin(pluginInfo, createAPI)
if (!plugin) {
return
}

await plugin.start()
})()
}
}

async _loadPlugin(pluginInfo: PluginInfo, createAPI: () => Promise<StorexHubApi_v0>): Promise<PluginInterface | null> {
let pluginModule: any
try {
pluginModule = require(pluginInfo.mainPath)
} catch (e) {
console.error(`ERROR - Could not require plugin ${pluginInfo.identifier} at path ${pluginInfo.mainPath}:`)
console.error(e)
return null
}

const entryFunction: PluginEntryFunction = pluginModule[pluginInfo.entryFunction]
if (!entryFunction) {
console.error(`ERROR - Could not find entry function '${pluginInfo.entryFunction}' in plugin ${pluginInfo.identifier}`)
return null
}

let plugin: PluginInterface
try {
plugin = await entryFunction({ api: await createAPI() })
} catch (e) {
console.error(`ERROR during initialization plugin '${pluginInfo.identifier}':`)
console.error(e)
return null
}

return plugin
}
}
9 changes: 7 additions & 2 deletions ts/plugins/storage/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as path from 'path'
import { StorageModule, StorageModuleConfig } from "@worldbrain/storex-pattern-modules";
import STORAGE_VERSIONS from "../../storage/versions";
import { PluginInfo } from "../types";
Expand Down Expand Up @@ -45,11 +46,15 @@ export class PluginManagementStorage extends StorageModule {
}

async getPluginInfoByIdentifier(identifier: string) {
return (this.operation('findPluginByIdentifier', { identifier })) || null
return ((await this.operation('findPluginByIdentifier', { identifier })) || null)?.info
}

async getInfoForEnabledPlugins(): Promise<PluginInfo[]> {
return this.operation('getEnabledPlugins', {})
const records: any[] = (await this.operation('getEnabledPlugins', {}))
return records.map(record => ({
...record.info,
mainPath: path.join(record.path, record.info.mainPath)
}))
}

_getNow = () => Date.now()
Expand Down
8 changes: 6 additions & 2 deletions ts/plugins/test-plugins/one/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { StorexHubApi_v0 } from "../../../public-api";
import { PluginEntryFunction } from "../../types";

export async function main(input: { api: StorexHubApi_v0 }) {

export const main: PluginEntryFunction = async (input: { api: StorexHubApi_v0 }) => {
return {
start: async () => { console.log('starting plugin!') },
stop: async () => { console.log('stopping plugin!') }
}
}
2 changes: 1 addition & 1 deletion ts/plugins/test-plugins/one/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"description": "My description",
"siteUrl": "https://test.io/storex-hub",
"apps": [],
"mainPath": "main.ts",
"mainPath": "main",
"entryFunction": "main"
}
}
9 changes: 9 additions & 0 deletions ts/plugins/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { StorexHubApi_v0 } from "../public-api";

export interface PluginInfo {
identifier: string
version: string
Expand All @@ -7,3 +9,10 @@ export interface PluginInfo {
mainPath: string
entryFunction: string
}

export interface PluginInterface {
start(): Promise<void>
stop(): Promise<void>
}

export type PluginEntryFunction = (input: { api: StorexHubApi_v0 }) => Promise<PluginInterface>

0 comments on commit 1140866

Please sign in to comment.