diff --git a/packages/docz-core/package.json b/packages/docz-core/package.json index 3eaa12de5..a8ae64056 100644 --- a/packages/docz-core/package.json +++ b/packages/docz-core/package.json @@ -64,6 +64,7 @@ "lodash.get": "^4.4.2", "mini-html-webpack-plugin": "^0.2.3", "react-dev-utils": "^6.1.0", + "p-reduce": "^1.0.0", "react-docgen-typescript-loader": "^3.0.0-rc.0", "react-hot-loader": "4.3.11", "rehype-docz": "^0.12.9", @@ -96,6 +97,7 @@ "@types/koa": "^2.0.46", "@types/lodash.get": "^4.4.4", "@types/node": "10.12.1", + "@types/p-reduce": "^1.0.0", "@types/prettier": "^1.13.2", "@types/resolve": "^0.0.8", "@types/webpack": "^4.4.17", diff --git a/packages/docz-core/src/Entries.ts b/packages/docz-core/src/Entries.ts index 75f629752..ebfbe60e3 100644 --- a/packages/docz-core/src/Entries.ts +++ b/packages/docz-core/src/Entries.ts @@ -80,7 +80,7 @@ export class Entries { } private async getMap(config: Config): Promise { - const { src, files: pattern, ignore } = config + const { src, files: pattern, ignore, plugins } = config const arr = Array.isArray(pattern) ? pattern : [pattern] const toMatch = matchFilesWithSrc(config) @@ -109,8 +109,13 @@ export class Entries { } } + const reduce = Plugin.reduceFromPlugins(plugins) + const modifiedFiles = reduce('modifyFiles', files) + const map = new Map() - const entries = await Promise.all(files.map(createEntry).filter(Boolean)) + const entries = await Promise.all( + modifiedFiles.map(createEntry).filter(Boolean) + ) for (const entry of entries) { if (entry) { diff --git a/packages/docz-core/src/Plugin.ts b/packages/docz-core/src/Plugin.ts index 4df7b2fbb..7cb062e88 100644 --- a/packages/docz-core/src/Plugin.ts +++ b/packages/docz-core/src/Plugin.ts @@ -1,16 +1,18 @@ import get from 'lodash.get' +import pReduce from 'p-reduce' import { Config } from './commands/args' import { isFn } from './utils/helpers' import { BabelRC } from './utils/babel-config' -export type SetConfig = (config: Config) => Config +export type SetConfig = (config: Config) => Config | Promise export type ModifyBundlerConfig = ( config: C, dev: boolean, args: Config ) => C export type ModifyBabelRC = (babelrc: BabelRC, args: Config) => BabelRC +export type ModifyFiles = (files: string[], args: Config) => string[] export type onCreateApp = (app: A) => void export type OnServerListening = (server: S) => void export type OnPreBuild = (args: Config) => void @@ -22,6 +24,7 @@ export interface PluginFactory { setConfig?: SetConfig modifyBundlerConfig?: ModifyBundlerConfig modifyBabelRc?: ModifyBabelRC + modifyFiles?: ModifyFiles onCreateApp?: onCreateApp onServerListening?: OnServerListening onPreBuild?: OnPreBuild @@ -64,9 +67,25 @@ export class Plugin implements PluginFactory { } } + public static reduceFromPluginsAsync( + plugins: Plugin[] | undefined + ): (method: keyof Plugin, initial: C, ...args: any[]) => Promise { + return (method, initial, ...args) => { + return pReduce( + [...(plugins || [])], + (obj: any, plugin: any) => { + const fn = get(plugin, method) + return Promise.resolve(fn && isFn(fn) ? fn(obj, ...args) : obj) + }, + initial + ) + } + } + public readonly setConfig?: SetConfig public readonly modifyBundlerConfig?: ModifyBundlerConfig public readonly modifyBabelRc?: ModifyBabelRC + public readonly modifyFiles?: ModifyFiles public readonly onCreateApp?: onCreateApp public readonly onServerListening?: OnServerListening public readonly onPreBuild?: OnPreBuild @@ -78,6 +97,7 @@ export class Plugin implements PluginFactory { this.setConfig = p.setConfig this.modifyBundlerConfig = p.modifyBundlerConfig this.modifyBabelRc = p.modifyBabelRc + this.modifyFiles = p.modifyFiles this.onCreateApp = p.onCreateApp this.onServerListening = p.onServerListening this.onPreBuild = p.onPreBuild diff --git a/packages/docz-core/src/commands/build.ts b/packages/docz-core/src/commands/build.ts index 1990248aa..d7070b4ec 100644 --- a/packages/docz-core/src/commands/build.ts +++ b/packages/docz-core/src/commands/build.ts @@ -11,7 +11,7 @@ import { Config } from './args' export const build = async (args: Config) => { const env = envDotProp.get('node.env') - const config = loadConfig(args) + const config = await loadConfig(args) const entries = new Entries(config) const bundler = webpack(config, env) diff --git a/packages/docz-core/src/commands/dev.ts b/packages/docz-core/src/commands/dev.ts index 21b50ff0e..6400ef7f2 100644 --- a/packages/docz-core/src/commands/dev.ts +++ b/packages/docz-core/src/commands/dev.ts @@ -11,7 +11,7 @@ import { loadConfig } from '../utils/load-config' export const dev = async (args: Config) => { const env = envDotProp.get('node.env') - const config = loadConfig(args) + const config = await loadConfig(args) const port = await detectPort(config.port) const hotPort = await detectPort(config.hotPort) const websocketPort = await detectPort(config.websocketPort) diff --git a/packages/docz-core/src/types.d.ts b/packages/docz-core/src/types.d.ts index efc884e92..665a24473 100644 --- a/packages/docz-core/src/types.d.ts +++ b/packages/docz-core/src/types.d.ts @@ -37,3 +37,4 @@ declare module 'detect-port' declare module 'react-dev-utils/FileSizeReporter' declare module 'react-dev-utils/formatWebpackMessages' declare module 'react-dev-utils/printBuildError' +declare module 'p-reduce' diff --git a/packages/docz-core/src/utils/load-config.ts b/packages/docz-core/src/utils/load-config.ts index 0ca260f35..618fdae6d 100644 --- a/packages/docz-core/src/utils/load-config.ts +++ b/packages/docz-core/src/utils/load-config.ts @@ -14,7 +14,7 @@ const defaultHtmlContext = { lang: 'en', } -export const loadConfig = (args: Config): Config => { +export const loadConfig = async (args: Config): Promise => { const defaultConfig = { ...args, hashRouter: false, @@ -33,6 +33,9 @@ export const loadConfig = (args: Config): Config => { ? loadFrom(path.resolve(args.config), defaultConfig) : load('docz', defaultConfig) - const reduce = Plugin.reduceFromPlugins(config.plugins) - return omit(toOmit, reduce('setConfig', { ...config, paths })) + const reduceAsync = Plugin.reduceFromPluginsAsync(config.plugins) + return omit( + toOmit, + await reduceAsync('setConfig', { ...config, paths }) + ) }