mirror of https://github.com/Seich/Beau.git
119 lines
3.2 KiB
TypeScript
119 lines
3.2 KiB
TypeScript
const vm = require('vm')
|
|
const requireg = require('requireg')
|
|
const deepmerge = require('deepmerge')
|
|
const { toKebabCase, dynamicValueRegex, replaceInObject } = require('./shared')
|
|
const { isPlainObject } = require('is-plain-object')
|
|
|
|
export default class Plugins {
|
|
constructor(plugins = [], autoload = ['std']) {
|
|
this.registry = {
|
|
preRequestModifiers: [],
|
|
postRequestModifiers: [],
|
|
dynamicValues: []
|
|
}
|
|
|
|
this.context = {}
|
|
|
|
this.autoload = autoload
|
|
|
|
this.loadPlugins(plugins.concat(this.autoload))
|
|
}
|
|
|
|
normalizePlugins(plugins) {
|
|
let results = {}
|
|
|
|
plugins.forEach((plugin) => {
|
|
let name = plugin
|
|
let settings = undefined
|
|
|
|
if (typeof plugin === 'object') {
|
|
let keys = Object.keys(plugin)
|
|
|
|
if (keys.length !== 1) {
|
|
throw new Error(`Plugin items should contain only one key.`)
|
|
}
|
|
|
|
name = keys[0]
|
|
settings = plugin[name]
|
|
}
|
|
|
|
results[name] = settings
|
|
})
|
|
|
|
return results
|
|
}
|
|
|
|
loadPlugins(plugins) {
|
|
plugins = this.normalizePlugins(plugins)
|
|
Object.keys(plugins).forEach((name) => {
|
|
const module = `beau-${toKebabCase(name)}`
|
|
|
|
if (typeof requireg.resolve(module) !== 'undefined') {
|
|
const plugin = requireg(module)
|
|
new plugin(this, plugins[name])
|
|
} else {
|
|
if (this.autoload.includes(name)) return
|
|
|
|
console.warn(
|
|
`Plugin ${name} couldn't be found. It is available globally?`
|
|
)
|
|
}
|
|
})
|
|
}
|
|
|
|
executeModifier(modifier, obj, orig) {
|
|
let result = deepmerge({}, obj, { isMergeableObject: isPlainObject })
|
|
|
|
this.registry[modifier].forEach(
|
|
(modifier) => (result = modifier(result, orig))
|
|
)
|
|
|
|
return result
|
|
}
|
|
|
|
replaceDynamicValues(obj) {
|
|
vm.createContext(this.context)
|
|
return replaceInObject(obj, (val) => {
|
|
let valIsEmpty = val.trim().length === 0
|
|
|
|
if (valIsEmpty) {
|
|
return val
|
|
}
|
|
|
|
try {
|
|
let onlyHasDynamic =
|
|
val.replace(dynamicValueRegex, '').trim() === ''
|
|
|
|
if (onlyHasDynamic) {
|
|
let call
|
|
val.replace(dynamicValueRegex, (match, c) => {
|
|
call = c
|
|
})
|
|
|
|
return vm.runInContext(call, this.context)
|
|
}
|
|
|
|
return val.replace(dynamicValueRegex, (match, call) => {
|
|
return vm.runInContext(call, this.context)
|
|
})
|
|
} catch (e) {
|
|
throw new Error(`DynamicValue: ` + e)
|
|
}
|
|
})
|
|
}
|
|
|
|
addPreRequestModifier(modifier) {
|
|
this.registry.preRequestModifiers.push(modifier)
|
|
}
|
|
|
|
addPostRequestModifier(modifier) {
|
|
this.registry.postRequestModifiers.push(modifier)
|
|
}
|
|
|
|
defineDynamicValue(name, fn) {
|
|
this.registry.dynamicValues.push({ name, fn })
|
|
this.context[name] = fn
|
|
}
|
|
}
|
|
|