hins
Version:
[](https://codecov.io/gh/l-zoy/hins) [](https://github.com/l-zoy/hins/blob/master/LICENSE)  • 3.93 kB
text/typescript
import assert from 'assert'
import { pathToRegister } from './resolvePlugins'
import { ICoreStage } from './enum'
import type {
IApiRegisterPlugins,
IApiRegisterMethod,
IApiDescribe,
IApiOpitons,
ICommands,
IHook,
IWorkDir
} from './types'
export default class Api {
/**
* @desc as an identifier
*/
path?: IWorkDir
/**
* @desc Core prototype
*/
core: IApiOpitons['core']
constructor(options: IApiOpitons) {
const { core } = options
// this.path = path
this.core = core
}
describe(options: IApiDescribe) {
const { key, config } = options
const { plugins } = this.core
assert(options.key, `api.describe() failed, the plugin is missing an 'key'.`)
assert(
options.config.schema && typeof options.config.schema === 'function',
`api.describe() failed, the plugin is missing 'schema'`
)
assert(this.path, `api.describe() failed, this.Path is not initialized`)
plugins[this.path].key = key
plugins[this.path].config = config
}
registerCommand(options: ICommands) {
const { commands } = this.core
const { command, alias } = options
assert(
!commands[command],
`api.registerCommand() failed, the command ${command} is exists.`
)
commands[command] = options
if (alias) {
commands[alias] = options
}
}
registerPlugins(plugins: IApiRegisterPlugins) {
assert(
this.core.stage === ICoreStage.initPlugins,
`api.registerPlugins() failed, it should only be used in registering stage.`
)
assert(Array.isArray(plugins), `api.registerPlugins() failed, plugins must be Array.`)
// dynamic registration support after processing
const keepKeys = {}
const extraPlugins = []
for (const plugin of plugins) {
if (typeof plugin === 'string') {
if (keepKeys[plugin]) {
continue
}
const applyPlugin = pathToRegister(plugin)
if (this.core.plugins[applyPlugin.path]) {
throw new Error(`Same plugin registered ${applyPlugin.path}`)
}
this.core.extraPlugins.forEach(({ path }) => {
if (path === applyPlugin.path) {
throw new Error(`Repeat the plugin to be registered ${applyPlugin.path}`)
}
})
keepKeys[plugin] = 1
extraPlugins.push(pathToRegister(plugin))
continue
}
if (!plugin.key || !plugin.apply) {
throw new Error(`Inline plugins must contain 'key' and 'apply'`)
}
if (keepKeys[plugin.key]) {
continue
}
keepKeys[plugin.key] = 1
extraPlugins.push({
path: plugin.key,
apply: () => plugin.apply
})
}
this.core.extraPlugins.unshift(...extraPlugins)
}
registerMethod(options: IApiRegisterMethod) {
const { pluginMethods } = this.core
const { fn, name } = options
assert(
!pluginMethods[name],
`api.registerMethod() failed, method ${name} is already exist.`
)
pluginMethods[name] =
fn ??
function (this: Api, hookOptions: Omit<IHook, 'pluginId'> | (() => any)) {
const hook = typeof hookOptions === 'function' ? { fn: hookOptions } : hookOptions
this.register({
key: name,
...hook
})
}
}
register(options: Omit<IHook, 'pluginId'>) {
const { hooksByPluginId } = this.core
assert(
options.key && typeof options.key === 'string',
`api.register() failed, hook.key must supplied and should be string, but got ${options.key}.`
)
assert(
typeof options.fn === 'function',
`api.register() failed, hook.fn must supplied and should be function, but got ${options.fn}.`
)
assert(this.path, `api.register() failed, this.Path is not initialized`)
hooksByPluginId[options.key] = (hooksByPluginId[options.key] ?? []).concat({
pluginId: this.path,
...options
})
}
}