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

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

Merged
merged 2 commits into from
Dec 22, 2021
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
Original file line number Diff line number Diff line change
@@ -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',
});
Original file line number Diff line number Diff line change
@@ -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',
};
};
Original file line number Diff line number Diff line change
@@ -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',
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -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": "/",
Expand Down
56 changes: 43 additions & 13 deletions packages/docusaurus/src/server/__tests__/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.$/,
);
});
Expand Down
16 changes: 14 additions & 2 deletions packages/docusaurus/src/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
35 changes: 35 additions & 0 deletions website/docs/api/docusaurus.config.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
10 changes: 9 additions & 1 deletion website/docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;