feat: astro features (#7815)
This commit is contained in:
parent
3fdf509b27
commit
9b4f70a629
20 changed files with 598 additions and 32 deletions
32
.changeset/dirty-lies-cover.md
Normal file
32
.changeset/dirty-lies-cover.md
Normal file
|
@ -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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
|
@ -1680,6 +1680,39 @@ export type PaginateFunction = (data: any[], args?: PaginateOptions) => GetStati
|
||||||
|
|
||||||
export type Params = Record<string, string | undefined>;
|
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 {
|
export interface AstroAdapter {
|
||||||
name: string;
|
name: string;
|
||||||
serverEntrypoint?: string;
|
serverEntrypoint?: string;
|
||||||
|
@ -1687,6 +1720,12 @@ export interface AstroAdapter {
|
||||||
exports?: string[];
|
exports?: string[];
|
||||||
args?: any;
|
args?: any;
|
||||||
adapterFeatures?: AstroAdapterFeatures;
|
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;
|
type Body = string;
|
||||||
|
|
|
@ -27,6 +27,11 @@ export async function generateImage(
|
||||||
options: ImageTransform,
|
options: ImageTransform,
|
||||||
filepath: string
|
filepath: string
|
||||||
): Promise<GenerationData | undefined> {
|
): 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)) {
|
if (!isESMImportedImage(options.src)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import { bold } from 'kleur/colors';
|
|
||||||
import MagicString from 'magic-string';
|
import MagicString from 'magic-string';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
import type * as vite from 'vite';
|
import type * as vite from 'vite';
|
||||||
import { normalizePath } from 'vite';
|
import { normalizePath } from 'vite';
|
||||||
import type { AstroPluginOptions, ImageTransform } from '../@types/astro';
|
import type { AstroPluginOptions, ImageTransform } from '../@types/astro';
|
||||||
import { error } from '../core/logger/core.js';
|
|
||||||
import {
|
import {
|
||||||
appendForwardSlash,
|
appendForwardSlash,
|
||||||
joinPaths,
|
joinPaths,
|
||||||
|
@ -23,37 +21,12 @@ const urlRE = /(\?|&)url(?:&|$)/;
|
||||||
|
|
||||||
export default function assets({
|
export default function assets({
|
||||||
settings,
|
settings,
|
||||||
logging,
|
|
||||||
mode,
|
mode,
|
||||||
}: AstroPluginOptions & { mode: string }): vite.Plugin[] {
|
}: AstroPluginOptions & { mode: string }): vite.Plugin[] {
|
||||||
let resolvedConfig: vite.ResolvedConfig;
|
let resolvedConfig: vite.ResolvedConfig;
|
||||||
|
|
||||||
globalThis.astroAsset = {};
|
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 [
|
return [
|
||||||
// Expose the components and different utilities from `astro:assets` and handle serving images from `/_image` in dev
|
// Expose the components and different utilities from `astro:assets` and handle serving images from `/_image` in dev
|
||||||
{
|
{
|
||||||
|
|
162
packages/astro/src/integrations/astroFeaturesValidation.ts
Normal file
162
packages/astro/src/integrations/astroFeaturesValidation.ts
Normal file
|
@ -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);
|
||||||
|
}
|
|
@ -18,8 +18,9 @@ import type { SerializedSSRManifest } from '../core/app/types';
|
||||||
import type { PageBuildData } from '../core/build/types';
|
import type { PageBuildData } from '../core/build/types';
|
||||||
import { buildClientDirectiveEntrypoint } from '../core/client-directive/index.js';
|
import { buildClientDirectiveEntrypoint } from '../core/client-directive/index.js';
|
||||||
import { mergeConfig } from '../core/config/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 { isServerLikeOutput } from '../prerender/utils.js';
|
||||||
|
import { validateSupportedFeatures } from './astroFeaturesValidation.js';
|
||||||
|
|
||||||
async function withTakingALongTimeMsg<T>({
|
async function withTakingALongTimeMsg<T>({
|
||||||
name,
|
name,
|
||||||
|
@ -197,6 +198,30 @@ export async function runHookConfigDone({
|
||||||
`Integration "${integration.name}" conflicts with "${settings.adapter.name}". You can only configure one deployment integration.`
|
`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;
|
settings.adapter = adapter;
|
||||||
},
|
},
|
||||||
logger,
|
logger,
|
||||||
|
|
55
packages/astro/test/featuresSupport.test.js
Normal file
55
packages/astro/test/featuresSupport.test.js
Normal file
|
@ -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."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -71,6 +71,15 @@ export default function (
|
||||||
name: 'my-ssr-adapter',
|
name: 'my-ssr-adapter',
|
||||||
serverEntrypoint: '@my-ssr',
|
serverEntrypoint: '@my-ssr',
|
||||||
exports: ['manifest', 'createApp'],
|
exports: ['manifest', 'createApp'],
|
||||||
|
supportedFeatures: {
|
||||||
|
assets: {
|
||||||
|
supportKind: 'Stable',
|
||||||
|
isNodeCompatible: true,
|
||||||
|
},
|
||||||
|
serverOutput: 'Stable',
|
||||||
|
staticOutput: 'Stable',
|
||||||
|
hybridOutput: 'Stable',
|
||||||
|
},
|
||||||
...extendAdapter,
|
...extendAdapter,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
import { runHookBuildSetup } from '../../../dist/integrations/index.js';
|
import { runHookBuildSetup } from '../../../dist/integrations/index.js';
|
||||||
|
import { validateSupportedFeatures } from '../../../dist/integrations/astroFeaturesValidation.js';
|
||||||
|
import { defaultLogging } from '../test-utils.js';
|
||||||
|
|
||||||
describe('Integration API', () => {
|
describe('Integration API', () => {
|
||||||
it('runHookBuildSetup should work', async () => {
|
it('runHookBuildSetup should work', async () => {
|
||||||
|
@ -28,3 +30,187 @@ describe('Integration API', () => {
|
||||||
expect(updatedViteConfig).to.haveOwnProperty('define');
|
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;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -24,11 +24,31 @@ export function getAdapter(isModeDirectory: boolean): AstroAdapter {
|
||||||
name: '@astrojs/cloudflare',
|
name: '@astrojs/cloudflare',
|
||||||
serverEntrypoint: '@astrojs/cloudflare/server.directory.js',
|
serverEntrypoint: '@astrojs/cloudflare/server.directory.js',
|
||||||
exports: ['onRequest', 'manifest'],
|
exports: ['onRequest', 'manifest'],
|
||||||
|
supportedAstroFeatures: {
|
||||||
|
hybridOutput: 'stable',
|
||||||
|
staticOutput: 'unsupported',
|
||||||
|
serverOutput: 'stable',
|
||||||
|
assets: {
|
||||||
|
supportKind: 'unsupported',
|
||||||
|
isSharpCompatible: false,
|
||||||
|
isSquooshCompatible: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
name: '@astrojs/cloudflare',
|
name: '@astrojs/cloudflare',
|
||||||
serverEntrypoint: '@astrojs/cloudflare/server.advanced.js',
|
serverEntrypoint: '@astrojs/cloudflare/server.advanced.js',
|
||||||
exports: ['default'],
|
exports: ['default'],
|
||||||
|
supportedAstroFeatures: {
|
||||||
|
hybridOutput: 'stable',
|
||||||
|
staticOutput: 'unsupported',
|
||||||
|
serverOutput: 'stable',
|
||||||
|
assets: {
|
||||||
|
supportKind: 'stable',
|
||||||
|
isSharpCompatible: false,
|
||||||
|
isSquooshCompatible: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,5 +6,5 @@ process.env.SECRET_STUFF = 'secret'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
adapter: cloudflare(),
|
adapter: cloudflare(),
|
||||||
output: 'server',
|
output: 'server'
|
||||||
});
|
});
|
||||||
|
|
|
@ -89,6 +89,16 @@ export function getAdapter(args?: Options): AstroAdapter {
|
||||||
serverEntrypoint: '@astrojs/deno/server.js',
|
serverEntrypoint: '@astrojs/deno/server.js',
|
||||||
args: args ?? {},
|
args: args ?? {},
|
||||||
exports: ['stop', 'handle', 'start', 'running'],
|
exports: ['stop', 'handle', 'start', 'running'],
|
||||||
|
supportedAstroFeatures: {
|
||||||
|
hybridOutput: 'stable',
|
||||||
|
staticOutput: 'stable',
|
||||||
|
serverOutput: 'stable',
|
||||||
|
assets: {
|
||||||
|
supportKind: 'stable',
|
||||||
|
isSharpCompatible: false,
|
||||||
|
isSquooshCompatible: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,5 +6,5 @@ import mdx from '@astrojs/mdx';
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
adapter: deno(),
|
adapter: deno(),
|
||||||
integrations: [react(), mdx()],
|
integrations: [react(), mdx()],
|
||||||
output: 'server',
|
output: 'server'
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,5 +3,5 @@ import deno from '@astrojs/deno';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
adapter: deno(),
|
adapter: deno(),
|
||||||
output: 'server',
|
output: 'server'
|
||||||
})
|
})
|
||||||
|
|
|
@ -11,6 +11,16 @@ export function getAdapter(): AstroAdapter {
|
||||||
name: '@astrojs/netlify/edge-functions',
|
name: '@astrojs/netlify/edge-functions',
|
||||||
serverEntrypoint: '@astrojs/netlify/netlify-edge-functions.js',
|
serverEntrypoint: '@astrojs/netlify/netlify-edge-functions.js',
|
||||||
exports: ['default'],
|
exports: ['default'],
|
||||||
|
supportedAstroFeatures: {
|
||||||
|
hybridOutput: 'stable',
|
||||||
|
staticOutput: 'stable',
|
||||||
|
serverOutput: 'stable',
|
||||||
|
assets: {
|
||||||
|
supportKind: 'stable',
|
||||||
|
isSharpCompatible: false,
|
||||||
|
isSquooshCompatible: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,16 @@ export function getAdapter({ functionPerRoute, edgeMiddleware, ...args }: Args):
|
||||||
functionPerRoute,
|
functionPerRoute,
|
||||||
edgeMiddleware,
|
edgeMiddleware,
|
||||||
},
|
},
|
||||||
|
supportedAstroFeatures: {
|
||||||
|
hybridOutput: 'stable',
|
||||||
|
staticOutput: 'stable',
|
||||||
|
serverOutput: 'stable',
|
||||||
|
assets: {
|
||||||
|
supportKind: 'stable',
|
||||||
|
isSharpCompatible: true,
|
||||||
|
isSquooshCompatible: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,16 @@ export function getAdapter(options: Options): AstroAdapter {
|
||||||
previewEntrypoint: '@astrojs/node/preview.js',
|
previewEntrypoint: '@astrojs/node/preview.js',
|
||||||
exports: ['handler', 'startServer'],
|
exports: ['handler', 'startServer'],
|
||||||
args: options,
|
args: options,
|
||||||
|
supportedAstroFeatures: {
|
||||||
|
hybridOutput: 'stable',
|
||||||
|
staticOutput: 'stable',
|
||||||
|
serverOutput: 'stable',
|
||||||
|
assets: {
|
||||||
|
supportKind: 'stable',
|
||||||
|
isSharpCompatible: true,
|
||||||
|
isSquooshCompatible: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,16 @@ function getAdapter(): AstroAdapter {
|
||||||
name: PACKAGE_NAME,
|
name: PACKAGE_NAME,
|
||||||
serverEntrypoint: `${PACKAGE_NAME}/entrypoint`,
|
serverEntrypoint: `${PACKAGE_NAME}/entrypoint`,
|
||||||
exports: ['default'],
|
exports: ['default'],
|
||||||
|
supportedAstroFeatures: {
|
||||||
|
hybridOutput: 'stable',
|
||||||
|
staticOutput: 'stable',
|
||||||
|
serverOutput: 'stable',
|
||||||
|
assets: {
|
||||||
|
supportKind: 'stable',
|
||||||
|
isSharpCompatible: false,
|
||||||
|
isSquooshCompatible: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,16 @@ function getAdapter({
|
||||||
edgeMiddleware,
|
edgeMiddleware,
|
||||||
functionPerRoute,
|
functionPerRoute,
|
||||||
},
|
},
|
||||||
|
supportedAstroFeatures: {
|
||||||
|
hybridOutput: 'stable',
|
||||||
|
staticOutput: 'stable',
|
||||||
|
serverOutput: 'stable',
|
||||||
|
assets: {
|
||||||
|
supportKind: 'stable',
|
||||||
|
isSharpCompatible: true,
|
||||||
|
isSquooshCompatible: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,6 @@ describe('Missing output config', () => {
|
||||||
error = err;
|
error = err;
|
||||||
}
|
}
|
||||||
expect(error).to.not.be.equal(undefined);
|
expect(error).to.not.be.equal(undefined);
|
||||||
expect(error.message).to.include(`output: "server"`);
|
expect(error.message).to.include('output: "server"');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue