summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/dirty-lies-cover.md32
-rw-r--r--packages/astro/src/@types/astro.ts39
-rw-r--r--packages/astro/src/assets/generate.ts5
-rw-r--r--packages/astro/src/assets/vite-plugin-assets.ts27
-rw-r--r--packages/astro/src/integrations/astroFeaturesValidation.ts162
-rw-r--r--packages/astro/src/integrations/index.ts27
-rw-r--r--packages/astro/test/featuresSupport.test.js55
-rw-r--r--packages/astro/test/test-adapter.js9
-rw-r--r--packages/astro/test/units/integrations/api.test.js186
-rw-r--r--packages/integrations/cloudflare/src/index.ts20
-rw-r--r--packages/integrations/cloudflare/test/fixtures/basics/astro.config.mjs2
-rw-r--r--packages/integrations/deno/src/index.ts10
-rw-r--r--packages/integrations/deno/test/fixtures/basics/astro.config.mjs2
-rw-r--r--packages/integrations/deno/test/fixtures/dynimport/astro.config.mjs2
-rw-r--r--packages/integrations/netlify/src/integration-edge-functions.ts10
-rw-r--r--packages/integrations/netlify/src/integration-functions.ts10
-rw-r--r--packages/integrations/node/src/index.ts10
-rw-r--r--packages/integrations/vercel/src/edge/adapter.ts10
-rw-r--r--packages/integrations/vercel/src/serverless/adapter.ts10
-rw-r--r--packages/integrations/vercel/test/no-output.test.js2
20 files changed, 598 insertions, 32 deletions
diff --git a/.changeset/dirty-lies-cover.md b/.changeset/dirty-lies-cover.md
new file mode 100644
index 000000000..ae74e348e
--- /dev/null
+++ b/.changeset/dirty-lies-cover.md
@@ -0,0 +1,32 @@
+---
+'@astrojs/cloudflare': minor
+'@astrojs/netlify': minor
+'@astrojs/vercel': minor
+'@astrojs/deno': minor
+'@astrojs/node': minor
+'astro': minor
+---
+
+Introduced the concept of feature map. A feature map is a list of features that are built-in in Astro, and an Adapter
+can tell Astro if it can support it.
+
+```ts
+import {AstroIntegration} from "./astro";
+
+function myIntegration(): AstroIntegration {
+ return {
+ name: 'astro-awesome-list',
+ // new feature map
+ supportedAstroFeatures: {
+ hybridOutput: 'experimental',
+ staticOutput: 'stable',
+ serverOutput: 'stable',
+ assets: {
+ supportKind: 'stable',
+ isSharpCompatible: false,
+ isSquooshCompatible: false,
+ },
+ }
+ }
+}
+```
diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts
index eb19900d3..dc710ec2f 100644
--- a/packages/astro/src/@types/astro.ts
+++ b/packages/astro/src/@types/astro.ts
@@ -1685,6 +1685,39 @@ export type PaginateFunction = (data: any[], args?: PaginateOptions) => GetStati
export type Params = Record<string, string | undefined>;
+export type SupportsKind = 'unsupported' | 'stable' | 'experimental' | 'deprecated';
+
+export type AstroFeatureMap = {
+ /**
+ * The adapter is able serve static pages
+ */
+ staticOutput?: SupportsKind;
+ /**
+ * The adapter is able to serve pages that are static or rendered via server
+ */
+ hybridOutput?: SupportsKind;
+ /**
+ * The adapter is able to serve SSR pages
+ */
+ serverOutput?: SupportsKind;
+ /**
+ * The adapter can emit static assets
+ */
+ assets?: AstroAssetsFeature;
+};
+
+export interface AstroAssetsFeature {
+ supportKind?: SupportsKind;
+ /**
+ * Whether if this adapter deploys files in an enviroment that is compatible with the library `sharp`
+ */
+ isSharpCompatible?: boolean;
+ /**
+ * Whether if this adapter deploys files in an enviroment that is compatible with the library `squoosh`
+ */
+ isSquooshCompatible?: boolean;
+}
+
export interface AstroAdapter {
name: string;
serverEntrypoint?: string;
@@ -1692,6 +1725,12 @@ export interface AstroAdapter {
exports?: string[];
args?: any;
adapterFeatures?: AstroAdapterFeatures;
+ /**
+ * List of features supported by an adapter.
+ *
+ * If the adapter is not able to handle certain configurations, Astro will throw an error.
+ */
+ supportedAstroFeatures?: AstroFeatureMap;
}
type Body = string;
diff --git a/packages/astro/src/assets/generate.ts b/packages/astro/src/assets/generate.ts
index d6cb02e56..04488ed8f 100644
--- a/packages/astro/src/assets/generate.ts
+++ b/packages/astro/src/assets/generate.ts
@@ -27,6 +27,11 @@ export async function generateImage(
options: ImageTransform,
filepath: string
): Promise<GenerationData | undefined> {
+ if (typeof buildOpts.settings.config.image === 'undefined') {
+ throw new Error(
+ "Astro hasn't set a default service for `astro:assets`. This is an internal error and you should report it."
+ );
+ }
if (!isESMImportedImage(options.src)) {
return undefined;
}
diff --git a/packages/astro/src/assets/vite-plugin-assets.ts b/packages/astro/src/assets/vite-plugin-assets.ts
index 565253001..2ab87b7c1 100644
--- a/packages/astro/src/assets/vite-plugin-assets.ts
+++ b/packages/astro/src/assets/vite-plugin-assets.ts
@@ -1,10 +1,8 @@
-import { bold } from 'kleur/colors';
import MagicString from 'magic-string';
import { fileURLToPath } from 'node:url';
import type * as vite from 'vite';
import { normalizePath } from 'vite';
import type { AstroPluginOptions, ImageTransform } from '../@types/astro';
-import { error } from '../core/logger/core.js';
import {
appendForwardSlash,
joinPaths,
@@ -23,37 +21,12 @@ const urlRE = /(\?|&)url(?:&|$)/;
export default function assets({
settings,
- logging,
mode,
}: AstroPluginOptions & { mode: string }): vite.Plugin[] {
let resolvedConfig: vite.ResolvedConfig;
globalThis.astroAsset = {};
- const UNSUPPORTED_ADAPTERS = new Set([
- '@astrojs/cloudflare',
- '@astrojs/deno',
- '@astrojs/netlify/edge-functions',
- '@astrojs/vercel/edge',
- ]);
-
- const adapterName = settings.config.adapter?.name;
- if (
- ['astro/assets/services/sharp', 'astro/assets/services/squoosh'].includes(
- settings.config.image.service.entrypoint
- ) &&
- adapterName &&
- UNSUPPORTED_ADAPTERS.has(adapterName)
- ) {
- error(
- logging,
- 'assets',
- `The currently selected adapter \`${adapterName}\` does not run on Node, however the currently used image service depends on Node built-ins. ${bold(
- 'Your project will NOT be able to build.'
- )}`
- );
- }
-
return [
// Expose the components and different utilities from `astro:assets` and handle serving images from `/_image` in dev
{
diff --git a/packages/astro/src/integrations/astroFeaturesValidation.ts b/packages/astro/src/integrations/astroFeaturesValidation.ts
new file mode 100644
index 000000000..6b92813c5
--- /dev/null
+++ b/packages/astro/src/integrations/astroFeaturesValidation.ts
@@ -0,0 +1,162 @@
+import type {
+ AstroAssetsFeature,
+ AstroConfig,
+ AstroFeatureMap,
+ SupportsKind,
+} from '../@types/astro';
+import { error, type LogOptions, warn } from '../core/logger/core.js';
+import { bold } from 'kleur/colors';
+
+const STABLE = 'stable';
+const DEPRECATED = 'deprecated';
+const UNSUPPORTED = 'unsupported';
+const EXPERIMENTAL = 'experimental';
+
+const UNSUPPORTED_ASSETS_FEATURE: AstroAssetsFeature = {
+ supportKind: UNSUPPORTED,
+ isSquooshCompatible: false,
+ isSharpCompatible: false,
+};
+
+// NOTE: remove for Astro 4.0
+const ALL_UNSUPPORTED: Required<AstroFeatureMap> = {
+ serverOutput: UNSUPPORTED,
+ staticOutput: UNSUPPORTED,
+ hybridOutput: UNSUPPORTED,
+ assets: UNSUPPORTED_ASSETS_FEATURE,
+};
+
+type ValidationResult = {
+ [Property in keyof AstroFeatureMap]: boolean;
+};
+
+/**
+ * Checks whether an adapter supports certain features that are enabled via Astro configuration.
+ *
+ * If a configuration is enabled and "unlocks" a feature, but the adapter doesn't support, the function
+ * will throw a runtime error.
+ *
+ */
+export function validateSupportedFeatures(
+ adapterName: string,
+ featureMap: AstroFeatureMap = ALL_UNSUPPORTED,
+ config: AstroConfig,
+ logging: LogOptions
+): ValidationResult {
+ const {
+ assets = UNSUPPORTED_ASSETS_FEATURE,
+ serverOutput = UNSUPPORTED,
+ staticOutput = UNSUPPORTED,
+ hybridOutput = UNSUPPORTED,
+ } = featureMap;
+ const validationResult: ValidationResult = {};
+
+ validationResult.staticOutput = validateSupportKind(
+ staticOutput,
+ adapterName,
+ logging,
+ 'staticOutput',
+ () => config?.output === 'static'
+ );
+
+ validationResult.hybridOutput = validateSupportKind(
+ hybridOutput,
+ adapterName,
+ logging,
+ 'hybridOutput',
+ () => config?.output === 'hybrid'
+ );
+
+ validationResult.serverOutput = validateSupportKind(
+ serverOutput,
+ adapterName,
+ logging,
+ 'serverOutput',
+ () => config?.output === 'server'
+ );
+ validationResult.assets = validateAssetsFeature(assets, adapterName, config, logging);
+
+ return validationResult;
+}
+
+function validateSupportKind(
+ supportKind: SupportsKind,
+ adapterName: string,
+ logging: LogOptions,
+ featureName: string,
+ hasCorrectConfig: () => boolean
+): boolean {
+ if (supportKind === STABLE) {
+ return true;
+ } else if (supportKind === DEPRECATED) {
+ featureIsDeprecated(adapterName, logging);
+ } else if (supportKind === EXPERIMENTAL) {
+ featureIsExperimental(adapterName, logging);
+ }
+
+ if (hasCorrectConfig() && supportKind === UNSUPPORTED) {
+ featureIsUnsupported(adapterName, logging, featureName);
+ return false;
+ } else {
+ return true;
+ }
+}
+
+function featureIsUnsupported(adapterName: string, logging: LogOptions, featureName: string) {
+ error(
+ logging,
+ `${adapterName}`,
+ `The feature ${featureName} is not supported by the adapter ${adapterName}.`
+ );
+}
+
+function featureIsExperimental(adapterName: string, logging: LogOptions) {
+ warn(logging, `${adapterName}`, 'The feature is experimental and subject to issues or changes.');
+}
+
+function featureIsDeprecated(adapterName: string, logging: LogOptions) {
+ warn(
+ logging,
+ `${adapterName}`,
+ 'The feature is deprecated and will be moved in the next release.'
+ );
+}
+
+const SHARP_SERVICE = 'astro/assets/services/sharp';
+const SQUOOSH_SERVICE = 'astro/assets/services/squoosh';
+
+function validateAssetsFeature(
+ assets: AstroAssetsFeature,
+ adapterName: string,
+ config: AstroConfig,
+ logging: LogOptions
+): boolean {
+ const {
+ supportKind = UNSUPPORTED,
+ isSharpCompatible = false,
+ isSquooshCompatible = false,
+ } = assets;
+ if (config?.image?.service?.entrypoint === SHARP_SERVICE && !isSharpCompatible) {
+ error(
+ logging,
+ 'astro',
+ `The currently selected adapter \`${adapterName}\` is not compatible with the service "Sharp". ${bold(
+ 'Your project will NOT be able to build.'
+ )}`
+ );
+ return false;
+ }
+
+ if (config?.image?.service?.entrypoint === SQUOOSH_SERVICE && !isSquooshCompatible) {
+ error(
+ logging,
+ 'astro',
+ `The currently selected adapter \`${adapterName}\` is not compatible with the service "Squoosh". ${bold(
+ 'Your project will NOT be able to build.'
+ )}`
+ );
+ return false;
+ }
+
+ return validateSupportKind(supportKind, adapterName, logging, 'assets', () => true);
+}
diff --git a/packages/astro/src/integrations/index.ts b/packages/astro/src/integrations/index.ts
index ab9898523..75971fa53 100644
--- a/packages/astro/src/integrations/index.ts
+++ b/packages/astro/src/integrations/index.ts
@@ -18,8 +18,9 @@ import type { SerializedSSRManifest } from '../core/app/types';
import type { PageBuildData } from '../core/build/types';
import { buildClientDirectiveEntrypoint } from '../core/client-directive/index.js';
import { mergeConfig } from '../core/config/index.js';
-import { info, type LogOptions, AstroIntegrationLogger } from '../core/logger/core.js';
+import { info, warn, error, type LogOptions, AstroIntegrationLogger } from '../core/logger/core.js';
import { isServerLikeOutput } from '../prerender/utils.js';
+import { validateSupportedFeatures } from './astroFeaturesValidation.js';
async function withTakingALongTimeMsg<T>({
name,
@@ -197,6 +198,30 @@ export async function runHookConfigDone({
`Integration "${integration.name}" conflicts with "${settings.adapter.name}". You can only configure one deployment integration.`
);
}
+ if (!adapter.supportedAstroFeatures) {
+ // NOTE: throw an error in Astro 4.0
+ warn(
+ logging,
+ 'astro',
+ `The adapter ${adapter.name} doesn't provide a feature map. From Astro 3.0, an adapter can provide a feature map. Not providing a feature map will cause an error in Astro 4.0.`
+ );
+ } else {
+ const validationResult = validateSupportedFeatures(
+ adapter.name,
+ adapter.supportedAstroFeatures,
+ settings.config,
+ logging
+ );
+ for (const [featureName, supported] of Object.entries(validationResult)) {
+ if (!supported) {
+ error(
+ logging,
+ 'astro',
+ `The adapter ${adapter.name} doesn't support the feature ${featureName}. Your project won't be built. You should not use it.`
+ );
+ }
+ }
+ }
settings.adapter = adapter;
},
logger,
diff --git a/packages/astro/test/featuresSupport.test.js b/packages/astro/test/featuresSupport.test.js
new file mode 100644
index 000000000..fba8da475
--- /dev/null
+++ b/packages/astro/test/featuresSupport.test.js
@@ -0,0 +1,55 @@
+import { loadFixture } from './test-utils.js';
+import { expect } from 'chai';
+import testAdapter from './test-adapter.js';
+
+describe('Adapter', () => {
+ let fixture;
+
+ it("should error if the adapter doesn't support edge middleware", async () => {
+ try {
+ fixture = await loadFixture({
+ root: './fixtures/middleware-dev/',
+ output: 'server',
+ build: {
+ excludeMiddleware: true,
+ },
+ adapter: testAdapter({
+ extendAdapter: {
+ supportsFeatures: {
+ edgeMiddleware: 'Unsupported',
+ },
+ },
+ }),
+ });
+ await fixture.build();
+ } catch (e) {
+ expect(e.toString()).to.contain(
+ "The adapter my-ssr-adapter doesn't support the feature build.excludeMiddleware."
+ );
+ }
+ });
+
+ it("should error if the adapter doesn't support split build", async () => {
+ try {
+ fixture = await loadFixture({
+ root: './fixtures/middleware-dev/',
+ output: 'server',
+ build: {
+ split: true,
+ },
+ adapter: testAdapter({
+ extendAdapter: {
+ supportsFeatures: {
+ functionPerPage: 'Unsupported',
+ },
+ },
+ }),
+ });
+ await fixture.build();
+ } catch (e) {
+ expect(e.toString()).to.contain(
+ "The adapter my-ssr-adapter doesn't support the feature build.split."
+ );
+ }
+ });
+});
diff --git a/packages/astro/test/test-adapter.js b/packages/astro/test/test-adapter.js
index 85b4d69c0..67058023d 100644
--- a/packages/astro/test/test-adapter.js
+++ b/packages/astro/test/test-adapter.js
@@ -71,6 +71,15 @@ export default function (
name: 'my-ssr-adapter',
serverEntrypoint: '@my-ssr',
exports: ['manifest', 'createApp'],
+ supportedFeatures: {
+ assets: {
+ supportKind: 'Stable',
+ isNodeCompatible: true,
+ },
+ serverOutput: 'Stable',
+ staticOutput: 'Stable',
+ hybridOutput: 'Stable',
+ },
...extendAdapter,
});
},
diff --git a/packages/astro/test/units/integrations/api.test.js b/packages/astro/test/units/integrations/api.test.js
index 919628da2..a420dd6c9 100644
--- a/packages/astro/test/units/integrations/api.test.js
+++ b/packages/astro/test/units/integrations/api.test.js
@@ -1,5 +1,7 @@
import { expect } from 'chai';
import { runHookBuildSetup } from '../../../dist/integrations/index.js';
+import { validateSupportedFeatures } from '../../../dist/integrations/astroFeaturesValidation.js';
+import { defaultLogging } from '../test-utils.js';
describe('Integration API', () => {
it('runHookBuildSetup should work', async () => {
@@ -28,3 +30,187 @@ describe('Integration API', () => {
expect(updatedViteConfig).to.haveOwnProperty('define');
});
});
+
+describe('Astro feature map', function () {
+ it('should support the feature when stable', () => {
+ let result = validateSupportedFeatures(
+ 'test',
+ {
+ hybridOutput: 'stable',
+ },
+ {
+ output: 'hybrid',
+ },
+ defaultLogging
+ );
+ expect(result['hybridOutput']).to.be.true;
+ });
+
+ it('should not support the feature when not provided', () => {
+ let result = validateSupportedFeatures(
+ 'test',
+ undefined,
+ {
+ output: 'hybrid',
+ },
+ defaultLogging
+ );
+ expect(result['hybridOutput']).to.be.false;
+ });
+
+ it('should not support the feature when an empty object is provided', () => {
+ let result = validateSupportedFeatures(
+ 'test',
+ {},
+ {
+ output: 'hybrid',
+ },
+ defaultLogging
+ );
+ expect(result['hybridOutput']).to.be.false;
+ });
+
+ describe('static output', function () {
+ it('should be supported with the correct config', () => {
+ let result = validateSupportedFeatures(
+ 'test',
+ { staticOutput: 'stable' },
+ {
+ output: 'static',
+ },
+ defaultLogging
+ );
+ expect(result['staticOutput']).to.be.true;
+ });
+
+ it("should not be valid if the config is correct, but the it's unsupported", () => {
+ let result = validateSupportedFeatures(
+ 'test',
+ { staticOutput: 'unsupported' },
+ {
+ output: 'static',
+ },
+ defaultLogging
+ );
+ expect(result['staticOutput']).to.be.false;
+ });
+ });
+ describe('hybrid output', function () {
+ it('should be supported with the correct config', () => {
+ let result = validateSupportedFeatures(
+ 'test',
+ { hybridOutput: 'stable' },
+ {
+ output: 'hybrid',
+ },
+ defaultLogging
+ );
+ expect(result['hybridOutput']).to.be.true;
+ });
+
+ it("should not be valid if the config is correct, but the it's unsupported", () => {
+ let result = validateSupportedFeatures(
+ 'test',
+ {
+ hybridOutput: 'unsupported',
+ },
+ {
+ output: 'hybrid',
+ },
+ defaultLogging
+ );
+ expect(result['hybridOutput']).to.be.false;
+ });
+ });
+ describe('server output', function () {
+ it('should be supported with the correct config', () => {
+ let result = validateSupportedFeatures(
+ 'test',
+ { serverOutput: 'stable' },
+ {
+ output: 'server',
+ },
+ defaultLogging
+ );
+ expect(result['serverOutput']).to.be.true;
+ });
+
+ it("should not be valid if the config is correct, but the it's unsupported", () => {
+ let result = validateSupportedFeatures(
+ 'test',
+ {
+ serverOutput: 'unsupported',
+ },
+ {
+ output: 'server',
+ },
+ defaultLogging
+ );
+ expect(result['serverOutput']).to.be.false;
+ });
+ });
+
+ describe('assets', function () {
+ it('should be supported when it is sharp compatible', () => {
+ let result = validateSupportedFeatures(
+ 'test',
+ {
+ assets: {
+ supportKind: 'stable',
+ isSharpCompatible: true,
+ },
+ },
+ {
+ image: {
+ service: {
+ entrypoint: 'astro/assets/services/sharp',
+ },
+ },
+ },
+ defaultLogging
+ );
+ expect(result['assets']).to.be.true;
+ });
+ it('should be supported when it is squoosh compatible', () => {
+ let result = validateSupportedFeatures(
+ 'test',
+ {
+ assets: {
+ supportKind: 'stable',
+ isSquooshCompatible: true,
+ },
+ },
+ {
+ image: {
+ service: {
+ entrypoint: 'astro/assets/services/squoosh',
+ },
+ },
+ },
+ defaultLogging
+ );
+ expect(result['assets']).to.be.true;
+ });
+
+ it("should not be valid if the config is correct, but the it's unsupported", () => {
+ let result = validateSupportedFeatures(
+ 'test',
+ {
+ assets: {
+ supportKind: 'unsupported',
+ isNodeCompatible: false,
+ },
+ },
+ {
+ image: {
+ service: {
+ entrypoint: 'astro/assets/services/sharp',
+ },
+ },
+ },
+ defaultLogging
+ );
+ expect(result['assets']).to.be.false;
+ });
+ });
+});
diff --git a/packages/integrations/cloudflare/src/index.ts b/packages/integrations/cloudflare/src/index.ts
index ef452aa95..a3bb76fbb 100644
--- a/packages/integrations/cloudflare/src/index.ts
+++ b/packages/integrations/cloudflare/src/index.ts
@@ -24,11 +24,31 @@ export function getAdapter(isModeDirectory: boolean): AstroAdapter {
name: '@astrojs/cloudflare',
serverEntrypoint: '@astrojs/cloudflare/server.directory.js',
exports: ['onRequest', 'manifest'],
+ supportedAstroFeatures: {
+ hybridOutput: 'stable',
+ staticOutput: 'unsupported',
+ serverOutput: 'stable',
+ assets: {
+ supportKind: 'unsupported',
+ isSharpCompatible: false,
+ isSquooshCompatible: false,
+ },
+ },
}
: {
name: '@astrojs/cloudflare',
serverEntrypoint: '@astrojs/cloudflare/server.advanced.js',
exports: ['default'],
+ supportedAstroFeatures: {
+ hybridOutput: 'stable',
+ staticOutput: 'unsupported',
+ serverOutput: 'stable',
+ assets: {
+ supportKind: 'stable',
+ isSharpCompatible: false,
+ isSquooshCompatible: false,
+ },
+ },
};
}
diff --git a/packages/integrations/cloudflare/test/fixtures/basics/astro.config.mjs b/packages/integrations/cloudflare/test/fixtures/basics/astro.config.mjs
index 105247b1b..407dc4355 100644
--- a/packages/integrations/cloudflare/test/fixtures/basics/astro.config.mjs
+++ b/packages/integrations/cloudflare/test/fixtures/basics/astro.config.mjs
@@ -6,5 +6,5 @@ process.env.SECRET_STUFF = 'secret'
export default defineConfig({
adapter: cloudflare(),
- output: 'server',
+ output: 'server'
});
diff --git a/packages/integrations/deno/src/index.ts b/packages/integrations/deno/src/index.ts
index db645eb69..3b011c830 100644
--- a/packages/integrations/deno/src/index.ts
+++ b/packages/integrations/deno/src/index.ts
@@ -89,6 +89,16 @@ export function getAdapter(args?: Options): AstroAdapter {
serverEntrypoint: '@astrojs/deno/server.js',
args: args ?? {},
exports: ['stop', 'handle', 'start', 'running'],
+ supportedAstroFeatures: {
+ hybridOutput: 'stable',
+ staticOutput: 'stable',
+ serverOutput: 'stable',
+ assets: {
+ supportKind: 'stable',
+ isSharpCompatible: false,
+ isSquooshCompatible: false,
+ },
+ },
};
}
diff --git a/packages/integrations/deno/test/fixtures/basics/astro.config.mjs b/packages/integrations/deno/test/fixtures/basics/astro.config.mjs
index b5187f891..cf80fdb2e 100644
--- a/packages/integrations/deno/test/fixtures/basics/astro.config.mjs
+++ b/packages/integrations/deno/test/fixtures/basics/astro.config.mjs
@@ -6,5 +6,5 @@ import mdx from '@astrojs/mdx';
export default defineConfig({
adapter: deno(),
integrations: [react(), mdx()],
- output: 'server',
+ output: 'server'
})
diff --git a/packages/integrations/deno/test/fixtures/dynimport/astro.config.mjs b/packages/integrations/deno/test/fixtures/dynimport/astro.config.mjs
index d670faac6..009023113 100644
--- a/packages/integrations/deno/test/fixtures/dynimport/astro.config.mjs
+++ b/packages/integrations/deno/test/fixtures/dynimport/astro.config.mjs
@@ -3,5 +3,5 @@ import deno from '@astrojs/deno';
export default defineConfig({
adapter: deno(),
- output: 'server',
+ output: 'server'
})
diff --git a/packages/integrations/netlify/src/integration-edge-functions.ts b/packages/integrations/netlify/src/integration-edge-functions.ts
index ac7c124fb..4e8bc6aa4 100644
--- a/packages/integrations/netlify/src/integration-edge-functions.ts
+++ b/packages/integrations/netlify/src/integration-edge-functions.ts
@@ -11,6 +11,16 @@ export function getAdapter(): AstroAdapter {
name: '@astrojs/netlify/edge-functions',
serverEntrypoint: '@astrojs/netlify/netlify-edge-functions.js',
exports: ['default'],
+ supportedAstroFeatures: {
+ hybridOutput: 'stable',
+ staticOutput: 'stable',
+ serverOutput: 'stable',
+ assets: {
+ supportKind: 'stable',
+ isSharpCompatible: false,
+ isSquooshCompatible: false,
+ },
+ },
};
}
diff --git a/packages/integrations/netlify/src/integration-functions.ts b/packages/integrations/netlify/src/integration-functions.ts
index 3b10e096c..b8d56ad65 100644
--- a/packages/integrations/netlify/src/integration-functions.ts
+++ b/packages/integrations/netlify/src/integration-functions.ts
@@ -18,6 +18,16 @@ export function getAdapter({ functionPerRoute, edgeMiddleware, ...args }: Args):
functionPerRoute,
edgeMiddleware,
},
+ supportedAstroFeatures: {
+ hybridOutput: 'stable',
+ staticOutput: 'stable',
+ serverOutput: 'stable',
+ assets: {
+ supportKind: 'stable',
+ isSharpCompatible: true,
+ isSquooshCompatible: true,
+ },
+ },
};
}
diff --git a/packages/integrations/node/src/index.ts b/packages/integrations/node/src/index.ts
index 17a8f4502..7435a60ed 100644
--- a/packages/integrations/node/src/index.ts
+++ b/packages/integrations/node/src/index.ts
@@ -8,6 +8,16 @@ export function getAdapter(options: Options): AstroAdapter {
previewEntrypoint: '@astrojs/node/preview.js',
exports: ['handler', 'startServer'],
args: options,
+ supportedAstroFeatures: {
+ hybridOutput: 'stable',
+ staticOutput: 'stable',
+ serverOutput: 'stable',
+ assets: {
+ supportKind: 'stable',
+ isSharpCompatible: true,
+ isSquooshCompatible: true,
+ },
+ },
};
}
diff --git a/packages/integrations/vercel/src/edge/adapter.ts b/packages/integrations/vercel/src/edge/adapter.ts
index b83c9f2b7..b613f502c 100644
--- a/packages/integrations/vercel/src/edge/adapter.ts
+++ b/packages/integrations/vercel/src/edge/adapter.ts
@@ -27,6 +27,16 @@ function getAdapter(): AstroAdapter {
name: PACKAGE_NAME,
serverEntrypoint: `${PACKAGE_NAME}/entrypoint`,
exports: ['default'],
+ supportedAstroFeatures: {
+ hybridOutput: 'stable',
+ staticOutput: 'stable',
+ serverOutput: 'stable',
+ assets: {
+ supportKind: 'stable',
+ isSharpCompatible: false,
+ isSquooshCompatible: false,
+ },
+ },
};
}
diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts
index 4fd7e22a4..9a8ead137 100644
--- a/packages/integrations/vercel/src/serverless/adapter.ts
+++ b/packages/integrations/vercel/src/serverless/adapter.ts
@@ -44,6 +44,16 @@ function getAdapter({
edgeMiddleware,
functionPerRoute,
},
+ supportedAstroFeatures: {
+ hybridOutput: 'stable',
+ staticOutput: 'stable',
+ serverOutput: 'stable',
+ assets: {
+ supportKind: 'stable',
+ isSharpCompatible: true,
+ isSquooshCompatible: true,
+ },
+ },
};
}
diff --git a/packages/integrations/vercel/test/no-output.test.js b/packages/integrations/vercel/test/no-output.test.js
index af4d9c2b6..3894ee779 100644
--- a/packages/integrations/vercel/test/no-output.test.js
+++ b/packages/integrations/vercel/test/no-output.test.js
@@ -19,6 +19,6 @@ describe('Missing output config', () => {
error = err;
}
expect(error).to.not.be.equal(undefined);
- expect(error.message).to.include(`output: "server"`);
+ expect(error.message).to.include('output: "server"');
});
});