Support integrations added in updateConfig() in astro:config:setup (#8672)
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
This commit is contained in:
parent
e8495c853b
commit
9b0114c7d3
3 changed files with 95 additions and 2 deletions
34
.changeset/cold-schools-yell.md
Normal file
34
.changeset/cold-schools-yell.md
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
---
|
||||||
|
'astro': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Support adding integrations dynamically
|
||||||
|
|
||||||
|
Astro integrations can now themselves dynamically add and configure additional integrations during set-up. This makes it possible for integration authors to bundle integrations more intelligently for their users.
|
||||||
|
|
||||||
|
In the following example, a custom integration checks whether `@astrojs/sitemap` is already configured. If not, the integration adds Astro’s sitemap integration, passing any desired configuration options:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import sitemap from '@astrojs/sitemap';
|
||||||
|
import type { AstroIntegration } from 'astro';
|
||||||
|
|
||||||
|
const MyIntegration = (): AstroIntegration => {
|
||||||
|
return {
|
||||||
|
name: 'my-integration',
|
||||||
|
|
||||||
|
'astro:config:setup': ({ config, updateConfig }) => {
|
||||||
|
// Look for sitemap in user-configured integrations.
|
||||||
|
const userSitemap = config.integrations.find(
|
||||||
|
({ name }) => name === '@astrojs/sitemap'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!userSitemap) {
|
||||||
|
// If sitemap wasn’t found, add it.
|
||||||
|
updateConfig({
|
||||||
|
integrations: [sitemap({ /* opts */ }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
|
@ -75,7 +75,10 @@ export async function runHookConfigSetup({
|
||||||
let addedClientDirectives = new Map<string, Promise<string>>();
|
let addedClientDirectives = new Map<string, Promise<string>>();
|
||||||
let astroJSXRenderer: AstroRenderer | null = null;
|
let astroJSXRenderer: AstroRenderer | null = null;
|
||||||
|
|
||||||
for (const integration of settings.config.integrations) {
|
// eslint-disable-next-line @typescript-eslint/prefer-for-of -- We need a for loop to be able to read integrations pushed while the loop is running.
|
||||||
|
for (let i = 0; i < updatedConfig.integrations.length; i++) {
|
||||||
|
const integration = updatedConfig.integrations[i];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* By making integration hooks optional, Astro can now ignore null or undefined Integrations
|
* By making integration hooks optional, Astro can now ignore null or undefined Integrations
|
||||||
* instead of giving an internal error most people can't read
|
* instead of giving an internal error most people can't read
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
import { runHookBuildSetup } from '../../../dist/integrations/index.js';
|
import { runHookBuildSetup, runHookConfigSetup } from '../../../dist/integrations/index.js';
|
||||||
import { validateSupportedFeatures } from '../../../dist/integrations/astroFeaturesValidation.js';
|
import { validateSupportedFeatures } from '../../../dist/integrations/astroFeaturesValidation.js';
|
||||||
import { defaultLogger } from '../test-utils.js';
|
import { defaultLogger } from '../test-utils.js';
|
||||||
|
|
||||||
|
@ -29,6 +29,62 @@ describe('Integration API', () => {
|
||||||
});
|
});
|
||||||
expect(updatedViteConfig).to.haveOwnProperty('define');
|
expect(updatedViteConfig).to.haveOwnProperty('define');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('runHookConfigSetup can update Astro config', async () => {
|
||||||
|
const site = 'https://test.com/';
|
||||||
|
const updatedSettings = await runHookConfigSetup({
|
||||||
|
logger: defaultLogger,
|
||||||
|
settings: {
|
||||||
|
config: {
|
||||||
|
integrations: [
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
hooks: {
|
||||||
|
"astro:config:setup": ({ updateConfig }) => {
|
||||||
|
updateConfig({ site });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(updatedSettings.config.site).to.equal(site);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('runHookConfigSetup runs integrations added by another integration', async () => {
|
||||||
|
const site = 'https://test.com/';
|
||||||
|
const updatedSettings = await runHookConfigSetup({
|
||||||
|
logger: defaultLogger,
|
||||||
|
settings: {
|
||||||
|
config: {
|
||||||
|
integrations: [
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
hooks: {
|
||||||
|
"astro:config:setup": ({ updateConfig }) => {
|
||||||
|
updateConfig({
|
||||||
|
integrations: [{
|
||||||
|
name: 'dynamically-added',
|
||||||
|
hooks: {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||||
|
"astro:config:setup": ({ updateConfig }) => {
|
||||||
|
updateConfig({ site });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(updatedSettings.config.site).to.equal(site);
|
||||||
|
expect(updatedSettings.config.integrations.length).to.equal(2);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Astro feature map', function () {
|
describe('Astro feature map', function () {
|
||||||
|
|
Loading…
Add table
Reference in a new issue