mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-03 17:59:37 +02:00
WIP plugins: plugin settings on server side
This commit is contained in:
parent
ffb321bedc
commit
ad91e7006e
20 changed files with 419 additions and 61 deletions
|
@ -1,6 +1,5 @@
|
|||
import { PluginModel } from '../../models/server/plugin'
|
||||
import { logger } from '../../helpers/logger'
|
||||
import { RegisterHookOptions } from '../../../shared/models/plugins/register.model'
|
||||
import { basename, join } from 'path'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
import { isLibraryCodeValid, isPackageJSONValid } from '../../helpers/custom-validators/plugins'
|
||||
|
@ -11,7 +10,9 @@ import { PLUGIN_GLOBAL_CSS_PATH } from '../../initializers/constants'
|
|||
import { PluginType } from '../../../shared/models/plugins/plugin.type'
|
||||
import { installNpmPlugin, installNpmPluginFromDisk, removeNpmPlugin } from './yarn'
|
||||
import { outputFile } from 'fs-extra'
|
||||
import { ServerConfigPlugin } from '../../../shared/models/server'
|
||||
import { RegisterSettingOptions } from '../../../shared/models/plugins/register-setting.model'
|
||||
import { RegisterHookOptions } from '../../../shared/models/plugins/register-hook.model'
|
||||
import { PluginSettingsManager } from '../../../shared/models/plugins/plugin-settings-manager.model'
|
||||
|
||||
export interface RegisteredPlugin {
|
||||
name: string
|
||||
|
@ -43,26 +44,13 @@ export class PluginManager {
|
|||
private static instance: PluginManager
|
||||
|
||||
private registeredPlugins: { [ name: string ]: RegisteredPlugin } = {}
|
||||
private settings: { [ name: string ]: RegisterSettingOptions[] } = {}
|
||||
private hooks: { [ name: string ]: HookInformationValue[] } = {}
|
||||
|
||||
private constructor () {
|
||||
}
|
||||
|
||||
async registerPluginsAndThemes () {
|
||||
await this.resetCSSGlobalFile()
|
||||
|
||||
const plugins = await PluginModel.listEnabledPluginsAndThemes()
|
||||
|
||||
for (const plugin of plugins) {
|
||||
try {
|
||||
await this.registerPluginOrTheme(plugin)
|
||||
} catch (err) {
|
||||
logger.error('Cannot register plugin %s, skipping.', plugin.name, { err })
|
||||
}
|
||||
}
|
||||
|
||||
this.sortHooksByPriority()
|
||||
}
|
||||
// ###################### Getters ######################
|
||||
|
||||
getRegisteredPluginOrTheme (name: string) {
|
||||
return this.registeredPlugins[name]
|
||||
|
@ -92,6 +80,12 @@ export class PluginManager {
|
|||
return this.getRegisteredPluginsOrThemes(PluginType.THEME)
|
||||
}
|
||||
|
||||
getSettings (name: string) {
|
||||
return this.settings[name] || []
|
||||
}
|
||||
|
||||
// ###################### Hooks ######################
|
||||
|
||||
async runHook (hookName: string, param?: any) {
|
||||
let result = param
|
||||
|
||||
|
@ -99,8 +93,11 @@ export class PluginManager {
|
|||
|
||||
for (const hook of this.hooks[hookName]) {
|
||||
try {
|
||||
if (wait) result = await hook.handler(param)
|
||||
else result = hook.handler()
|
||||
if (wait) {
|
||||
result = await hook.handler(param)
|
||||
} else {
|
||||
result = hook.handler()
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('Cannot run hook %s of plugin %s.', hookName, hook.pluginName, { err })
|
||||
}
|
||||
|
@ -109,6 +106,24 @@ export class PluginManager {
|
|||
return result
|
||||
}
|
||||
|
||||
// ###################### Registration ######################
|
||||
|
||||
async registerPluginsAndThemes () {
|
||||
await this.resetCSSGlobalFile()
|
||||
|
||||
const plugins = await PluginModel.listEnabledPluginsAndThemes()
|
||||
|
||||
for (const plugin of plugins) {
|
||||
try {
|
||||
await this.registerPluginOrTheme(plugin)
|
||||
} catch (err) {
|
||||
logger.error('Cannot register plugin %s, skipping.', plugin.name, { err })
|
||||
}
|
||||
}
|
||||
|
||||
this.sortHooksByPriority()
|
||||
}
|
||||
|
||||
async unregister (name: string) {
|
||||
const plugin = this.getRegisteredPlugin(name)
|
||||
|
||||
|
@ -133,7 +148,9 @@ export class PluginManager {
|
|||
await this.regeneratePluginGlobalCSS()
|
||||
}
|
||||
|
||||
async install (toInstall: string, version: string, fromDisk = false) {
|
||||
// ###################### Installation ######################
|
||||
|
||||
async install (toInstall: string, version?: string, fromDisk = false) {
|
||||
let plugin: PluginModel
|
||||
let name: string
|
||||
|
||||
|
@ -206,6 +223,8 @@ export class PluginManager {
|
|||
logger.info('Plugin %s uninstalled.', packageName)
|
||||
}
|
||||
|
||||
// ###################### Private register ######################
|
||||
|
||||
private async registerPluginOrTheme (plugin: PluginModel) {
|
||||
logger.info('Registering plugin or theme %s.', plugin.name)
|
||||
|
||||
|
@ -251,13 +270,25 @@ export class PluginManager {
|
|||
})
|
||||
}
|
||||
|
||||
const registerSetting = (options: RegisterSettingOptions) => {
|
||||
if (!this.settings[plugin.name]) this.settings[plugin.name] = []
|
||||
|
||||
this.settings[plugin.name].push(options)
|
||||
}
|
||||
|
||||
const settingsManager: PluginSettingsManager = {
|
||||
getSetting: (name: string) => PluginModel.getSetting(plugin.name, name),
|
||||
|
||||
setSetting: (name: string, value: string) => PluginModel.setSetting(plugin.name, name, value)
|
||||
}
|
||||
|
||||
const library: PluginLibrary = require(join(pluginPath, packageJSON.library))
|
||||
|
||||
if (!isLibraryCodeValid(library)) {
|
||||
throw new Error('Library code is not valid (miss register or unregister function)')
|
||||
}
|
||||
|
||||
library.register({ registerHook })
|
||||
library.register({ registerHook, registerSetting, settingsManager })
|
||||
|
||||
logger.info('Add plugin %s CSS to global file.', plugin.name)
|
||||
|
||||
|
@ -266,13 +297,7 @@ export class PluginManager {
|
|||
return library
|
||||
}
|
||||
|
||||
private sortHooksByPriority () {
|
||||
for (const hookName of Object.keys(this.hooks)) {
|
||||
this.hooks[hookName].sort((a, b) => {
|
||||
return b.priority - a.priority
|
||||
})
|
||||
}
|
||||
}
|
||||
// ###################### CSS ######################
|
||||
|
||||
private resetCSSGlobalFile () {
|
||||
return outputFile(PLUGIN_GLOBAL_CSS_PATH, '')
|
||||
|
@ -296,6 +321,26 @@ export class PluginManager {
|
|||
})
|
||||
}
|
||||
|
||||
private async regeneratePluginGlobalCSS () {
|
||||
await this.resetCSSGlobalFile()
|
||||
|
||||
for (const key of Object.keys(this.registeredPlugins)) {
|
||||
const plugin = this.registeredPlugins[key]
|
||||
|
||||
await this.addCSSToGlobalFile(plugin.path, plugin.css)
|
||||
}
|
||||
}
|
||||
|
||||
// ###################### Utils ######################
|
||||
|
||||
private sortHooksByPriority () {
|
||||
for (const hookName of Object.keys(this.hooks)) {
|
||||
this.hooks[hookName].sort((a, b) => {
|
||||
return b.priority - a.priority
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private getPackageJSON (pluginName: string, pluginType: PluginType) {
|
||||
const pluginPath = join(this.getPluginPath(pluginName, pluginType), 'package.json')
|
||||
|
||||
|
@ -312,15 +357,7 @@ export class PluginManager {
|
|||
return name.replace(/^peertube-((theme)|(plugin))-/, '')
|
||||
}
|
||||
|
||||
private async regeneratePluginGlobalCSS () {
|
||||
await this.resetCSSGlobalFile()
|
||||
|
||||
for (const key of Object.keys(this.registeredPlugins)) {
|
||||
const plugin = this.registeredPlugins[key]
|
||||
|
||||
await this.addCSSToGlobalFile(plugin.path, plugin.css)
|
||||
}
|
||||
}
|
||||
// ###################### Private getters ######################
|
||||
|
||||
private getRegisteredPluginsOrThemes (type: PluginType) {
|
||||
const plugins: RegisteredPlugin[] = []
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue