From ee38b3a94697fe883ce8300eff9f001470b8adb6 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Fri, 13 Sep 2024 11:44:55 +0200 Subject: [PATCH 1/3] refactor(next): send `IntegrationRouteData` to integrations (#11864) Co-authored-by: Luiz Ferraz Co-authored-by: Alexander Niebuhr Co-authored-by: Florian Lefebvre --- .changeset/brave-elephants-fly.md | 21 +++++ .changeset/fuzzy-pugs-live.md | 21 +++++ .changeset/ten-walls-tap.md | 24 +++++ packages/astro/src/core/build/generate.ts | 6 +- .../astro/src/core/routing/manifest/create.ts | 3 + packages/astro/src/integrations/hooks.ts | 28 +++++- .../astro/src/types/public/integrations.ts | 17 +++- packages/astro/src/types/public/internal.ts | 88 ++++++++++++++++++- .../test/static-build-page-dist-url.test.js | 4 +- 9 files changed, 203 insertions(+), 9 deletions(-) create mode 100644 .changeset/brave-elephants-fly.md create mode 100644 .changeset/fuzzy-pugs-live.md create mode 100644 .changeset/ten-walls-tap.md diff --git a/.changeset/brave-elephants-fly.md b/.changeset/brave-elephants-fly.md new file mode 100644 index 000000000000..0c76730279a4 --- /dev/null +++ b/.changeset/brave-elephants-fly.md @@ -0,0 +1,21 @@ +--- +'astro': major +--- + +### [changed]: `entryPoint` type inside the hook `astro:build:ssr` +In Astro v4.x, the `entryPoint` type was `RouteData`. + +Astro v5.0 the `entryPoint` type is `IntegrationRouteData`, which contains a subset of the `RouteData` type. The fields `isIndex` and `fallbackRoutes` were removed. + +#### What should I do? +Update your adapter to change the type of `entryPoint` from `RouteData` to `IntegrationRouteData`. + +```diff +-import type {RouteData} from 'astro'; ++import type {IntegrationRouteData} from "astro" + +-function useRoute(route: RouteData) { ++function useRoute(route: IntegrationRouteData) { + +} +``` diff --git a/.changeset/fuzzy-pugs-live.md b/.changeset/fuzzy-pugs-live.md new file mode 100644 index 000000000000..bf1bd39dc7f7 --- /dev/null +++ b/.changeset/fuzzy-pugs-live.md @@ -0,0 +1,21 @@ +--- +'astro': major +--- + +### [changed]: `routes` type inside the hook `astro:build:done` +In Astro v4.x, the `routes` type was `RouteData`. + +Astro v5.0 the `routes` type is `IntegrationRouteData`, which contains a subset of the `RouteData` type. The fields `isIndex` and `fallbackRoutes` were removed. + +#### What should I do? +Update your adapter to change the type of `routes` from `RouteData` to `IntegrationRouteData`. + +```diff +-import type {RouteData} from 'astro'; ++import type {IntegrationRouteData} from "astro" + +-function useRoute(route: RouteData) { ++function useRoute(route: IntegrationRouteData) { + +} +``` diff --git a/.changeset/ten-walls-tap.md b/.changeset/ten-walls-tap.md new file mode 100644 index 000000000000..afc8c07ed8d3 --- /dev/null +++ b/.changeset/ten-walls-tap.md @@ -0,0 +1,24 @@ +--- +'astro': major +--- + +### [changed]: `RouteData.distURL` is now an array +In Astro v4.x, `RouteData.distURL` was `undefined` or a `URL` + +Astro v5.0, `RouteData.distURL` is `undefined` or an array of `URL`. This was a bug, because a route can generate multiple files on disk, especially when using dynamic routes such as `[slug]` or `[...slug]`. + +#### What should I do? +Update your code to handle `RouteData.distURL` as an array. + +```diff +if (route.distURL) { +- if (route.distURL.endsWith('index.html')) { +- // do something +- } ++ for (const url of route.distURL) { ++ if (url.endsWith('index.html')) { ++ // do something ++ } ++ } +} +``` diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts index 9eaf4ff1d626..7c8776f1d0c4 100644 --- a/packages/astro/src/core/build/generate.ts +++ b/packages/astro/src/core/build/generate.ts @@ -466,7 +466,11 @@ async function generatePath( const outFolder = getOutFolder(pipeline.settings, pathname, route); const outFile = getOutFile(config, outFolder, pathname, route); - route.distURL = outFile; + if (route.distURL) { + route.distURL.push(outFile); + } else { + route.distURL = [outFile]; + } await fs.promises.mkdir(outFolder, { recursive: true }); await fs.promises.writeFile(outFile, body); diff --git a/packages/astro/src/core/routing/manifest/create.ts b/packages/astro/src/core/routing/manifest/create.ts index 834c37efe226..4e0fb964a82b 100644 --- a/packages/astro/src/core/routing/manifest/create.ts +++ b/packages/astro/src/core/routing/manifest/create.ts @@ -254,6 +254,7 @@ function createFileBasedRoutes( pathname: pathname || undefined, prerender, fallbackRoutes: [], + distURL: [], }); } } @@ -318,6 +319,7 @@ function createInjectedRoutes({ settings, cwd }: CreateRouteManifestParams): Rou pathname: pathname || void 0, prerender: prerenderInjected ?? prerender, fallbackRoutes: [], + distURL: [], }); } @@ -386,6 +388,7 @@ function createRedirectRoutes( redirect: to, redirectRoute: routeMap.get(destination), fallbackRoutes: [], + distURL: [], }); } diff --git a/packages/astro/src/integrations/hooks.ts b/packages/astro/src/integrations/hooks.ts index 0c40e60cdb96..18544ae8009c 100644 --- a/packages/astro/src/integrations/hooks.ts +++ b/packages/astro/src/integrations/hooks.ts @@ -25,6 +25,7 @@ import type { AstroIntegration, AstroRenderer, HookParameters, + IntegrationRouteData, RouteOptions, } from '../types/public/integrations.js'; import type { RouteData } from '../types/public/internal.js'; @@ -532,6 +533,10 @@ export async function runHookBuildSsr({ entryPoints, middlewareEntryPoint, }: RunHookBuildSsr) { + const entryPointsMap = new Map(); + for (const [key, value] of entryPoints) { + entryPointsMap.set(toIntegrationRouteData(key), value); + } for (const integration of config.integrations) { if (integration?.hooks?.['astro:build:ssr']) { await withTakingALongTimeMsg({ @@ -539,7 +544,7 @@ export async function runHookBuildSsr({ hookName: 'astro:build:ssr', hookResult: integration.hooks['astro:build:ssr']({ manifest, - entryPoints, + entryPoints: entryPointsMap, middlewareEntryPoint, logger: getLogger(integration, logger), }), @@ -592,7 +597,7 @@ export async function runHookBuildDone({ const dir = settings.buildOutput === 'server' ? settings.config.build.client : settings.config.outDir; await fsMod.promises.mkdir(dir, { recursive: true }); - + const integrationRoutes = routes.map(toIntegrationRouteData); for (const integration of settings.config.integrations) { if (integration?.hooks?.['astro:build:done']) { const logger = getLogger(integration, logging); @@ -603,7 +608,7 @@ export async function runHookBuildDone({ hookResult: integration.hooks['astro:build:done']({ pages: pages.map((p) => ({ pathname: p })), dir, - routes, + routes: integrationRoutes, logger, cacheManifest, }), @@ -653,3 +658,20 @@ export async function runHookRouteSetup({ ); } } + +function toIntegrationRouteData(route: RouteData): IntegrationRouteData { + return { + route: route.route, + component: route.component, + generate: route.generate, + params: route.params, + pathname: route.pathname, + segments: route.segments, + prerender: route.prerender, + redirect: route.redirect, + redirectRoute: route.redirectRoute ? toIntegrationRouteData(route.redirectRoute) : undefined, + type: route.type, + pattern: route.pattern, + distURL: route.distURL, + }; +} diff --git a/packages/astro/src/types/public/integrations.ts b/packages/astro/src/types/public/integrations.ts index 0836bdc9e9bb..1980c0ab10ad 100644 --- a/packages/astro/src/types/public/integrations.ts +++ b/packages/astro/src/types/public/integrations.ts @@ -206,7 +206,7 @@ export interface BaseIntegrationHooks { * This maps a {@link RouteData} to an {@link URL}, this URL represents * the physical file you should import. */ - entryPoints: Map; + entryPoints: Map; /** * File path of the emitted middleware */ @@ -228,7 +228,7 @@ export interface BaseIntegrationHooks { 'astro:build:done': (options: { pages: { pathname: string }[]; dir: URL; - routes: RouteData[]; + routes: IntegrationRouteData[]; logger: AstroIntegrationLogger; cacheManifest: boolean; }) => void | Promise; @@ -246,3 +246,16 @@ export interface AstroIntegration { [K in keyof Astro.IntegrationHooks]?: Astro.IntegrationHooks[K]; } & Partial>; } + +/** + * A smaller version of the {@link RouteData} that is used in the integrations. + */ +export type IntegrationRouteData = Omit< + RouteData, + 'isIndex' | 'fallbackRoutes' | 'redirectRoute' +> & { + /** + * {@link RouteData.redirectRoute} + */ + redirectRoute?: IntegrationRouteData; +}; diff --git a/packages/astro/src/types/public/internal.ts b/packages/astro/src/types/public/internal.ts index bee15c6f75c0..c970ab3d18ac 100644 --- a/packages/astro/src/types/public/internal.ts +++ b/packages/astro/src/types/public/internal.ts @@ -36,21 +36,105 @@ export interface SSRLoadedRendererValue { renderHydrationScript?: () => string; } +/** + * It contains the information about a route + */ export interface RouteData { + /** + * The current **pattern** of the route. For example: + * - `src/pages/index.astro` has a pattern of `/` + * - `src/pages/blog/[...slug].astro` has a pattern of `/blog/[...slug]` + * - `src/pages/site/[blog]/[...slug].astro` has a pattern of `/site/[blog]/[...slug]` + */ route: string; + /** + * Source component URL + */ component: string; + /** + * @param {any} data The optional parameters of the route + * + * @description + * A function that accepts a list of params, interpolates them with the route pattern, and returns the path name of the route. + * + * ## Example + * + * For a route such as `/blog/[...id].astro`, the `generate` function would return something like this: + * + * ```js + * console.log(generate({ id: 'presentation' })) // will log `/blog/presentation` + * ``` + */ generate: (data?: any) => string; + /** + * Dynamic and spread route params + * ex. "/pages/[lang]/[...slug].astro" will output the params ['lang', '...slug'] + */ params: string[]; + /** + * Output URL pathname where this route will be served + * note: will be undefined for [dynamic] and [...spread] routes + */ pathname?: string; - // expose the real path name on SSG - distURL?: URL; + /** + * The paths of the physical files emitted by this route. When a route **isn't** prerendered, the value is either `undefined` or an empty array. + */ + distURL?: URL[]; + /** + * + * regex used for matching an input URL against a requested route + * ex. "[fruit]/about.astro" will generate the pattern: /^\/([^/]+?)\/about\/?$/ + * where pattern.test("banana/about") is "true" + * + * ## Example + * + * ```js + * if (route.pattern.test('/blog')) { + * // do something + * } + * ``` + */ pattern: RegExp; + /** + * Similar to the "params" field, but with more associated metadata. For example, for `/site/[blog]/[...slug].astro`, the segments are: + * + * 1. `{ content: 'site', dynamic: false, spread: false }` + * 2. `{ content: 'blog', dynamic: true, spread: false }` + * 3. `{ content: '...slug', dynamic: true, spread: true }` + */ segments: RoutePart[][]; + /** + * + * The type of the route. It can be: + * - `page`: a route that lives in the file system, usually an Astro component + * - `endpoint`: a route that lives in the file system, usually a JS file that exposes endpoints methods + * - `redirect`: a route points to another route that lives in the file system + * - `fallback`: a route that doesn't exist in the file system that needs to be handled with other means, usually the middleware + */ type: RouteType; + /** + * Whether the route is prerendered or not + */ prerender: boolean; + /** + * The route to redirect to. It holds information regarding the status code and its destination. + */ redirect?: RedirectConfig; + /** + * The {@link RouteData} to redirect to. It's present when `RouteData.type` is `redirect`. + */ redirectRoute?: RouteData; + /** + * A list of {@link RouteData} to fallback to. They are present when `i18n.fallback` has a list of locales. + */ fallbackRoutes: RouteData[]; + + /** + * If this route is a directory index + * For example: + * - src/pages/index.astro + * - src/pages/blog/index.astro + */ isIndex: boolean; } diff --git a/packages/astro/test/static-build-page-dist-url.test.js b/packages/astro/test/static-build-page-dist-url.test.js index 72602274b9be..ebfa75d0e90e 100644 --- a/packages/astro/test/static-build-page-dist-url.test.js +++ b/packages/astro/test/static-build-page-dist-url.test.js @@ -25,7 +25,9 @@ describe('Static build: pages routes have distURL', () => { it('Pages routes have distURL', async () => { assert.equal(checkRoutes.length > 0, true, 'Pages not found: build end hook not being called'); checkRoutes.forEach((p) => { - assert.equal(p.distURL instanceof URL, true, `${p.pathname} doesn't include distURL`); + p.distURL.forEach((distURL) => { + assert.equal(distURL instanceof URL, true, `${p.pathname} doesn't include distURL`); + }); }); }); }); From f7f2338c2b96975001b5c782f458710e9cc46d74 Mon Sep 17 00:00:00 2001 From: Erika <3019731+Princesseuh@users.noreply.github.com> Date: Fri, 13 Sep 2024 13:58:57 +0200 Subject: [PATCH 2/3] refactor: rework supportedAstroFeatures (#11806) * refactor: rework supportAstroFeatures * fix: build * fix: tests * chore: changeset --- .changeset/fluffy-jars-live.md | 7 + .changeset/slimy-queens-hang.md | 7 + .changeset/unlucky-bobcats-sit.md | 5 + .../src/core/build/plugins/plugin-manifest.ts | 4 +- packages/astro/src/core/logger/core.ts | 1 + .../src/integrations/features-validation.ts | 148 ++++++++++-------- packages/astro/src/integrations/hooks.ts | 16 +- .../astro/src/types/public/integrations.ts | 45 +++--- .../astro/test/units/integrations/api.test.js | 58 ------- 9 files changed, 127 insertions(+), 164 deletions(-) create mode 100644 .changeset/fluffy-jars-live.md create mode 100644 .changeset/slimy-queens-hang.md create mode 100644 .changeset/unlucky-bobcats-sit.md diff --git a/.changeset/fluffy-jars-live.md b/.changeset/fluffy-jars-live.md new file mode 100644 index 000000000000..59549a4a2131 --- /dev/null +++ b/.changeset/fluffy-jars-live.md @@ -0,0 +1,7 @@ +--- +'astro': major +--- + +Removes the `assets` property on `supportedAstroFeatures` for adapters, as it did not reflect reality properly in many cases. + +Now, relating to assets, only a single `sharpImageService` property is available, determining if the adapter is compatible with the built-in sharp image service. diff --git a/.changeset/slimy-queens-hang.md b/.changeset/slimy-queens-hang.md new file mode 100644 index 000000000000..936ed273158c --- /dev/null +++ b/.changeset/slimy-queens-hang.md @@ -0,0 +1,7 @@ +--- +'astro': minor +--- + +The value of the different properties on `supportedAstroFeatures` for adapters can now be objects, with a `support` and `message` properties. The content of the `message` property will be shown in the Astro CLI when the adapter is not compatible with the feature, allowing one to give a better informational message to the user. + +This is notably useful with the new `limited` value, to explain to the user why support is limited. diff --git a/.changeset/unlucky-bobcats-sit.md b/.changeset/unlucky-bobcats-sit.md new file mode 100644 index 000000000000..e815c8acdc51 --- /dev/null +++ b/.changeset/unlucky-bobcats-sit.md @@ -0,0 +1,5 @@ +--- +'astro': minor +--- + +Adds a new `limited` value for the different properties of `supportedAstroFeatures` for adapters, which indicates that the adapter is compatible with the feature, but with some limitations. This is useful for adapters that support a feature, but not in all cases or with all options. diff --git a/packages/astro/src/core/build/plugins/plugin-manifest.ts b/packages/astro/src/core/build/plugins/plugin-manifest.ts index 79bd3b44d3c4..df3c8c81184a 100644 --- a/packages/astro/src/core/build/plugins/plugin-manifest.ts +++ b/packages/astro/src/core/build/plugins/plugin-manifest.ts @@ -5,6 +5,7 @@ import type { Plugin as VitePlugin } from 'vite'; import { getAssetsPrefix } from '../../../assets/utils/getAssetsPrefix.js'; import { normalizeTheLocale } from '../../../i18n/index.js'; import { toFallbackType, toRoutingStrategy } from '../../../i18n/utils.js'; +import { unwrapSupportKind } from '../../../integrations/features-validation.js'; import { runHookBuildSsr } from '../../../integrations/hooks.js'; import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from '../../../vite-plugin-scripts/index.js'; import type { @@ -273,6 +274,7 @@ function buildManifest( serverIslandNameMap: Array.from(settings.serverIslandNameMap), key: encodedKey, envGetSecretEnabled: - (settings.adapter?.supportedAstroFeatures.envGetSecret ?? 'unsupported') !== 'unsupported', + (unwrapSupportKind(settings.adapter?.supportedAstroFeatures.envGetSecret) ?? + 'unsupported') !== 'unsupported', }; } diff --git a/packages/astro/src/core/logger/core.ts b/packages/astro/src/core/logger/core.ts index 51ebd9325b06..05566b258902 100644 --- a/packages/astro/src/core/logger/core.ts +++ b/packages/astro/src/core/logger/core.ts @@ -33,6 +33,7 @@ export type LoggerLabel = | 'assets' | 'env' | 'update' + | 'adapter' // SKIP_FORMAT: A special label that tells the logger not to apply any formatting. // Useful for messages that are already formatted, like the server start message. | 'SKIP_FORMAT'; diff --git a/packages/astro/src/integrations/features-validation.ts b/packages/astro/src/integrations/features-validation.ts index 77db47e0a2ed..9383c76b2e7c 100644 --- a/packages/astro/src/integrations/features-validation.ts +++ b/packages/astro/src/integrations/features-validation.ts @@ -1,22 +1,18 @@ import type { Logger } from '../core/logger/core.js'; import type { AstroSettings } from '../types/astro.js'; -import type { AstroConfig } from '../types/public/config.js'; import type { + AdapterSupport, AdapterSupportsKind, AstroAdapterFeatureMap, - AstroAdapterFeatures, - AstroAssetsFeature, } from '../types/public/integrations.js'; -const STABLE = 'stable'; -const DEPRECATED = 'deprecated'; -const UNSUPPORTED = 'unsupported'; -const EXPERIMENTAL = 'experimental'; - -const UNSUPPORTED_ASSETS_FEATURE: AstroAssetsFeature = { - supportKind: UNSUPPORTED, - isSharpCompatible: false, -}; +export const AdapterFeatureStability = { + STABLE: 'stable', + DEPRECATED: 'deprecated', + UNSUPPORTED: 'unsupported', + EXPERIMENTAL: 'experimental', + LIMITED: 'limited', +} as const; type ValidationResult = { [Property in keyof AstroAdapterFeatureMap]: boolean; @@ -33,16 +29,15 @@ export function validateSupportedFeatures( adapterName: string, featureMap: AstroAdapterFeatureMap, settings: AstroSettings, - adapterFeatures: AstroAdapterFeatures | undefined, logger: Logger, ): ValidationResult { const { - assets = UNSUPPORTED_ASSETS_FEATURE, - serverOutput = UNSUPPORTED, - staticOutput = UNSUPPORTED, - hybridOutput = UNSUPPORTED, - i18nDomains = UNSUPPORTED, - envGetSecret = UNSUPPORTED, + serverOutput = AdapterFeatureStability.UNSUPPORTED, + staticOutput = AdapterFeatureStability.UNSUPPORTED, + hybridOutput = AdapterFeatureStability.UNSUPPORTED, + i18nDomains = AdapterFeatureStability.UNSUPPORTED, + envGetSecret = AdapterFeatureStability.UNSUPPORTED, + sharpImageService = AdapterFeatureStability.UNSUPPORTED, } = featureMap; const validationResult: ValidationResult = {}; @@ -67,9 +62,8 @@ export function validateSupportedFeatures( adapterName, logger, 'serverOutput', - () => settings.config?.output === 'server', + () => settings.config?.output === 'server' || settings.buildOutput === 'server', ); - validationResult.assets = validateAssetsFeature(assets, adapterName, settings.config, logger); if (settings.config.i18n?.domains) { validationResult.i18nDomains = validateSupportKind( @@ -91,71 +85,93 @@ export function validateSupportedFeatures( () => Object.keys(settings.config?.env?.schema ?? {}).length !== 0, ); + validationResult.sharpImageService = validateSupportKind( + sharpImageService, + adapterName, + logger, + 'sharp', + () => settings.config?.image?.service?.entrypoint === 'astro/assets/services/sharp', + ); + return validationResult; } +export function unwrapSupportKind(supportKind?: AdapterSupport): AdapterSupportsKind | undefined { + if (!supportKind) { + return undefined; + } + + return typeof supportKind === 'object' ? supportKind.support : supportKind; +} + +export function getSupportMessage(supportKind: AdapterSupport): string | undefined { + return typeof supportKind === 'object' ? supportKind.message : undefined; +} + function validateSupportKind( - supportKind: AdapterSupportsKind, + supportKind: AdapterSupport, adapterName: string, logger: Logger, featureName: string, hasCorrectConfig: () => boolean, ): boolean { - if (supportKind === STABLE) { - return true; - } else if (supportKind === DEPRECATED) { - featureIsDeprecated(adapterName, logger, featureName); - } else if (supportKind === EXPERIMENTAL) { - featureIsExperimental(adapterName, logger, featureName); - } + const supportValue = unwrapSupportKind(supportKind); + const message = getSupportMessage(supportKind); - if (hasCorrectConfig() && supportKind === UNSUPPORTED) { - featureIsUnsupported(adapterName, logger, featureName); + if (!supportValue) { return false; - } else { - return true; } -} -function featureIsUnsupported(adapterName: string, logger: Logger, featureName: string) { - logger.error( - 'config', - `The adapter ${adapterName} doesn't currently support the feature "${featureName}".`, - ); -} + if (supportValue === AdapterFeatureStability.STABLE) { + return true; + } else if (hasCorrectConfig()) { + // If the user has the relevant configuration, but the adapter doesn't support it, warn the user + logFeatureSupport(adapterName, logger, featureName, supportValue, message); + } -function featureIsExperimental(adapterName: string, logger: Logger, featureName: string) { - logger.warn( - 'config', - `The adapter ${adapterName} provides experimental support for "${featureName}". You may experience issues or breaking changes until this feature is fully supported by the adapter.`, - ); + return false; } -function featureIsDeprecated(adapterName: string, logger: Logger, featureName: string) { - logger.warn( - 'config', - `The adapter ${adapterName} has deprecated its support for "${featureName}", and future compatibility is not guaranteed. The adapter may completely remove support for this feature without warning.`, - ); -} - -const SHARP_SERVICE = 'astro/assets/services/sharp'; - -function validateAssetsFeature( - assets: AstroAssetsFeature, +function logFeatureSupport( adapterName: string, - config: AstroConfig, logger: Logger, -): boolean { - const { supportKind = UNSUPPORTED, isSharpCompatible = false } = assets; - if (config?.image?.service?.entrypoint === SHARP_SERVICE && !isSharpCompatible) { - logger.warn( - null, - `The currently selected adapter \`${adapterName}\` is not compatible with the image service "Sharp".`, - ); - return false; + featureName: string, + supportKind: AdapterSupport, + adapterMessage?: string, +) { + switch (supportKind) { + case AdapterFeatureStability.STABLE: + break; + case AdapterFeatureStability.DEPRECATED: + logger.warn( + 'config', + `The adapter ${adapterName} has deprecated its support for "${featureName}", and future compatibility is not guaranteed. The adapter may completely remove support for this feature without warning.`, + ); + break; + case AdapterFeatureStability.EXPERIMENTAL: + logger.warn( + 'config', + `The adapter ${adapterName} provides experimental support for "${featureName}". You may experience issues or breaking changes until this feature is fully supported by the adapter.`, + ); + break; + case AdapterFeatureStability.LIMITED: + logger.warn( + 'config', + `The adapter ${adapterName} has limited support for "${featureName}". Certain features may not work as expected.`, + ); + break; + case AdapterFeatureStability.UNSUPPORTED: + logger.error( + 'config', + `The adapter ${adapterName} does not currently support the feature "${featureName}". Your project may not build correctly.`, + ); + break; } - return validateSupportKind(supportKind, adapterName, logger, 'assets', () => true); + // If the adapter specified a custom message, log it after the default message + if (adapterMessage) { + logger.warn('adapter', adapterMessage); + } } export function getAdapterStaticRecommendation(adapterName: string): string | undefined { diff --git a/packages/astro/src/integrations/hooks.ts b/packages/astro/src/integrations/hooks.ts index 18544ae8009c..5ac21c435a5f 100644 --- a/packages/astro/src/integrations/hooks.ts +++ b/packages/astro/src/integrations/hooks.ts @@ -323,26 +323,12 @@ export async function runHookConfigDone({ `The adapter ${adapter.name} doesn't provide a feature map. It is required in Astro 4.0.`, ); } else { - const validationResult = validateSupportedFeatures( + validateSupportedFeatures( adapter.name, adapter.supportedAstroFeatures, settings, - // SAFETY: we checked before if it's not present, and we throw an error - adapter.adapterFeatures, logger, ); - for (const [featureName, supported] of Object.entries(validationResult)) { - // If `supported` / `validationResult[featureName]` only allows boolean, - // in theory 'assets' false, doesn't mean that the feature is not supported, but rather that the chosen image service is unsupported - // in this case we should not show an error, that the featrue is not supported - // if we would refactor the validation to support more than boolean, we could still be able to differentiate between the two cases - if (!supported && featureName !== 'assets') { - logger.error( - null, - `The adapter ${adapter.name} doesn't support the feature ${featureName}. Your project won't be built. You should not use it.`, - ); - } - } } settings.adapter = adapter; }, diff --git a/packages/astro/src/types/public/integrations.ts b/packages/astro/src/types/public/integrations.ts index 1980c0ab10ad..49557c23aa61 100644 --- a/packages/astro/src/types/public/integrations.ts +++ b/packages/astro/src/types/public/integrations.ts @@ -3,6 +3,7 @@ import type { ViteDevServer, InlineConfig as ViteInlineConfig } from 'vite'; import type { SerializedSSRManifest } from '../../core/app/types.js'; import type { PageBuildData } from '../../core/build/types.js'; import type { AstroIntegrationLogger } from '../../core/logger/core.js'; +import type { AdapterFeatureStability } from '../../integrations/features-validation.js'; import type { getToolbarServerCommunicationHelpers } from '../../integrations/hooks.js'; import type { DeepPartial } from '../../type-utils.js'; import type { AstroConfig } from './config.js'; @@ -60,7 +61,15 @@ export interface AstroRenderer { serverEntrypoint: string; } -export type AdapterSupportsKind = 'unsupported' | 'stable' | 'experimental' | 'deprecated'; +export type AdapterSupportsKind = + (typeof AdapterFeatureStability)[keyof typeof AdapterFeatureStability]; + +export type AdapterSupportWithMessage = { + support: Exclude; + message: string; +}; + +export type AdapterSupport = AdapterSupportsKind | AdapterSupportWithMessage; export interface AstroAdapterFeatures { /** @@ -92,45 +101,33 @@ export type AstroAdapterFeatureMap = { /** * The adapter is able serve static pages */ - staticOutput?: AdapterSupportsKind; + staticOutput?: AdapterSupport; + /** * The adapter is able to serve pages that are static or rendered via server */ - hybridOutput?: AdapterSupportsKind; + hybridOutput?: AdapterSupport; + /** * The adapter is able to serve SSR pages */ - serverOutput?: AdapterSupportsKind; - /** - * The adapter can emit static assets - */ - assets?: AstroAssetsFeature; + serverOutput?: AdapterSupport; /** - * List of features that orbit around the i18n routing + * The adapter is able to support i18n domains */ - i18nDomains?: AdapterSupportsKind; + i18nDomains?: AdapterSupport; /** * The adapter is able to support `getSecret` exported from `astro:env/server` */ - envGetSecret?: AdapterSupportsKind; -}; + envGetSecret?: AdapterSupport; -export interface AstroAssetsFeature { - supportKind?: AdapterSupportsKind; /** - * Whether if this adapter deploys files in an environment that is compatible with the library `sharp` + * The adapter supports image transformation using the built-in Sharp image service */ - isSharpCompatible?: boolean; -} - -export interface AstroInternationalizationFeature { - /** - * The adapter should be able to create the proper redirects - */ - domains?: AdapterSupportsKind; -} + sharpImageService?: AdapterSupport; +}; /** * IDs for different stages of JS script injection: diff --git a/packages/astro/test/units/integrations/api.test.js b/packages/astro/test/units/integrations/api.test.js index 4aef593be3ed..0a0233215061 100644 --- a/packages/astro/test/units/integrations/api.test.js +++ b/packages/astro/test/units/integrations/api.test.js @@ -153,7 +153,6 @@ describe('Astro feature map', function () { buildOutput: 'server', config: { output: 'static' }, }, - {}, defaultLogger, ); assert.equal(result['hybridOutput'], false); @@ -167,7 +166,6 @@ describe('Astro feature map', function () { buildOutput: 'server', config: { output: 'static' }, }, - {}, defaultLogger, ); assert.equal(result['hybridOutput'], false); @@ -181,7 +179,6 @@ describe('Astro feature map', function () { { config: { output: 'static' }, }, - {}, defaultLogger, ); assert.equal(result['staticOutput'], true); @@ -195,7 +192,6 @@ describe('Astro feature map', function () { buildOutput: 'static', config: { output: 'static' }, }, - {}, defaultLogger, ); assert.equal(result['staticOutput'], false); @@ -209,7 +205,6 @@ describe('Astro feature map', function () { { config: { output: 'static' }, }, - {}, defaultLogger, ); assert.equal(result['hybridOutput'], true); @@ -225,7 +220,6 @@ describe('Astro feature map', function () { buildOutput: 'server', config: { output: 'static' }, }, - {}, defaultLogger, ); assert.equal(result['hybridOutput'], false); @@ -239,7 +233,6 @@ describe('Astro feature map', function () { { config: { output: 'server' }, }, - {}, defaultLogger, ); assert.equal(result['serverOutput'], true); @@ -254,62 +247,11 @@ describe('Astro feature map', function () { { config: { output: 'server' }, }, - {}, defaultLogger, ); assert.equal(result['serverOutput'], false); }); }); - - describe('assets', function () { - it('should be supported when it is sharp compatible', () => { - let result = validateSupportedFeatures( - 'test', - { - assets: { - supportKind: 'stable', - isSharpCompatible: true, - }, - }, - { - config: { - image: { - service: { - entrypoint: 'astro/assets/services/sharp', - }, - }, - }, - }, - {}, - defaultLogger, - ); - assert.equal(result['assets'], 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, - }, - }, - { - config: { - image: { - service: { - entrypoint: 'astro/assets/services/sharp', - }, - }, - }, - }, - {}, - defaultLogger, - ); - assert.equal(result['assets'], false); - }); - }); }); describe('normalizeInjectedTypeFilename', () => { From f15922d177a623c19c5e1d9a85cc5aa2df4ae82b Mon Sep 17 00:00:00 2001 From: "Houston (Bot)" <108291165+astrobot-houston@users.noreply.github.com> Date: Fri, 13 Sep 2024 06:27:42 -0700 Subject: [PATCH 3/3] [ci] release (alpha) (#11962) Co-authored-by: github-actions[bot] --- .changeset/pre.json | 15 +- examples/basics/package.json | 2 +- examples/blog/package.json | 2 +- examples/component/package.json | 2 +- examples/container-with-vitest/package.json | 2 +- examples/framework-alpine/package.json | 2 +- examples/framework-multiple/package.json | 2 +- examples/framework-preact/package.json | 2 +- examples/framework-react/package.json | 2 +- examples/framework-solid/package.json | 2 +- examples/framework-svelte/package.json | 2 +- examples/framework-vue/package.json | 2 +- examples/hackernews/package.json | 2 +- examples/integration/package.json | 2 +- examples/middleware/package.json | 2 +- examples/minimal/package.json | 2 +- examples/non-html-pages/package.json | 2 +- examples/portfolio/package.json | 2 +- examples/server-islands/package.json | 2 +- examples/ssr/package.json | 2 +- examples/starlog/package.json | 2 +- examples/toolbar-app/package.json | 2 +- examples/view-transitions/package.json | 2 +- examples/with-markdoc/package.json | 2 +- examples/with-markdown-plugins/package.json | 2 +- examples/with-markdown-shiki/package.json | 2 +- examples/with-mdx/package.json | 4 +- examples/with-nanostores/package.json | 2 +- examples/with-tailwindcss/package.json | 2 +- examples/with-vitest/package.json | 2 +- packages/astro/CHANGELOG.md | 197 ++++++++++++++++++++ packages/astro/package.json | 2 +- packages/astro/src/core/build/index.ts | 2 +- packages/astro/test/server-islands.test.js | 6 +- pnpm-lock.yaml | 60 +++--- 35 files changed, 274 insertions(+), 68 deletions(-) diff --git a/.changeset/pre.json b/.changeset/pre.json index 99f40b214c8a..b6b9b33b9800 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -34,16 +34,19 @@ "changesets": [ "afraid-apricots-buy", "blue-boats-relax", + "brave-elephants-fly", "breezy-colts-promise", "chatty-teachers-sit", "chilly-terms-know", "clean-donuts-walk", "cuddly-shoes-press", "curvy-walls-kneel", + "dry-worms-knock", + "eighty-bags-cross", "eighty-boxes-applaud", - "empty-spoons-kiss", "five-jars-hear", - "forty-spies-train", + "fluffy-jars-live", + "fuzzy-pugs-live", "giant-rocks-thank", "healthy-ads-scream", "heavy-seahorses-poke", @@ -55,6 +58,7 @@ "long-months-rule", "many-garlics-lick", "mean-donkeys-switch", + "mighty-stingrays-press", "modern-bears-deny", "moody-waves-think", "nasty-crabs-worry", @@ -68,10 +72,15 @@ "selfish-cats-crash", "selfish-impalas-grin", "sharp-worms-sniff", + "slimy-queens-hang", "small-ties-sort", "spotty-garlics-cheat", + "strange-sheep-film", "ten-students-repair", + "ten-walls-tap", "twelve-comics-march", - "twenty-cobras-push" + "twenty-cobras-push", + "unlucky-bobcats-sit", + "violet-goats-grab" ] } diff --git a/examples/basics/package.json b/examples/basics/package.json index d8be60597d99..6ba9df6d7f5d 100644 --- a/examples/basics/package.json +++ b/examples/basics/package.json @@ -11,6 +11,6 @@ "astro": "astro" }, "dependencies": { - "astro": "^5.0.0-alpha.6" + "astro": "^5.0.0-alpha.7" } } diff --git a/examples/blog/package.json b/examples/blog/package.json index 7265f2f2c909..ea7bba9a2c90 100644 --- a/examples/blog/package.json +++ b/examples/blog/package.json @@ -14,6 +14,6 @@ "@astrojs/mdx": "^4.0.0-alpha.2", "@astrojs/rss": "^4.0.7", "@astrojs/sitemap": "^3.1.6", - "astro": "^5.0.0-alpha.6" + "astro": "^5.0.0-alpha.7" } } diff --git a/examples/component/package.json b/examples/component/package.json index 287b931fb131..13609b2b23ab 100644 --- a/examples/component/package.json +++ b/examples/component/package.json @@ -15,7 +15,7 @@ ], "scripts": {}, "devDependencies": { - "astro": "^5.0.0-alpha.6" + "astro": "^5.0.0-alpha.7" }, "peerDependencies": { "astro": "^4.0.0" diff --git a/examples/container-with-vitest/package.json b/examples/container-with-vitest/package.json index d192a9d11b38..19266af1dd00 100644 --- a/examples/container-with-vitest/package.json +++ b/examples/container-with-vitest/package.json @@ -12,7 +12,7 @@ "test": "vitest run" }, "dependencies": { - "astro": "^5.0.0-alpha.6", + "astro": "^5.0.0-alpha.7", "@astrojs/react": "^3.6.2", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/examples/framework-alpine/package.json b/examples/framework-alpine/package.json index 99f893339280..ed02a2a5c55b 100644 --- a/examples/framework-alpine/package.json +++ b/examples/framework-alpine/package.json @@ -14,6 +14,6 @@ "@astrojs/alpinejs": "^0.4.0", "@types/alpinejs": "^3.13.10", "alpinejs": "^3.14.1", - "astro": "^5.0.0-alpha.6" + "astro": "^5.0.0-alpha.7" } } diff --git a/examples/framework-multiple/package.json b/examples/framework-multiple/package.json index 568c1f72ceeb..c7a8159130b1 100644 --- a/examples/framework-multiple/package.json +++ b/examples/framework-multiple/package.json @@ -18,7 +18,7 @@ "@astrojs/vue": "^5.0.0-alpha.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "astro": "^5.0.0-alpha.6", + "astro": "^5.0.0-alpha.7", "preact": "^10.23.2", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/examples/framework-preact/package.json b/examples/framework-preact/package.json index fe4c2e27c957..fa4db6bc8018 100644 --- a/examples/framework-preact/package.json +++ b/examples/framework-preact/package.json @@ -13,7 +13,7 @@ "dependencies": { "@astrojs/preact": "^3.5.3", "@preact/signals": "^1.3.0", - "astro": "^5.0.0-alpha.6", + "astro": "^5.0.0-alpha.7", "preact": "^10.23.2" } } diff --git a/examples/framework-react/package.json b/examples/framework-react/package.json index e814ea45895f..a0effb6a016d 100644 --- a/examples/framework-react/package.json +++ b/examples/framework-react/package.json @@ -14,7 +14,7 @@ "@astrojs/react": "^3.6.2", "@types/react": "^18.3.5", "@types/react-dom": "^18.3.0", - "astro": "^5.0.0-alpha.6", + "astro": "^5.0.0-alpha.7", "react": "^18.3.1", "react-dom": "^18.3.1" } diff --git a/examples/framework-solid/package.json b/examples/framework-solid/package.json index e00e56146294..5002bb9a8b69 100644 --- a/examples/framework-solid/package.json +++ b/examples/framework-solid/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@astrojs/solid-js": "^4.4.1", - "astro": "^5.0.0-alpha.6", + "astro": "^5.0.0-alpha.7", "solid-js": "^1.8.22" } } diff --git a/examples/framework-svelte/package.json b/examples/framework-svelte/package.json index da249f7f9bff..4dbcbda27106 100644 --- a/examples/framework-svelte/package.json +++ b/examples/framework-svelte/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@astrojs/svelte": "^6.0.0-alpha.0", - "astro": "^5.0.0-alpha.6", + "astro": "^5.0.0-alpha.7", "svelte": "^4.2.19" } } diff --git a/examples/framework-vue/package.json b/examples/framework-vue/package.json index 7b797e7a32fc..de6bc4b761f2 100644 --- a/examples/framework-vue/package.json +++ b/examples/framework-vue/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@astrojs/vue": "^5.0.0-alpha.0", - "astro": "^5.0.0-alpha.6", + "astro": "^5.0.0-alpha.7", "vue": "^3.4.38" } } diff --git a/examples/hackernews/package.json b/examples/hackernews/package.json index 88ebb0c77a16..ba39a098cb6f 100644 --- a/examples/hackernews/package.json +++ b/examples/hackernews/package.json @@ -12,6 +12,6 @@ }, "dependencies": { "@astrojs/node": "^9.0.0-alpha.1", - "astro": "^5.0.0-alpha.6" + "astro": "^5.0.0-alpha.7" } } diff --git a/examples/integration/package.json b/examples/integration/package.json index 1b3cf734664c..9bb5380a7619 100644 --- a/examples/integration/package.json +++ b/examples/integration/package.json @@ -15,7 +15,7 @@ ], "scripts": {}, "devDependencies": { - "astro": "^5.0.0-alpha.6" + "astro": "^5.0.0-alpha.7" }, "peerDependencies": { "astro": "^4.0.0" diff --git a/examples/middleware/package.json b/examples/middleware/package.json index c4442a2febcd..b5b258d5ba9d 100644 --- a/examples/middleware/package.json +++ b/examples/middleware/package.json @@ -13,7 +13,7 @@ }, "dependencies": { "@astrojs/node": "^9.0.0-alpha.1", - "astro": "^5.0.0-alpha.6", + "astro": "^5.0.0-alpha.7", "html-minifier": "^4.0.0" }, "devDependencies": { diff --git a/examples/minimal/package.json b/examples/minimal/package.json index 6d4836a965b0..ed6d92798fd1 100644 --- a/examples/minimal/package.json +++ b/examples/minimal/package.json @@ -11,6 +11,6 @@ "astro": "astro" }, "dependencies": { - "astro": "^5.0.0-alpha.6" + "astro": "^5.0.0-alpha.7" } } diff --git a/examples/non-html-pages/package.json b/examples/non-html-pages/package.json index 3e0fc489af11..3b0fdf468642 100644 --- a/examples/non-html-pages/package.json +++ b/examples/non-html-pages/package.json @@ -11,6 +11,6 @@ "astro": "astro" }, "dependencies": { - "astro": "^5.0.0-alpha.6" + "astro": "^5.0.0-alpha.7" } } diff --git a/examples/portfolio/package.json b/examples/portfolio/package.json index fb4eeb9f9c8a..84782d028671 100644 --- a/examples/portfolio/package.json +++ b/examples/portfolio/package.json @@ -11,6 +11,6 @@ "astro": "astro" }, "dependencies": { - "astro": "^5.0.0-alpha.6" + "astro": "^5.0.0-alpha.7" } } diff --git a/examples/server-islands/package.json b/examples/server-islands/package.json index 8a41764536c8..84a43a672e77 100644 --- a/examples/server-islands/package.json +++ b/examples/server-islands/package.json @@ -17,7 +17,7 @@ "@tailwindcss/forms": "^0.5.9", "@types/react": "^18.3.5", "@types/react-dom": "^18.3.0", - "astro": "^5.0.0-alpha.6", + "astro": "^5.0.0-alpha.7", "postcss": "^8.4.43", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/examples/ssr/package.json b/examples/ssr/package.json index d25f5f4a11c6..98b2c37fe238 100644 --- a/examples/ssr/package.json +++ b/examples/ssr/package.json @@ -14,7 +14,7 @@ "dependencies": { "@astrojs/node": "^9.0.0-alpha.1", "@astrojs/svelte": "^6.0.0-alpha.0", - "astro": "^5.0.0-alpha.6", + "astro": "^5.0.0-alpha.7", "svelte": "^4.2.19" } } diff --git a/examples/starlog/package.json b/examples/starlog/package.json index f4f8605e230a..ec255e51c895 100644 --- a/examples/starlog/package.json +++ b/examples/starlog/package.json @@ -10,7 +10,7 @@ "astro": "astro" }, "dependencies": { - "astro": "^5.0.0-alpha.6", + "astro": "^5.0.0-alpha.7", "sass": "^1.77.8", "sharp": "^0.33.3" } diff --git a/examples/toolbar-app/package.json b/examples/toolbar-app/package.json index aa832cb668b3..2e91f896519d 100644 --- a/examples/toolbar-app/package.json +++ b/examples/toolbar-app/package.json @@ -15,6 +15,6 @@ "./app": "./dist/app.js" }, "devDependencies": { - "astro": "^5.0.0-alpha.6" + "astro": "^5.0.0-alpha.7" } } diff --git a/examples/view-transitions/package.json b/examples/view-transitions/package.json index f5dd2717d33f..0678b74b78f9 100644 --- a/examples/view-transitions/package.json +++ b/examples/view-transitions/package.json @@ -12,6 +12,6 @@ "devDependencies": { "@astrojs/tailwind": "^6.0.0-alpha.0", "@astrojs/node": "^9.0.0-alpha.1", - "astro": "^5.0.0-alpha.6" + "astro": "^5.0.0-alpha.7" } } diff --git a/examples/with-markdoc/package.json b/examples/with-markdoc/package.json index 14152bb8ba68..7516637758f7 100644 --- a/examples/with-markdoc/package.json +++ b/examples/with-markdoc/package.json @@ -12,6 +12,6 @@ }, "dependencies": { "@astrojs/markdoc": "^1.0.0-alpha.1", - "astro": "^5.0.0-alpha.6" + "astro": "^5.0.0-alpha.7" } } diff --git a/examples/with-markdown-plugins/package.json b/examples/with-markdown-plugins/package.json index 9edad4072e94..f0c25d088591 100644 --- a/examples/with-markdown-plugins/package.json +++ b/examples/with-markdown-plugins/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@astrojs/markdown-remark": "^6.0.0-alpha.1", - "astro": "^5.0.0-alpha.6", + "astro": "^5.0.0-alpha.7", "hast-util-select": "^6.0.2", "rehype-autolink-headings": "^7.1.0", "rehype-slug": "^6.0.0", diff --git a/examples/with-markdown-shiki/package.json b/examples/with-markdown-shiki/package.json index d278d1e84842..e28cb8d120e0 100644 --- a/examples/with-markdown-shiki/package.json +++ b/examples/with-markdown-shiki/package.json @@ -11,6 +11,6 @@ "astro": "astro" }, "dependencies": { - "astro": "^5.0.0-alpha.6" + "astro": "^5.0.0-alpha.7" } } diff --git a/examples/with-mdx/package.json b/examples/with-mdx/package.json index c1e3586c92a3..07a400adc8be 100644 --- a/examples/with-mdx/package.json +++ b/examples/with-mdx/package.json @@ -12,8 +12,8 @@ }, "dependencies": { "@astrojs/mdx": "^4.0.0-alpha.2", - "@astrojs/preact": "^3.5.2", - "astro": "^5.0.0-alpha.6", + "@astrojs/preact": "^3.5.3", + "astro": "^5.0.0-alpha.7", "preact": "^10.23.2" } } diff --git a/examples/with-nanostores/package.json b/examples/with-nanostores/package.json index 060c95200485..fa8b4697128e 100644 --- a/examples/with-nanostores/package.json +++ b/examples/with-nanostores/package.json @@ -13,7 +13,7 @@ "dependencies": { "@astrojs/preact": "^3.5.3", "@nanostores/preact": "^0.5.2", - "astro": "^5.0.0-alpha.6", + "astro": "^5.0.0-alpha.7", "nanostores": "^0.11.3", "preact": "^10.23.2" } diff --git a/examples/with-tailwindcss/package.json b/examples/with-tailwindcss/package.json index 0e295fa7c511..b25a27f868e9 100644 --- a/examples/with-tailwindcss/package.json +++ b/examples/with-tailwindcss/package.json @@ -14,7 +14,7 @@ "@astrojs/mdx": "^4.0.0-alpha.2", "@astrojs/tailwind": "^6.0.0-alpha.0", "@types/canvas-confetti": "^1.6.4", - "astro": "^5.0.0-alpha.6", + "astro": "^5.0.0-alpha.7", "autoprefixer": "^10.4.20", "canvas-confetti": "^1.9.3", "postcss": "^8.4.45", diff --git a/examples/with-vitest/package.json b/examples/with-vitest/package.json index 7aa75dcea924..0790d01d88fa 100644 --- a/examples/with-vitest/package.json +++ b/examples/with-vitest/package.json @@ -12,7 +12,7 @@ "test": "vitest" }, "dependencies": { - "astro": "^5.0.0-alpha.6", + "astro": "^5.0.0-alpha.7", "vitest": "^2.0.5" } } diff --git a/packages/astro/CHANGELOG.md b/packages/astro/CHANGELOG.md index eaf252d703cf..038cd15a3f03 100644 --- a/packages/astro/CHANGELOG.md +++ b/packages/astro/CHANGELOG.md @@ -1,5 +1,202 @@ # astro +## 5.0.0-alpha.7 + +### Major Changes + +- [#11864](https://github.com/withastro/astro/pull/11864) [`ee38b3a`](https://github.com/withastro/astro/commit/ee38b3a94697fe883ce8300eff9f001470b8adb6) Thanks [@ematipico](https://github.com/ematipico)! - ### [changed]: `entryPoint` type inside the hook `astro:build:ssr` + In Astro v4.x, the `entryPoint` type was `RouteData`. + + Astro v5.0 the `entryPoint` type is `IntegrationRouteData`, which contains a subset of the `RouteData` type. The fields `isIndex` and `fallbackRoutes` were removed. + + #### What should I do? + + Update your adapter to change the type of `entryPoint` from `RouteData` to `IntegrationRouteData`. + + ```diff + -import type {RouteData} from 'astro'; + +import type {IntegrationRouteData} from "astro" + + -function useRoute(route: RouteData) { + +function useRoute(route: IntegrationRouteData) { + + } + ``` + +- [#11908](https://github.com/withastro/astro/pull/11908) [`518433e`](https://github.com/withastro/astro/commit/518433e433fe69ee3bbbb1f069181cd9eb69ec9a) Thanks [@Princesseuh](https://github.com/Princesseuh)! - The `image.endpoint` config now allow customizing the route of the image endpoint in addition to the entrypoint. This can be useful in niche situations where the default route `/_image` conflicts with an existing route or your local server setup. + + ```js + import { defineConfig } from 'astro/config'; + + defineConfig({ + image: { + endpoint: { + route: '/image', + entrypoint: './src/image_endpoint.ts', + }, + }, + }); + ``` + +- [#11806](https://github.com/withastro/astro/pull/11806) [`f7f2338`](https://github.com/withastro/astro/commit/f7f2338c2b96975001b5c782f458710e9cc46d74) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Removes the `assets` property on `supportedAstroFeatures` for adapters, as it did not reflect reality properly in many cases. + + Now, relating to assets, only a single `sharpImageService` property is available, determining if the adapter is compatible with the built-in sharp image service. + +- [#11864](https://github.com/withastro/astro/pull/11864) [`ee38b3a`](https://github.com/withastro/astro/commit/ee38b3a94697fe883ce8300eff9f001470b8adb6) Thanks [@ematipico](https://github.com/ematipico)! - ### [changed]: `routes` type inside the hook `astro:build:done` + In Astro v4.x, the `routes` type was `RouteData`. + + Astro v5.0 the `routes` type is `IntegrationRouteData`, which contains a subset of the `RouteData` type. The fields `isIndex` and `fallbackRoutes` were removed. + + #### What should I do? + + Update your adapter to change the type of `routes` from `RouteData` to `IntegrationRouteData`. + + ```diff + -import type {RouteData} from 'astro'; + +import type {IntegrationRouteData} from "astro" + + -function useRoute(route: RouteData) { + +function useRoute(route: IntegrationRouteData) { + + } + ``` + +- [#11864](https://github.com/withastro/astro/pull/11864) [`ee38b3a`](https://github.com/withastro/astro/commit/ee38b3a94697fe883ce8300eff9f001470b8adb6) Thanks [@ematipico](https://github.com/ematipico)! - ### [changed]: `RouteData.distURL` is now an array + In Astro v4.x, `RouteData.distURL` was `undefined` or a `URL` + + Astro v5.0, `RouteData.distURL` is `undefined` or an array of `URL`. This was a bug, because a route can generate multiple files on disk, especially when using dynamic routes such as `[slug]` or `[...slug]`. + + #### What should I do? + + Update your code to handle `RouteData.distURL` as an array. + + ```diff + if (route.distURL) { + - if (route.distURL.endsWith('index.html')) { + - // do something + - } + + for (const url of route.distURL) { + + if (url.endsWith('index.html')) { + + // do something + + } + + } + } + ``` + +### Minor Changes + +- [#11806](https://github.com/withastro/astro/pull/11806) [`f7f2338`](https://github.com/withastro/astro/commit/f7f2338c2b96975001b5c782f458710e9cc46d74) Thanks [@Princesseuh](https://github.com/Princesseuh)! - The value of the different properties on `supportedAstroFeatures` for adapters can now be objects, with a `support` and `message` properties. The content of the `message` property will be shown in the Astro CLI when the adapter is not compatible with the feature, allowing one to give a better informational message to the user. + + This is notably useful with the new `limited` value, to explain to the user why support is limited. + +- [#11955](https://github.com/withastro/astro/pull/11955) [`d813262`](https://github.com/withastro/astro/commit/d8132626b05f150341c0628d6078fdd86b89aaed) Thanks [@matthewp](https://github.com/matthewp)! - [Server Islands](https://astro.build/blog/future-of-astro-server-islands/) introduced behind an experimental flag in [v4.12.0](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md#4120) is no longer experimental and is available for general use. + + Server islands are Astro's solution for highly cacheable pages of mixed static and dynamic content. They allow you to specify components that should run on the server, allowing the rest of the page to be more aggressively cached, or even generated statically. + + Turn any `.astro` component into a server island by adding the `server:defer` directive and optionally, fallback placeholder content. It will be rendered dynamically at runtime outside the context of the rest of the page, allowing you to add longer cache headers for the pages, or even prerender them. + + ```astro + --- + import Avatar from '../components/Avatar.astro'; + import GenericUser from '../components/GenericUser.astro'; + --- + +
+

Page Title

+
+ + + +
+
+ ``` + + If you were previously using this feature, please remove the experimental flag from your Astro config: + + ```diff + import { defineConfig } from 'astro/config'; + + export default defineConfig({ + experimental { + - serverIslands: true, + }, + }); + ``` + + If you have been waiting for stabilization before using server islands, you can now do so. + + Please see the [server island documentation](https://docs.astro.build/en/guides/server-islands/) for more about this feature. + +- [#11806](https://github.com/withastro/astro/pull/11806) [`f7f2338`](https://github.com/withastro/astro/commit/f7f2338c2b96975001b5c782f458710e9cc46d74) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Adds a new `limited` value for the different properties of `supportedAstroFeatures` for adapters, which indicates that the adapter is compatible with the feature, but with some limitations. This is useful for adapters that support a feature, but not in all cases or with all options. + +- [#11925](https://github.com/withastro/astro/pull/11925) [`74722cb`](https://github.com/withastro/astro/commit/74722cb81c46d4d29c8c5a2127f896da4d8d3235) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - Updates `astro/config` import to reference `astro/client` types + + When importing `astro/config`, types from `astro/client` will be made automatically available to your project. If your project `tsconfig.json` changes how references behave, you'll still have access to these types after running `astro sync`. + +### Patch Changes + +- [#11974](https://github.com/withastro/astro/pull/11974) [`60211de`](https://github.com/withastro/astro/commit/60211defbfb2992ba17d1369e71c146d8928b09a) Thanks [@ascorbic](https://github.com/ascorbic)! - Exports the `RenderResult` type + +- [#11939](https://github.com/withastro/astro/pull/11939) [`7b09c62`](https://github.com/withastro/astro/commit/7b09c62b565cd7b50c35fb68d390729f936a43fb) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Adds support for Zod discriminated unions on Action form inputs. This allows forms with different inputs to be submitted to the same action, using a given input to decide which object should be used for validation. + + This example accepts either a `create` or `update` form submission, and uses the `type` field to determine which object to validate against. + + ```ts + import { defineAction } from 'astro:actions'; + import { z } from 'astro:schema'; + + export const server = { + changeUser: defineAction({ + accept: 'form', + input: z.discriminatedUnion('type', [ + z.object({ + type: z.literal('create'), + name: z.string(), + email: z.string().email(), + }), + z.object({ + type: z.literal('update'), + id: z.number(), + name: z.string(), + email: z.string().email(), + }), + ]), + async handler(input) { + if (input.type === 'create') { + // input is { type: 'create', name: string, email: string } + } else { + // input is { type: 'update', id: number, name: string, email: string } + } + }, + }), + }; + ``` + + The corresponding `create` and `update` forms may look like this: + + ```astro + --- + import { actions } from 'astro:actions'; + --- + + +
+ + + + +
+ + +
+ + + + + +
+ ``` + ## 5.0.0-alpha.6 ### Major Changes diff --git a/packages/astro/package.json b/packages/astro/package.json index 1e7c8f4af5a8..5c8d070f04e3 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -1,6 +1,6 @@ { "name": "astro", - "version": "5.0.0-alpha.6", + "version": "5.0.0-alpha.7", "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.", "type": "module", "author": "withastro", diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts index c420e85c415d..1757dc65c914 100644 --- a/packages/astro/src/core/build/index.ts +++ b/packages/astro/src/core/build/index.ts @@ -213,7 +213,7 @@ class AstroBuilder { const hasServerIslands = this.settings.serverIslandNameMap.size > 0; // Error if there are server islands but no adapter provided. - if(hasServerIslands && this.settings.buildOutput !== 'server') { + if (hasServerIslands && this.settings.buildOutput !== 'server') { throw new AstroError(AstroErrorData.NoAdapterInstalledServerIslands); } diff --git a/packages/astro/test/server-islands.test.js b/packages/astro/test/server-islands.test.js index 86956f0d1ae8..5055369727bf 100644 --- a/packages/astro/test/server-islands.test.js +++ b/packages/astro/test/server-islands.test.js @@ -69,7 +69,7 @@ describe('Server islands', () => { describe('build', () => { before(async () => { await fixture.build({ - adapter: testAdapter() + adapter: testAdapter(), }); }); @@ -89,10 +89,10 @@ describe('Server islands', () => { it('Errors during the build', async () => { try { await fixture.build({ - adapter: undefined + adapter: undefined, }); assert.equal(true, false, 'should not have succeeded'); - } catch(err) { + } catch (err) { assert.equal(err.title, 'Cannot use Server Islands without an adapter.'); } }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a272c03a6f12..e5e027330101 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -116,7 +116,7 @@ importers: examples/basics: dependencies: astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro examples/blog: @@ -131,13 +131,13 @@ importers: specifier: ^3.1.6 version: link:../../packages/integrations/sitemap astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro examples/component: devDependencies: astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro examples/container-with-vitest: @@ -146,7 +146,7 @@ importers: specifier: ^3.6.2 version: link:../../packages/integrations/react astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro react: specifier: ^18.3.1 @@ -177,7 +177,7 @@ importers: specifier: ^3.14.1 version: 3.14.1 astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro examples/framework-multiple: @@ -204,7 +204,7 @@ importers: specifier: ^18.3.0 version: 18.3.0 astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro preact: specifier: ^10.23.2 @@ -234,7 +234,7 @@ importers: specifier: ^1.3.0 version: 1.3.0(preact@10.23.2) astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro preact: specifier: ^10.23.2 @@ -252,7 +252,7 @@ importers: specifier: ^18.3.0 version: 18.3.0 astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro react: specifier: ^18.3.1 @@ -267,7 +267,7 @@ importers: specifier: ^4.4.1 version: link:../../packages/integrations/solid astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro solid-js: specifier: ^1.8.22 @@ -279,7 +279,7 @@ importers: specifier: ^6.0.0-alpha.0 version: link:../../packages/integrations/svelte astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro svelte: specifier: ^4.2.19 @@ -291,7 +291,7 @@ importers: specifier: ^5.0.0-alpha.0 version: link:../../packages/integrations/vue astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro vue: specifier: ^3.4.38 @@ -303,13 +303,13 @@ importers: specifier: ^9.0.0-alpha.1 version: 9.0.0-alpha.1(astro@packages+astro) astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro examples/integration: devDependencies: astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro examples/middleware: @@ -318,7 +318,7 @@ importers: specifier: ^9.0.0-alpha.1 version: 9.0.0-alpha.1(astro@packages+astro) astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro html-minifier: specifier: ^4.0.0 @@ -331,19 +331,19 @@ importers: examples/minimal: dependencies: astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro examples/non-html-pages: dependencies: astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro examples/portfolio: dependencies: astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro examples/server-islands: @@ -370,7 +370,7 @@ importers: specifier: ^18.3.0 version: 18.3.0 astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro postcss: specifier: ^8.4.43 @@ -394,7 +394,7 @@ importers: specifier: ^6.0.0-alpha.0 version: link:../../packages/integrations/svelte astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro svelte: specifier: ^4.2.19 @@ -403,7 +403,7 @@ importers: examples/starlog: dependencies: astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro sass: specifier: ^1.77.8 @@ -415,7 +415,7 @@ importers: examples/toolbar-app: devDependencies: astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro examples/view-transitions: @@ -427,7 +427,7 @@ importers: specifier: ^6.0.0-alpha.0 version: link:../../packages/integrations/tailwind astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro examples/with-markdoc: @@ -436,7 +436,7 @@ importers: specifier: ^1.0.0-alpha.1 version: link:../../packages/integrations/markdoc astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro examples/with-markdown-plugins: @@ -445,7 +445,7 @@ importers: specifier: ^6.0.0-alpha.1 version: link:../../packages/markdown/remark astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro hast-util-select: specifier: ^6.0.2 @@ -466,7 +466,7 @@ importers: examples/with-markdown-shiki: dependencies: astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro examples/with-mdx: @@ -475,10 +475,10 @@ importers: specifier: ^4.0.0-alpha.2 version: link:../../packages/integrations/mdx '@astrojs/preact': - specifier: ^3.5.2 + specifier: ^3.5.3 version: link:../../packages/integrations/preact astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro preact: specifier: ^10.23.2 @@ -493,7 +493,7 @@ importers: specifier: ^0.5.2 version: 0.5.2(nanostores@0.11.3)(preact@10.23.2) astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro nanostores: specifier: ^0.11.3 @@ -514,7 +514,7 @@ importers: specifier: ^1.6.4 version: 1.6.4 astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro autoprefixer: specifier: ^10.4.20 @@ -532,7 +532,7 @@ importers: examples/with-vitest: dependencies: astro: - specifier: ^5.0.0-alpha.6 + specifier: ^5.0.0-alpha.7 version: link:../../packages/astro vitest: specifier: ^2.0.5