Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make filterPlugins work in saber-node.js #221

Merged
merged 4 commits into from
May 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 29 additions & 15 deletions packages/saber/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ class Saber {
}

for (const plugin of userPlugins) {
this.applyPlugin(plugin, plugin.options, plugin.__path)
this.applyPlugin(plugin, plugin.options, plugin.location)
}

await this.hooks.afterPlugins.promise()
Expand Down Expand Up @@ -214,32 +214,46 @@ class Saber {

getUserPlugins() {
// Plugins that are specified in user config, a.k.a. saber-config.js etc
let plugins =
const plugins =
this.configDir && this.config.plugins
? this.config.plugins.map(p => {
if (typeof p === 'string') {
p = { resolve: p }
}

p.resolve = resolveFrom(this.configDir, p.resolve)
return p
const location = resolveFrom(this.configDir, p.resolve)

const plugin = require(location)
plugin.location = location
plugin.options = p.option

return plugin
})
: []

plugins = plugins.map(({ resolve, options }) => {
const plugin = require(resolve)
plugin.__path = resolve
plugin.options = options
if (plugin.filterPlugins) {
this.hooks.filterPlugins.tap(plugin.name, plugins =>
plugin.filterPlugins(plugins, options)
)
const applyFilterPlugins = plugins => {
const handlers = new Set()

for (const plugin of plugins) {
const { filterPlugins, options } = plugin
if (filterPlugins) {
delete plugin.filterPlugins
handlers.add(plugins => filterPlugins(plugins, options))
}
}

return plugin
})
if (handlers.size > 0) {
for (const handler of handlers) {
plugins = handler(plugins)
}

return applyFilterPlugins(plugins)
}

return plugins
}

return this.hooks.filterPlugins.call(plugins)
return applyFilterPlugins(this.hooks.filterPlugins.call(plugins))
}

resolveCache(...args) {
Expand Down
51 changes: 25 additions & 26 deletions packages/saber/lib/plugins/extend-node-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,40 +22,39 @@ exports.apply = api => {
updateNodeApi()

const getHookHandler = hookName => nodeApi[hookName] || __noopHandler__

api.hooks.beforePlugins.tapPromise(nodeApiId, () => {
const hookHandler = getHookHandler('beforePlugins')
if (hookHandler.name !== '__noopHandler__') {
log.verbose(() => `beforePlugins ${colors.dim(`(${nodeApiId})`)}`)
const addHook = hookName => {
const hook = api.hooks[hookName]
if (hook) {
const tapType = hook.call ? 'tap' : 'tapPromise'
hook[tapType](nodeApiId, (...args) => {
const hookHandler = getHookHandler(hookName)
if (hookHandler.name !== '__noopHandler__') {
log.verbose(() => `${hookName} ${colors.dim(`(${nodeApiId})`)}`)
}

if (tapType === 'tap') {
return hookHandler.call(api, ...args)
}

return Promise.resolve(hookHandler.call(api, ...args))
})
}
}

return Promise.resolve(hookHandler.call(api))
})
// Hooks that should be added before `afterPlugins` hook
const preHooks = ['beforePlugins', 'filterPlugins']

for (const preHook of preHooks) {
addHook(preHook)
}

api.hooks.afterPlugins.tap(nodeApiId, () => {
for (const hookName of Object.keys(api.hooks)) {
if (hookName === 'beforePlugins') {
if (preHooks.includes(hookName)) {
continue
}

const hook = api.hooks[hookName]
if (hook) {
const tapType = hook.call ? 'tap' : 'tapPromise'
hook[tapType](nodeApiId, (...args) => {
const hookHandler = getHookHandler(hookName)
const result = hookHandler.call(api, ...args)

if (hookHandler.name !== '__noopHandler__') {
log.verbose(() => `${hookName} ${colors.dim(`(${nodeApiId})`)}`)
}

if (tapType === 'tapPromise') {
return Promise.resolve(result)
}

return result
})
}
addHook(hookName)
}
})

Expand Down
17 changes: 16 additions & 1 deletion website/pages/docs/plugin-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,22 @@ A function to invoke.

### filterPlugins

- Type: `(plugins: Plugins[], options: any) => Plugins[]`
- Type: `FilterPlugins`
- Required: `false`

Filter the plugins, you can use it to add or remove plugins.

```ts
type FilterPlugins = (plugins: Plugin[], options: any) => Plugins[]

interface Plugin {
/* Plugin name */
name: string
apply: (api: SaberInstance, options?: any) => void
filterPlugins: FilterPlugins
/* Plugin options */
options?: any
/* The path to the plugin, only used in logs */
location?: string
}
```
9 changes: 9 additions & 0 deletions website/pages/docs/saber-instance.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,18 +99,27 @@ Depending on the hook type, `tapAsync` and `tapPromise` may also be available. H

Called to filter plugins.

This hook is __only__ available `saber-node.js`.

```ts
interface Plugin {
/* Plugin name */
name: string
apply: (api: SaberInstance, options?: any) => void
/* Plugin options */
options?: any
/* The path to the plugin, only used in logs */
location?: string
}
```


### `beforePlugins`

- Hook Type: `AsyncSeriesHook`

This hook is __only__ available `saber-node.js`.

Called before loading user plugins.

### `afterPlugins`
Expand Down