refactor: convert all fs methods to async (#6725)

* refactor: convert all fs methods to async

* fix snap
This commit is contained in:
Joshua Chen 2022-02-20 10:21:33 +08:00 committed by GitHub
parent c0b3c9af65
commit c6d0d812eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 518 additions and 429 deletions

View file

@ -36,7 +36,7 @@ const {
*
* cache data is stored in `~/.config/configstore/update-notifier-@docusaurus`
*/
function beforeCli() {
async function beforeCli() {
const notifier = updateNotifier({
pkg: {
name,
@ -98,7 +98,9 @@ function beforeCli() {
.filter((p) => p.startsWith('@docusaurus'))
.map((p) => p.concat('@latest'))
.join(' ');
const isYarnUsed = fs.existsSync(path.resolve(process.cwd(), 'yarn.lock'));
const isYarnUsed = await fs.pathExists(
path.resolve(process.cwd(), 'yarn.lock'),
);
const upgradeCommand = isYarnUsed
? `yarn upgrade ${siteDocusaurusPackagesForUpdate}`
: `npm i ${siteDocusaurusPackagesForUpdate}`;

View file

@ -9,7 +9,7 @@
// @ts-check
import logger from '@docusaurus/logger';
import fs from 'fs';
import fs from 'fs-extra';
import cli from 'commander';
import {createRequire} from 'module';
import {
@ -25,9 +25,9 @@ import {
} from '../lib/index.js';
import beforeCli from './beforeCli.mjs';
beforeCli();
await beforeCli();
const resolveDir = (dir = '.') => fs.realpathSync(dir);
const resolveDir = (dir = '.') => fs.realpath(dir);
cli
.version(createRequire(import.meta.url)('../package.json').version)
@ -56,8 +56,8 @@ cli
'--no-minify',
'build website without minimizing JS bundles (default: false)',
)
.action((siteDir, {bundleAnalyzer, config, outDir, locale, minify}) => {
build(resolveDir(siteDir), {
.action(async (siteDir, {bundleAnalyzer, config, outDir, locale, minify}) => {
build(await resolveDir(siteDir), {
bundleAnalyzer,
outDir,
config,
@ -74,8 +74,14 @@ cli
'copy TypeScript theme files when possible (default: false)',
)
.option('--danger', 'enable swizzle for internal component of themes')
.action((themeName, componentName, siteDir, {typescript, danger}) => {
swizzle(resolveDir(siteDir), themeName, componentName, typescript, danger);
.action(async (themeName, componentName, siteDir, {typescript, danger}) => {
swizzle(
await resolveDir(siteDir),
themeName,
componentName,
typescript,
danger,
);
});
cli
@ -97,8 +103,8 @@ cli
'--skip-build',
'skip building website before deploy it (default: false)',
)
.action((siteDir, {outDir, skipBuild, config}) => {
deploy(resolveDir(siteDir), {
.action(async (siteDir, {outDir, skipBuild, config}) => {
deploy(await resolveDir(siteDir), {
outDir,
config,
skipBuild,
@ -124,17 +130,19 @@ cli
'--poll [interval]',
'use polling rather than watching for reload (default: false). Can specify a poll interval in milliseconds',
)
.action((siteDir, {port, host, locale, config, hotOnly, open, poll}) => {
start(resolveDir(siteDir), {
port,
host,
locale,
config,
hotOnly,
open,
poll,
});
});
.action(
async (siteDir, {port, host, locale, config, hotOnly, open, poll}) => {
start(await resolveDir(siteDir), {
port,
host,
locale,
config,
hotOnly,
open,
poll,
});
},
);
cli
.command('serve [siteDir]')
@ -151,7 +159,7 @@ cli
.option('--build', 'build website before serving (default: false)')
.option('-h, --host <host>', 'use specified host (default: localhost)')
.action(
(
async (
siteDir,
{
dir = 'build',
@ -161,7 +169,7 @@ cli
config,
},
) => {
serve(resolveDir(siteDir), {
serve(await resolveDir(siteDir), {
dir,
port,
build: buildSite,
@ -174,8 +182,8 @@ cli
cli
.command('clear [siteDir]')
.description('Remove build artifacts.')
.action((siteDir) => {
clear(resolveDir(siteDir));
.action(async (siteDir) => {
clear(await resolveDir(siteDir));
});
cli
@ -198,11 +206,11 @@ cli
'allows to init new written messages with a given prefix. This might help you to highlight untranslated message to make them stand out in the UI',
)
.action(
(
async (
siteDir,
{locale = undefined, override = false, messagePrefix = '', config},
) => {
writeTranslations(resolveDir(siteDir), {
writeTranslations(await resolveDir(siteDir), {
locale,
override,
config,
@ -219,8 +227,8 @@ cli
"keep the headings' casing, otherwise make all lowercase (default: false)",
)
.option('--overwrite', 'overwrite existing heading IDs (default: false)')
.action((siteDir, files, options) =>
writeHeadingIds(resolveDir(siteDir), files, options),
.action(async (siteDir, files, options) =>
writeHeadingIds(await resolveDir(siteDir), files, options),
);
cli.arguments('<command>').action((cmd) => {
@ -246,7 +254,7 @@ function isInternalCommand(command) {
async function run() {
if (!isInternalCommand(process.argv.slice(2)[0])) {
await externalCommand(cli, resolveDir('.'));
await externalCommand(cli, await resolveDir('.'));
}
cli.parse(process.argv);

View file

@ -56,6 +56,7 @@
"boxen": "^5.1.2",
"chokidar": "^3.5.3",
"clean-css": "^5.2.4",
"combine-promises": "^1.1.0",
"commander": "^5.1.0",
"copy-webpack-plugin": "^10.2.4",
"core-js": "^3.21.1",

View file

@ -130,7 +130,7 @@ async function buildLocale({
'client-manifest.json',
);
let clientConfig: Configuration = merge(
createClientConfig(props, cliOptions.minify),
await createClientConfig(props, cliOptions.minify),
{
plugins: [
// Remove/clean build folders before building bundles.
@ -148,23 +148,26 @@ async function buildLocale({
const allCollectedLinks: Record<string, string[]> = {};
let serverConfig: Configuration = createServerConfig({
let serverConfig: Configuration = await createServerConfig({
props,
onLinksCollected: (staticPagePath, links) => {
allCollectedLinks[staticPagePath] = links;
},
});
serverConfig = merge(serverConfig, {
plugins: [
new CopyWebpackPlugin({
patterns: staticDirectories
.map((dir) => path.resolve(siteDir, dir))
.filter(fs.existsSync)
.map((dir) => ({from: dir, to: outDir})),
}),
],
});
if (staticDirectories.length > 0) {
await Promise.all(staticDirectories.map((dir) => fs.ensureDir(dir)));
serverConfig = merge(serverConfig, {
plugins: [
new CopyWebpackPlugin({
patterns: staticDirectories
.map((dir) => path.resolve(siteDir, dir))
.map((dir) => ({from: dir, to: outDir})),
}),
],
});
}
// Plugin Lifecycle - configureWebpack and configurePostCss.
plugins.forEach((plugin) => {

View file

@ -107,7 +107,7 @@ export default async function start(
? (cliOptions.poll as number)
: undefined,
};
const httpsConfig = getHttpsConfig();
const httpsConfig = await getHttpsConfig();
const fsWatcher = chokidar.watch(pathsToWatch, {
cwd: siteDir,
ignoreInitial: true,
@ -118,7 +118,7 @@ export default async function start(
fsWatcher.on(event, reload),
);
let config: webpack.Configuration = merge(createClientConfig(props), {
let config: webpack.Configuration = merge(await createClientConfig(props), {
infrastructureLogging: {
// Reduce log verbosity, see https://github.com/facebook/docusaurus/pull/5420#issuecomment-906613105
level: 'warn',

View file

@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable no-restricted-properties */
import logger from '@docusaurus/logger';
import fs from 'fs-extra';
import importFresh from 'import-fresh';

View file

@ -97,7 +97,7 @@ Available locales are: ${context.i18n.locales.join(',')}.`,
const babelOptions = getBabelOptions({
isServer: true,
babelOptions: getCustomBabelConfigFilePath(siteDir),
babelOptions: await getCustomBabelConfigFilePath(siteDir),
});
const extractedCodeTranslations = await extractSiteSourceCodeTranslations(
siteDir,

View file

@ -20,6 +20,7 @@ import {
} from '@docusaurus/utils';
import {getAllFinalRoutes} from './utils';
import path from 'path';
import combinePromises from 'combine-promises';
function toReactRouterRoutes(routes: RouteConfig[]): RRRouteConfig[] {
// @ts-expect-error: types incompatible???
@ -158,9 +159,9 @@ export function getBrokenLinksErrorMessage(
);
}
function isExistingFile(filePath: string) {
async function isExistingFile(filePath: string) {
try {
return fs.statSync(filePath).isFile();
return (await fs.stat(filePath)).isFile();
} catch (e) {
return false;
}
@ -177,8 +178,7 @@ export async function filterExistingFileLinks({
outDir: string;
allCollectedLinks: Record<string, string[]>;
}): Promise<Record<string, string[]>> {
// not easy to make this async :'(
function linkFileExists(link: string): boolean {
async function linkFileExists(link: string) {
// /baseUrl/javadoc/ -> /outDir/javadoc
const baseFilePath = removeSuffix(
`${outDir}/${removePrefix(link, baseUrl)}`,
@ -194,11 +194,22 @@ export async function filterExistingFileLinks({
filePathsToTry.push(path.join(baseFilePath, 'index.html'));
}
return filePathsToTry.some(isExistingFile);
for (const file of filePathsToTry) {
if (await isExistingFile(file)) {
return true;
}
}
return false;
}
return _.mapValues(allCollectedLinks, (links) =>
links.filter((link) => !linkFileExists(link)),
return combinePromises(
_.mapValues(allCollectedLinks, async (links) =>
(
await Promise.all(
links.map(async (link) => ((await linkFileExists(link)) ? '' : link)),
)
).filter(Boolean),
),
);
}

View file

@ -13,7 +13,7 @@ import {validateConfig} from './configValidation';
export default async function loadConfig(
configPath: string,
): Promise<DocusaurusConfig> {
if (!fs.existsSync(configPath)) {
if (!(await fs.pathExists(configPath))) {
throw new Error(`Config file at "${configPath}" not found.`);
}

View file

@ -403,10 +403,12 @@ ${Object.keys(registry)
// Version metadata.
const siteMetadata: DocusaurusSiteMetadata = {
docusaurusVersion: getPackageJsonVersion(
docusaurusVersion: (await getPackageJsonVersion(
path.join(__dirname, '../../package.json'),
)!,
siteVersion: getPackageJsonVersion(path.join(siteDir, 'package.json')),
))!,
siteVersion: await getPackageJsonVersion(
path.join(siteDir, 'package.json'),
),
pluginVersions: {},
};
plugins

View file

@ -133,9 +133,9 @@ export default async function initPlugins({
// siteDir's package.json declares the dependency on these plugins.
const pluginRequire = createRequire(context.siteConfigPath);
function doGetPluginVersion(
async function doGetPluginVersion(
normalizedPluginConfig: NormalizedPluginConfig,
): DocusaurusPluginVersionInformation {
): Promise<DocusaurusPluginVersionInformation> {
// get plugin version
if (normalizedPluginConfig.pluginModule?.path) {
const pluginPath = pluginRequire.resolve(
@ -187,7 +187,7 @@ export default async function initPlugins({
pluginRequire,
);
const pluginVersion: DocusaurusPluginVersionInformation =
doGetPluginVersion(normalizedPluginConfig);
await doGetPluginVersion(normalizedPluginConfig);
const pluginOptions = doValidatePluginOptions(normalizedPluginConfig);
// Side-effect: merge the normalized theme config in the original one

View file

@ -10,10 +10,10 @@ import fs from 'fs-extra';
import themeAlias from '../alias';
describe('themeAlias', () => {
test('valid themePath 1 with components', () => {
test('valid themePath 1 with components', async () => {
const fixtures = path.join(__dirname, '__fixtures__');
const themePath = path.join(fixtures, 'theme-1');
const alias = themeAlias(themePath, true);
const alias = await themeAlias(themePath, true);
// Testing entries, because order matters!
expect(Object.entries(alias)).toEqual(
Object.entries({
@ -26,10 +26,10 @@ describe('themeAlias', () => {
expect(alias).not.toEqual({});
});
test('valid themePath 1 with components without original', () => {
test('valid themePath 1 with components without original', async () => {
const fixtures = path.join(__dirname, '__fixtures__');
const themePath = path.join(fixtures, 'theme-1');
const alias = themeAlias(themePath, false);
const alias = await themeAlias(themePath, false);
// Testing entries, because order matters!
expect(Object.entries(alias)).toEqual(
Object.entries({
@ -40,10 +40,10 @@ describe('themeAlias', () => {
expect(alias).not.toEqual({});
});
test('valid themePath 2 with components', () => {
test('valid themePath 2 with components', async () => {
const fixtures = path.join(__dirname, '__fixtures__');
const themePath = path.join(fixtures, 'theme-2');
const alias = themeAlias(themePath, true);
const alias = await themeAlias(themePath, true);
// Testing entries, because order matters!
expect(Object.entries(alias)).toEqual(
Object.entries({
@ -83,10 +83,10 @@ describe('themeAlias', () => {
expect(alias).not.toEqual({});
});
test('valid themePath 2 with components without original', () => {
test('valid themePath 2 with components without original', async () => {
const fixtures = path.join(__dirname, '__fixtures__');
const themePath = path.join(fixtures, 'theme-2');
const alias = themeAlias(themePath, false);
const alias = await themeAlias(themePath, false);
// Testing entries, because order matters!
expect(Object.entries(alias)).toEqual(
Object.entries({
@ -107,26 +107,26 @@ describe('themeAlias', () => {
expect(alias).not.toEqual({});
});
test('valid themePath with no components', () => {
test('valid themePath with no components', async () => {
const fixtures = path.join(__dirname, '__fixtures__');
const themePath = path.join(fixtures, 'empty-theme');
fs.ensureDirSync(themePath);
const alias = themeAlias(themePath, true);
await fs.ensureDir(themePath);
const alias = await themeAlias(themePath, true);
expect(alias).toEqual({});
});
test('valid themePath with no components without original', () => {
test('valid themePath with no components without original', async () => {
const fixtures = path.join(__dirname, '__fixtures__');
const themePath = path.join(fixtures, 'empty-theme');
fs.ensureDirSync(themePath);
const alias = themeAlias(themePath, false);
await fs.ensureDir(themePath);
const alias = await themeAlias(themePath, false);
expect(alias).toEqual({});
});
test('invalid themePath that does not exist', () => {
test('invalid themePath that does not exist', async () => {
const fixtures = path.join(__dirname, '__fixtures__');
const themePath = path.join(fixtures, '__noExist__');
const alias = themeAlias(themePath, true);
const alias = await themeAlias(themePath, true);
expect(alias).toEqual({});
});
});

View file

@ -9,12 +9,12 @@ import path from 'path';
import {loadThemeAliases} from '../index';
describe('loadThemeAliases', () => {
test('next alias can override the previous alias', () => {
test('next alias can override the previous alias', async () => {
const fixtures = path.join(__dirname, '__fixtures__');
const theme1Path = path.join(fixtures, 'theme-1');
const theme2Path = path.join(fixtures, 'theme-2');
const alias = loadThemeAliases([theme1Path, theme2Path], []);
const alias = await loadThemeAliases([theme1Path, theme2Path], []);
// Testing entries, because order matters!
expect(Object.entries(alias)).toEqual(

View file

@ -25,16 +25,15 @@ export function sortAliases(aliases: ThemeAliases): ThemeAliases {
return Object.fromEntries(entries);
}
// TODO make async
export default function themeAlias(
export default async function themeAlias(
themePath: string,
addOriginalAlias: boolean,
): ThemeAliases {
if (!fs.pathExistsSync(themePath)) {
): Promise<ThemeAliases> {
if (!(await fs.pathExists(themePath))) {
return {};
}
const themeComponentFiles = Globby.sync(['**/*.{js,jsx,ts,tsx}'], {
const themeComponentFiles = await Globby(['**/*.{js,jsx,ts,tsx}'], {
cwd: themePath,
});

View file

@ -12,14 +12,14 @@ import themeAlias, {sortAliases} from './alias';
const ThemeFallbackDir = path.resolve(__dirname, '../../client/theme-fallback');
export function loadThemeAliases(
export async function loadThemeAliases(
themePaths: string[],
userThemePaths: string[],
): ThemeAliases {
): Promise<ThemeAliases> {
const aliases: ThemeAliases = {};
themePaths.forEach((themePath) => {
const themeAliases = themeAlias(themePath, true);
for (const themePath of themePaths) {
const themeAliases = await themeAlias(themePath, true);
Object.keys(themeAliases).forEach((aliasKey) => {
// If this alias shadows a previous one, use @theme-init to preserve the
// initial one. @theme-init is only applied once: to the initial theme
@ -33,12 +33,12 @@ export function loadThemeAliases(
}
aliases[aliasKey] = themeAliases[aliasKey];
});
});
}
userThemePaths.forEach((themePath) => {
const userThemeAliases = themeAlias(themePath, false);
for (const themePath of userThemePaths) {
const userThemeAliases = await themeAlias(themePath, false);
Object.assign(aliases, userThemeAliases);
});
}
return sortAliases(aliases);
}
@ -49,7 +49,7 @@ export function loadPluginsThemeAliases({
}: {
siteDir: string;
plugins: LoadedPlugin[];
}): ThemeAliases {
}): Promise<ThemeAliases> {
const pluginThemes: string[] = plugins
.map((plugin) => (plugin.getThemePath ? plugin.getThemePath() : undefined))
.filter((x): x is string => Boolean(x));

View file

@ -6,7 +6,7 @@
*/
import type {RouteConfig} from '@docusaurus/types';
import nodePath from 'path';
import path from 'path';
import {posixPath, Globby} from '@docusaurus/utils';
// Recursively get the final routes (routes with no subroutes)
@ -26,7 +26,7 @@ export async function safeGlobby(
// Required for Windows support, as paths using \ should not be used by globby
// (also using the windows hard drive prefix like c: is not a good idea)
const globPaths = patterns.map((dirPath) =>
posixPath(nodePath.relative(process.cwd(), dirPath)),
posixPath(path.relative(process.cwd(), dirPath)),
);
return Globby(globPaths, options);

View file

@ -9,27 +9,27 @@ import {getPluginVersion} from '..';
import path from 'path';
describe('getPluginVersion', () => {
it('Can detect external packages plugins versions of correctly.', () => {
expect(
it('Can detect external packages plugins versions of correctly.', async () => {
await expect(
getPluginVersion(
path.join(__dirname, '..', '__fixtures__', 'dummy-plugin.js'),
// Make the plugin appear external.
path.join(__dirname, '..', '..', '..', '..', '..', '..', 'website'),
),
).toEqual({type: 'package', version: 'random-version'});
).resolves.toEqual({type: 'package', version: 'random-version'});
});
it('Can detect project plugins versions correctly.', () => {
expect(
it('Can detect project plugins versions correctly.', async () => {
await expect(
getPluginVersion(
path.join(__dirname, '..', '__fixtures__', 'dummy-plugin.js'),
// Make the plugin appear project local.
path.join(__dirname, '..', '__fixtures__'),
),
).toEqual({type: 'project'});
).resolves.toEqual({type: 'project'});
});
it('Can detect local packages versions correctly.', () => {
expect(getPluginVersion('/', '/')).toEqual({type: 'local'});
it('Can detect local packages versions correctly.', async () => {
await expect(getPluginVersion('/', '/')).resolves.toEqual({type: 'local'});
});
});

View file

@ -6,13 +6,13 @@
*/
import type {DocusaurusPluginVersionInformation} from '@docusaurus/types';
import {existsSync, lstatSync} from 'fs-extra';
import {dirname, join} from 'path';
import fs from 'fs-extra';
import path from 'path';
export function getPackageJsonVersion(
export async function getPackageJsonVersion(
packageJsonPath: string,
): string | undefined {
if (existsSync(packageJsonPath)) {
): Promise<string | undefined> {
if (await fs.pathExists(packageJsonPath)) {
// eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require, global-require
const {version} = require(packageJsonPath);
return typeof version === 'string' ? version : undefined;
@ -20,10 +20,10 @@ export function getPackageJsonVersion(
return undefined;
}
export function getPackageJsonName(
export async function getPackageJsonName(
packageJsonPath: string,
): string | undefined {
if (existsSync(packageJsonPath)) {
): Promise<string | undefined> {
if (await fs.pathExists(packageJsonPath)) {
// eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require, global-require
const {name} = require(packageJsonPath);
return typeof name === 'string' ? name : undefined;
@ -31,17 +31,20 @@ export function getPackageJsonName(
return undefined;
}
export function getPluginVersion(
export async function getPluginVersion(
pluginPath: string,
siteDir: string,
): DocusaurusPluginVersionInformation {
let potentialPluginPackageJsonDirectory = dirname(pluginPath);
): Promise<DocusaurusPluginVersionInformation> {
let potentialPluginPackageJsonDirectory = path.dirname(pluginPath);
while (potentialPluginPackageJsonDirectory !== '/') {
const packageJsonPath = join(
const packageJsonPath = path.join(
potentialPluginPackageJsonDirectory,
'package.json',
);
if (existsSync(packageJsonPath) && lstatSync(packageJsonPath).isFile()) {
if (
(await fs.pathExists(packageJsonPath)) &&
(await fs.lstat(packageJsonPath)).isFile()
) {
if (potentialPluginPackageJsonDirectory === siteDir) {
// If the plugin belongs to the same docusaurus project, we classify it
// as local plugin.
@ -49,11 +52,11 @@ export function getPluginVersion(
}
return {
type: 'package',
name: getPackageJsonName(packageJsonPath),
version: getPackageJsonVersion(packageJsonPath),
name: await getPackageJsonName(packageJsonPath),
version: await getPackageJsonVersion(packageJsonPath),
};
}
potentialPluginPackageJsonDirectory = dirname(
potentialPluginPackageJsonDirectory = path.dirname(
potentialPluginPackageJsonDirectory,
);
}

View file

@ -68,10 +68,10 @@ describe('babel transpilation exclude logic', () => {
});
describe('getDocusaurusAliases()', () => {
test('return appropriate webpack aliases', () => {
test('return appropriate webpack aliases', async () => {
// using relative paths makes tests work everywhere
const relativeDocusaurusAliases = _.mapValues(
getDocusaurusAliases(),
await getDocusaurusAliases(),
(aliasValue) => posixPath(path.relative(__dirname, aliasValue)),
);
expect(relativeDocusaurusAliases).toMatchSnapshot();
@ -120,10 +120,10 @@ describe('base webpack config', () => {
jest.restoreAllMocks();
});
test('should create webpack aliases', () => {
test('should create webpack aliases', async () => {
// @ts-expect-error: Docusaurus webpack alias is always an object
const aliases: ThemeAliases =
createBaseConfig(props, true).resolve?.alias ?? {};
(await createBaseConfig(props, true)).resolve?.alias ?? {};
// Make aliases relative so that test work on all computers
const relativeAliases = _.mapValues(aliases, (a) =>
posixPath(path.relative(props.siteDir, a)),
@ -131,14 +131,14 @@ describe('base webpack config', () => {
expect(relativeAliases).toMatchSnapshot();
});
test('should use svg rule', () => {
test('should use svg rule', async () => {
const fileLoaderUtils = utils.getFileLoaderUtils();
const mockSvg = jest.spyOn(fileLoaderUtils.rules, 'svg');
jest
.spyOn(utils, 'getFileLoaderUtils')
.mockImplementation(() => fileLoaderUtils);
createBaseConfig(props, false, false);
await createBaseConfig(props, false, false);
expect(mockSvg).toBeCalled();
});
});

View file

@ -14,7 +14,7 @@ describe('webpack dev config', () => {
test('simple', async () => {
console.log = jest.fn();
const props = await loadSetup('simple');
const config = createClientConfig(props);
const config = await createClientConfig(props);
const errors = validate(config);
expect(errors).toBeUndefined();
});
@ -22,7 +22,7 @@ describe('webpack dev config', () => {
test('custom', async () => {
console.log = jest.fn();
const props = await loadSetup('custom');
const config = createClientConfig(props);
const config = await createClientConfig(props);
const errors = validate(config);
expect(errors).toBeUndefined();
});

View file

@ -14,7 +14,7 @@ describe('webpack production config', () => {
test('simple', async () => {
console.log = jest.fn();
const props = await loadSetup('simple');
const config = createServerConfig({props});
const config = await createServerConfig({props});
const errors = validate(config);
expect(errors).toBeUndefined();
});
@ -22,7 +22,7 @@ describe('webpack production config', () => {
test('custom', async () => {
console.log = jest.fn();
const props = await loadSetup('custom');
const config = createServerConfig({props});
const config = await createServerConfig({props});
const errors = validate(config);
expect(errors).toBeUndefined();
});

View file

@ -44,13 +44,13 @@ export function excludeJS(modulePath: string): boolean {
);
}
export function getDocusaurusAliases(): Record<string, string> {
export async function getDocusaurusAliases(): Promise<Record<string, string>> {
const dirPath = path.resolve(__dirname, '../client/exports');
const extensions = ['.js', '.ts', '.tsx'];
const aliases: Record<string, string> = {};
fs.readdirSync(dirPath)
(await fs.readdir(dirPath))
.filter((fileName) => extensions.includes(path.extname(fileName)))
.forEach((fileName) => {
const fileNameWithoutExtension = path.basename(
@ -64,11 +64,11 @@ export function getDocusaurusAliases(): Record<string, string> {
return aliases;
}
export function createBaseConfig(
export async function createBaseConfig(
props: Props,
isServer: boolean,
minify: boolean = true,
): Configuration {
): Promise<Configuration> {
const {
outDir,
siteDir,
@ -90,7 +90,7 @@ export function createBaseConfig(
const name = isServer ? 'server' : 'client';
const mode = isProd ? 'production' : 'development';
const themeAliases = loadPluginsThemeAliases({siteDir, plugins});
const themeAliases = await loadPluginsThemeAliases({siteDir, plugins});
return {
mode,
@ -158,7 +158,7 @@ export function createBaseConfig(
// Note: a @docusaurus alias would also catch @docusaurus/theme-common,
// so we use fine-grained aliases instead
// '@docusaurus': path.resolve(__dirname, '../client/exports'),
...getDocusaurusAliases(),
...(await getDocusaurusAliases()),
...themeAliases,
},
// This allows you to set a fallback for where Webpack should look for
@ -169,7 +169,7 @@ export function createBaseConfig(
modules: [
path.resolve(__dirname, '..', '..', 'node_modules'),
'node_modules',
path.resolve(fs.realpathSync(process.cwd()), 'node_modules'),
path.resolve(await fs.realpath(process.cwd()), 'node_modules'),
],
},
resolveLoader: {
@ -225,7 +225,7 @@ export function createBaseConfig(
use: [
getCustomizableJSLoader(siteConfig.webpack?.jsLoader)({
isServer,
babelOptions: getCustomBabelConfigFilePath(siteDir),
babelOptions: await getCustomBabelConfigFilePath(siteDir),
}),
],
},

View file

@ -15,12 +15,12 @@ import {createBaseConfig} from './base';
import ChunkAssetPlugin from './plugins/ChunkAssetPlugin';
import LogPlugin from './plugins/LogPlugin';
export default function createClientConfig(
export default async function createClientConfig(
props: Props,
minify: boolean = true,
): Configuration {
): Promise<Configuration> {
const isBuilding = process.argv[2] === 'build';
const config = createBaseConfig(props, false, minify);
const config = await createBaseConfig(props, false, minify);
const clientConfig = merge(config, {
// useless, disabled on purpose (errors on existing sites with no

View file

@ -18,13 +18,13 @@ import {NODE_MAJOR_VERSION, NODE_MINOR_VERSION} from '@docusaurus/utils';
// Forked for Docusaurus: https://github.com/slorber/static-site-generator-webpack-plugin
import StaticSiteGeneratorPlugin from '@slorber/static-site-generator-webpack-plugin';
export default function createServerConfig({
export default async function createServerConfig({
props,
onLinksCollected = () => {},
}: {
props: Props;
onLinksCollected?: (staticPagePath: string, links: string[]) => void;
}): Configuration {
}): Promise<Configuration> {
const {
baseUrl,
routesPaths,
@ -35,7 +35,7 @@ export default function createServerConfig({
ssrTemplate,
siteConfig: {noIndex, trailingSlash},
} = props;
const config = createBaseConfig(props, true);
const config = await createBaseConfig(props, true);
const routesLocation: Record<string, string> = {};
// Array of paths to be rendered. Relative to output directory

View file

@ -101,14 +101,14 @@ export function getStyleLoaders(
];
}
export function getCustomBabelConfigFilePath(
export async function getCustomBabelConfigFilePath(
siteDir: string,
): string | undefined {
): Promise<string | undefined> {
const customBabelConfigurationPath = path.join(
siteDir,
BABEL_CONFIG_FILE_NAME,
);
return fs.existsSync(customBabelConfigurationPath)
return (await fs.pathExists(customBabelConfigurationPath))
? customBabelConfigurationPath
: undefined;
}
@ -333,19 +333,21 @@ ${err}`,
}
// Read file and throw an error if it doesn't exist
function readEnvFile(file: string, type: string) {
if (!fs.existsSync(file)) {
async function readEnvFile(file: string, type: string) {
if (!(await fs.pathExists(file))) {
throw new Error(
`You specified ${type} in your env, but the file "${file}" can't be found.`,
);
}
return fs.readFileSync(file);
return fs.readFile(file);
}
const appDirectory = fs.realpathSync(process.cwd());
// Get the https config
// Return cert files if provided in env, otherwise just true or false
export function getHttpsConfig(): boolean | {cert: Buffer; key: Buffer} {
export async function getHttpsConfig(): Promise<
boolean | {cert: Buffer; key: Buffer}
> {
const appDirectory = await fs.realpath(process.cwd());
const {SSL_CRT_FILE, SSL_KEY_FILE, HTTPS} = process.env;
const isHttps = HTTPS === 'true';
@ -353,8 +355,8 @@ export function getHttpsConfig(): boolean | {cert: Buffer; key: Buffer} {
const crtFile = path.resolve(appDirectory, SSL_CRT_FILE);
const keyFile = path.resolve(appDirectory, SSL_KEY_FILE);
const config = {
cert: readEnvFile(crtFile, 'SSL_CRT_FILE'),
key: readEnvFile(keyFile, 'SSL_KEY_FILE'),
cert: await readEnvFile(crtFile, 'SSL_CRT_FILE'),
key: await readEnvFile(keyFile, 'SSL_KEY_FILE'),
};
validateKeyAndCerts({...config, keyFile, crtFile});