1.1.3 • Published 4 years ago
hins v1.1.3
hins
中间插件程序, 可以快速创建定制化 cli 工具
安装
npm install hins用法
暴露一个核心类 Core
const { Core } = require('hins')
const core = new Core({
  // ...arguments
})
// 需要执行的命令
core.start({ ...arguments })Core.start()
参数: object
{
  args?: object
  command: string
  reloadCommand?: boolean
}- args 接受任何参数, 类型是一个对象, 最后会传入命令插件
- command 启动命令
- reloadCommand 重新运行命令
// 这里先执行了 dev 命令,进入到 dev 插件,
core.start({ command: 'dev' })
// 有的时候需要做命令派发, 在dev插件命令内 做了一些计算,
// 最后得出执行webDev命令. 但是又不需要重新注册插件等前置步奏
core.start({ command: 'webDev', reloadCommand: true })接受参数:
cwd
- 工作区路径
- Type: string
- Default: process.cwd()
babelRegister
- config 和 plugin 的运行时, 使其支持 ts 或 ESNext
- Type: function
- Default: () => {}
possibleConfigName
- 读取配置文件的路径及文件名
- Type: string[]
- Default: []
{
  possibleConfigName: ['config.js']
}运行时就会去传入 cwd 根目录下找 config.js 文件并读取
plugins
- plugins 配置路径
- Type: string[]
- Default: []
可以是 绝对路径 或者 相对路径. 相对路径是相对传入的 cwd 参数
watchConfig
- 是否监听配置文件, 如果发现更改则重新运行命令
- Type: object
- Default:
  // IChangeTypes:'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir'
  {
    changeLog: (type: IChangeTypes, path: string) => void
    reloadLog: (type: IChangeTypes, path: string) => void
  }核心方法:
每个 plugin 都会接受一个 api 实例参数
describe 注册阶段执行,用于描述插件或插件集的 key、配置信息、启用方式等
参数: object
{
  key: string,
  config: {
    default: any,
    schema: (joi) => {
      return joi.string()
    }
  }
}api.describe({
  key: 'history',
  config: {
    default: 'browser',
    schema(joi) {
      return joi.string()
    }
  }
})// config
export default {
  history: 'node'
}注:
- config.default 为配置的默认值,用户没有配置时取这个
- config.schema 用于声明配置的类型,基于 joi,如果你希望用户进行配置,这个是必须的,否则用户的配置无效
register 为 api.applyHooks 注册可供其使用的 hook
参数: object
{
  key: string,
  fn: Function,
  pluginId?: string,
  before?: string,
  stage?: number
}// 可同步
api.register({
  key: 'foo',
  fn() {
    return 'a';
  },
});
// 可异步
api.register({
  key: 'foo',
  async fn() {
    await delay(100);
    return 'b';
  },
});
然后通过 api.applyHooks 即可拿到 ['a', 'b'],
const foo = await api.applyHooks({
  key: 'foo',
  type: api.ApplyHookType.add,
  initialValue: [],
});
console.log(foo); // ['a', 'b']- fn 支持同步和异步,异步通过 Promise,返回值为 Promise 即为异步
- fn 里的内容需结合 api.applyHooks 的 type 参数来看- 如果是 api.ApplyHookType.add,需有返回值,这些返回值最终会被合成一个数组
- 如果是 api.ApplyHookType.modify,需对第一个参数做修改,并返回
- 如果是 api.ApplyHookType.event,无需返回值
 
- stage 和 before 都是用于调整执行顺序的
- stage 默认是 0,设为 -1 或更少会提前执行,设为 1 或更多会后置执行
提供三个便捷调用:
api.applyAddHooks({
  key: 'foo',
  initialValue: []
})
api.applyModifyHooks({
  key: 'modify',
  initialValue: 'bar'
})
api.applyEventHooks({
  key: 'event'
})applyHooks 取得 register 注册的 hooks 执行后的数据
参数: object
{
  key: string,
  type:api.ApplyHookType,
  initialValue?: any,
  args?: any
}相同 key 可能有多个 hook, api.ApplyHookType.add 会返回所有 hook 的数组合值
const foo = await api.applyHooks({
  key: 'foo',
  type: api.ApplyHookType.add,
  initialValue: []
})
console.log(foo) // ['a', 'b']registerPlugins(plugins: string[]) 注册插件,参数为路径数组
api.registerPlugins([
  { key: 'preset2', apply: (api) => {} },
  require.resolve('./preset_3')
])这里内联插件不会进行处理, 直接添加至待执行的插件列表, 因为插件的键名是依照文件路径生成的, 这里的 key 需要填写唯一值
registerCommand 注册命令
参数: object
{
  command: string,
  alias?: string,
  fn: function
}api.registerCommand({
  command: 'generate',
  alias: 'g',
  fn: ({ args }) => {
    return `hello ${api.args.projectName}`
  }
})alias 为别名,比如 generate 的别名 g fn 的参数为 { args }
registerMethod
参数: object
{
  name: string,
  fn?: Function,
}往 api 上注册方法。可以是 api.register() 的快捷使用方式,便于调用;也可以不是,如果有提供 fn,则执行 fn 定义的函数。
api.registerMethod({
  name: 'foo',
  fn() {
    return 'foo'
  }
})
api.foo()
// 'foo'configInstance
    watchConfig(): void;
    // 开启监听config文件
    在插件里使用api.configInstance.watchConfig开启监听配置文件, 当修改时会重启周期钩子
onStart()
在执行命令函数前触发。可以使用 config
api.onStart(() => {
  // do something
})onPluginReady()
在插件初始化完成触发。在 onStart 之前,此时 config 尚未解析好。
api.onPluginReady(() => {
  // do something
})modifyConfig
修改最终配置,参数为最终 config 配置
api.modifyConfig((memo) => {
  return {
    ...memo,
    ...defaultOptions
  }
})修改后的值不会再做 schema 校验