feat(core): async docusaurus.config.js creator function (#6165)

This commit is contained in:
Sébastien Lorber 2021-12-22 17:03:01 +01:00 committed by GitHub
parent 5dcfa8fa23
commit f8a670966e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 249 additions and 16 deletions

View file

@ -0,0 +1,15 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
module.exports = Promise.resolve({
title: 'Hello',
tagline: 'Hello World',
organizationName: 'endiliey',
projectName: 'hello',
baseUrl: '/',
url: 'https://docusaurus.io',
});

View file

@ -0,0 +1,17 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
module.exports = function createConfig() {
return {
title: 'Hello',
tagline: 'Hello World',
organizationName: 'endiliey',
projectName: 'hello',
baseUrl: '/',
url: 'https://docusaurus.io',
};
};

View file

@ -0,0 +1,20 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
module.exports = async function createConfig() {
await new Promise((resolve) => {
setTimeout(resolve, 10);
});
return {
title: 'Hello',
tagline: 'Hello World',
organizationName: 'endiliey',
projectName: 'hello',
baseUrl: '/',
url: 'https://docusaurus.io',
};
};

View file

@ -11,6 +11,102 @@ If you still want these fields to be in your configuration, put them in the \\"c
See https://docusaurus.io/docs/docusaurus.config.js/#customfields"
`;
exports[`loadConfig website with valid async config 1`] = `
Object {
"baseUrl": "/",
"baseUrlIssueBanner": true,
"customFields": Object {},
"i18n": Object {
"defaultLocale": "en",
"localeConfigs": Object {},
"locales": Array [
"en",
],
},
"noIndex": false,
"onBrokenLinks": "throw",
"onBrokenMarkdownLinks": "warn",
"onDuplicateRoutes": "warn",
"organizationName": "endiliey",
"plugins": Array [],
"presets": Array [],
"projectName": "hello",
"staticDirectories": Array [
"static",
],
"tagline": "Hello World",
"themeConfig": Object {},
"themes": Array [],
"title": "Hello",
"titleDelimiter": "|",
"url": "https://docusaurus.io",
}
`;
exports[`loadConfig website with valid async config creator function 1`] = `
Object {
"baseUrl": "/",
"baseUrlIssueBanner": true,
"customFields": Object {},
"i18n": Object {
"defaultLocale": "en",
"localeConfigs": Object {},
"locales": Array [
"en",
],
},
"noIndex": false,
"onBrokenLinks": "throw",
"onBrokenMarkdownLinks": "warn",
"onDuplicateRoutes": "warn",
"organizationName": "endiliey",
"plugins": Array [],
"presets": Array [],
"projectName": "hello",
"staticDirectories": Array [
"static",
],
"tagline": "Hello World",
"themeConfig": Object {},
"themes": Array [],
"title": "Hello",
"titleDelimiter": "|",
"url": "https://docusaurus.io",
}
`;
exports[`loadConfig website with valid config creator function 1`] = `
Object {
"baseUrl": "/",
"baseUrlIssueBanner": true,
"customFields": Object {},
"i18n": Object {
"defaultLocale": "en",
"localeConfigs": Object {},
"locales": Array [
"en",
],
},
"noIndex": false,
"onBrokenLinks": "throw",
"onBrokenMarkdownLinks": "warn",
"onDuplicateRoutes": "warn",
"organizationName": "endiliey",
"plugins": Array [],
"presets": Array [],
"projectName": "hello",
"staticDirectories": Array [
"static",
],
"tagline": "Hello World",
"themeConfig": Object {},
"themes": Array [],
"title": "Hello",
"titleDelimiter": "|",
"url": "https://docusaurus.io",
}
`;
exports[`loadConfig website with valid siteConfig 1`] = `
Object {
"baseUrl": "/",

View file

@ -16,45 +16,75 @@ describe('loadConfig', () => {
'simple-site',
'docusaurus.config.js',
);
const config = loadConfig(siteDir);
const config = await loadConfig(siteDir);
expect(config).toMatchSnapshot();
expect(config).not.toEqual({});
});
test('website with incomplete siteConfig', () => {
test('website with valid config creator function', async () => {
const siteDir = path.join(
__dirname,
'__fixtures__',
'configs',
'createConfig.config.js',
);
const config = await loadConfig(siteDir);
expect(config).toMatchSnapshot();
expect(config).not.toEqual({});
});
test('website with valid async config', async () => {
const siteDir = path.join(
__dirname,
'__fixtures__',
'configs',
'configAsync.config.js',
);
const config = await loadConfig(siteDir);
expect(config).toMatchSnapshot();
expect(config).not.toEqual({});
});
test('website with valid async config creator function', async () => {
const siteDir = path.join(
__dirname,
'__fixtures__',
'configs',
'createConfigAsync.config.js',
);
const config = await loadConfig(siteDir);
expect(config).toMatchSnapshot();
expect(config).not.toEqual({});
});
test('website with incomplete siteConfig', async () => {
const siteDir = path.join(
__dirname,
'__fixtures__',
'bad-site',
'docusaurus.config.js',
);
expect(() => {
loadConfig(siteDir);
}).toThrowErrorMatchingSnapshot();
await expect(loadConfig(siteDir)).rejects.toThrowErrorMatchingSnapshot();
});
test('website with useless field (wrong field) in siteConfig', () => {
test('website with useless field (wrong field) in siteConfig', async () => {
const siteDir = path.join(
__dirname,
'__fixtures__',
'wrong-site',
'docusaurus.config.js',
);
expect(() => {
loadConfig(siteDir);
}).toThrowErrorMatchingSnapshot();
await expect(loadConfig(siteDir)).rejects.toThrowErrorMatchingSnapshot();
});
test('website with no siteConfig', () => {
test('website with no siteConfig', async () => {
const siteDir = path.join(
__dirname,
'__fixtures__',
'nonExisting',
'docusaurus.config.js',
);
expect(() => {
loadConfig(siteDir);
}).toThrowError(
await expect(loadConfig(siteDir)).rejects.toThrowError(
/Config file at "(.*?)__fixtures__[/\\]nonExisting[/\\]docusaurus.config.js" not found.$/,
);
});

View file

@ -10,11 +10,23 @@ import importFresh from 'import-fresh';
import {DocusaurusConfig} from '@docusaurus/types';
import {validateConfig} from './configValidation';
export default function loadConfig(configPath: string): DocusaurusConfig {
export default async function loadConfig(
configPath: string,
): Promise<DocusaurusConfig> {
if (!fs.existsSync(configPath)) {
throw new Error(`Config file at "${configPath}" not found.`);
}
const loadedConfig = importFresh(configPath) as Partial<DocusaurusConfig>;
const importedConfig = importFresh(configPath) as
| Partial<DocusaurusConfig>
| Promise<Partial<DocusaurusConfig>>
| (() => Partial<DocusaurusConfig>)
| (() => Promise<Partial<DocusaurusConfig>>);
const loadedConfig =
importedConfig instanceof Function
? await importedConfig()
: await importedConfig;
return validateConfig(loadedConfig);
}

View file

@ -11,6 +11,41 @@ slug: /api/docusaurus-config
`docusaurus.config.js` contains configurations for your site and is placed in the root directory of your site.
It usually exports a site configuration object:
```js title="docusaurus.config.js"
module.exports = {
// site config...
};
```
<details>
<summary>Config files also support config creator functions and async code.</summary>
```js title="docusaurus.config.js"
module.exports = function configCreator() {
return {
// site config...
};
};
```
```js title="docusaurus.config.js"
module.exports = async function configCreatorAsync() {
return {
// site config...
};
};
```
```js title="docusaurus.config.js"
module.exports = Promise.resolve({
// site config...
});
```
</details>
## Required fields {#required-fields}
### `title` {#title}

View file

@ -515,4 +515,12 @@ const config = {
}),
};
module.exports = config;
// TODO temporary dogfood async config, remove soon
async function createConfig() {
await new Promise((resolve) => {
setTimeout(resolve, 0);
});
return config;
}
module.exports = createConfig;