misc(v2): add more typing for server code (#1548)

* refactor(v2): add types to loading code

* misc(v2): better typing

* misc(v2): rename presets

* misc(v2): further typing

* fix typing for webpack config
This commit is contained in:
Yangshun Tay 2019-06-03 03:16:17 -07:00 committed by Endi
parent 5af8cd566e
commit 7115cfc743
7 changed files with 88 additions and 37 deletions

View File

@ -59,7 +59,7 @@ export async function start(
};
const pluginPaths = _.compact(
_.flatten(
_.flatten<string | undefined>(
plugins.map(plugin => plugin.getPathsToWatch && plugin.getPathsToWatch()),
),
).map(normalizeToSiteDir);

View File

@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
import {PluginConfig} from './plugins';
import fs from 'fs-extra';
import _ from 'lodash';
import importFresh from 'import-fresh';
@ -21,7 +23,7 @@ export interface DocusaurusConfig {
projectName?: string;
customFields?: string[];
githubHost?: string;
plugins?: any[];
plugins?: PluginConfig[];
presets?: any[];
themeConfig?: {
[key: string]: any;

View File

@ -5,7 +5,11 @@
* LICENSE file in the root directory of this source tree.
*/
import {PluginConfig, Plugin} from './plugins';
import path from 'path';
import _ from 'lodash';
import {generate} from '@docusaurus/utils';
import {loadConfig, DocusaurusConfig} from './config';
@ -29,7 +33,7 @@ export interface LoadContext {
}
export interface Props extends LoadContext {
routesPaths: string[];
plugins: any[];
plugins: Plugin<any>[];
}
export async function load(
@ -60,11 +64,11 @@ export async function load(
baseUrl,
};
/* Preset */
// Presets.
const {plugins: presetPlugins, themes: presetThemes} = loadPresets(context);
/* Plugin */
const pluginConfigs = [
// Plugins.
const pluginConfigs: PluginConfig[] = [
...presetPlugins,
...(siteConfig.plugins || []),
...presetThemes,
@ -75,15 +79,16 @@ export async function load(
context,
});
/* Theme */
// Themes.
const fallbackTheme = path.resolve(__dirname, '../client/theme-fallback');
const pluginThemes = plugins
.map(plugin => plugin.getThemePath && plugin.getThemePath())
.filter(Boolean) as string[];
const pluginThemes = _.compact(
plugins.map(plugin => plugin.getThemePath && plugin.getThemePath()),
);
const userTheme = path.resolve(siteDir, 'theme');
const alias = loadThemeAlias([fallbackTheme, ...pluginThemes, userTheme]);
// Make a fake plugin to resolve aliased theme components.
plugins.push({
name: 'docusaurus-bootstrap-plugin',
configureWebpack: () => ({
resolve: {
alias,

View File

@ -5,21 +5,51 @@
* LICENSE file in the root directory of this source tree.
*/
import {LoadContext, Props} from '..';
import {RouteConfig} from '../routes';
import fs from 'fs-extra';
import importFresh from 'import-fresh';
import path from 'path';
import {generate} from '@docusaurus/utils';
import {LoadContext} from '..';
import {Configuration} from 'webpack';
export interface Plugin<T> {
name: string;
loadContent?(): T;
contentLoaded?({
content: T,
actions: DocusaurusPluginContentLoadedActions,
}): void;
postBuild?(props: Props): void;
postStart?(props: Props): void;
configureWebpack?(config: Configuration, isServer: boolean): Configuration;
getThemePath?(): string;
getPathsToWatch?(): string[];
}
export interface PluginConfig {
module: string;
options?: Object;
}
export interface PluginContentLoadedActions {
addRoute(config: RouteConfig): void;
createData(name: string, data: Object): Promise<string>;
}
export async function loadPlugins({
pluginConfigs = [],
pluginConfigs,
context,
}: {
pluginConfigs: any[];
pluginConfigs: PluginConfig[];
context: LoadContext;
}) {
}): Promise<{
plugins: Plugin<any>[];
pluginsRouteConfigs: RouteConfig[];
}> {
// 1. Plugin Lifecycle - Initialization/Constructor
const plugins = pluginConfigs.map(({module, options}) => {
const plugins: Plugin<any>[] = pluginConfigs.map(({module, options}) => {
// module is any valid module identifier - npm package or locally-resolved path.
const plugin = importFresh(module);
return plugin(context, options);
@ -40,7 +70,7 @@ export async function loadPlugins({
);
// 3. Plugin lifecycle - contentLoaded
const pluginsRouteConfigs: any[] = [];
const pluginsRouteConfigs: RouteConfig[] = [];
await Promise.all(
plugins.map(async (plugin, index) => {
@ -52,7 +82,8 @@ export async function loadPlugins({
context.generatedFilesDir,
plugin.name,
);
const actions = {
const actions: PluginContentLoadedActions = {
addRoute: config => pluginsRouteConfigs.push(config),
createData: async (name, content) => {
const modulePath = path.join(pluginContentDir, name);
@ -62,9 +93,8 @@ export async function loadPlugins({
},
};
const loadedContent = pluginsLoadedContent[index];
await plugin.contentLoaded({
content: loadedContent,
content: pluginsLoadedContent[index],
actions,
});
}),

View File

@ -5,31 +5,45 @@
* LICENSE file in the root directory of this source tree.
*/
import {LoadContext} from '../index';
import {PluginConfig} from '../plugins';
import importFresh from 'import-fresh';
import _ from 'lodash';
import {LoadContext} from '../index';
export function loadPresets(context: LoadContext) {
export interface Preset {
plugins?: PluginConfig[];
themes?: PluginConfig[];
}
export function loadPresets(
context: LoadContext,
): {
plugins: PluginConfig[];
themes: PluginConfig[];
} {
const presets: any[] = context.siteConfig.presets || [];
const plugins: any[] = [];
const themes: any[] = [];
const plugins: (PluginConfig[] | undefined)[] = [];
const themes: (PluginConfig[] | undefined)[] = [];
presets.forEach(presetItem => {
let presetModule;
let presetModuleImport;
let presetOptions = {};
if (typeof presetItem === 'string') {
presetModule = presetItem;
presetModuleImport = presetItem;
} else if (Array.isArray(presetItem)) {
[presetModule, presetOptions] = presetItem;
[presetModuleImport, presetOptions] = presetItem;
}
const preset = importFresh(presetModule);
plugins.push(preset(context, presetOptions).plugins);
themes.push(preset(context, presetOptions).themes);
const presetModule = importFresh(presetModuleImport);
const preset: Preset = presetModule(context, presetOptions);
plugins.push(preset.plugins);
themes.push(preset.themes);
});
return {
plugins: _.compact(_.flatten(plugins)),
themes: _.compact(_.flatten(themes)),
plugins: _.compact(_.flatten<PluginConfig | undefined>(plugins)),
themes: _.compact(_.flatten<PluginConfig | undefined>(themes)),
};
}

View File

@ -10,11 +10,11 @@ import fs from 'fs-extra';
import path from 'path';
import {fileToPath, posixPath, normalizeUrl} from '@docusaurus/utils';
export interface Alias {
export interface ThemeAlias {
[alias: string]: string;
}
export function themeAlias(themePath: string): Alias {
export function themeAlias(themePath: string): ThemeAlias {
if (!fs.pathExistsSync(themePath)) {
return {};
}
@ -23,7 +23,7 @@ export function themeAlias(themePath: string): Alias {
cwd: themePath,
});
const alias = {};
const alias: ThemeAlias = {};
themeComponentFiles.forEach(relativeSource => {
const filePath = path.join(themePath, relativeSource);
const fileName = fileToPath(relativeSource);

View File

@ -5,11 +5,11 @@
* LICENSE file in the root directory of this source tree.
*/
import {themeAlias, Alias} from './alias';
import {themeAlias, ThemeAlias} from './alias';
export {Alias} from './alias';
export {ThemeAlias} from './alias';
export function loadThemeAlias(themePaths: string[]): Alias {
export function loadThemeAlias(themePaths: string[]): ThemeAlias {
return themePaths.reduce(
(alias, themePath) => ({
...alias,