Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .changeset/dull-beers-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
"astro": minor
---

Adds an option for integration authors to suppress adapter warning/errors in `supportedAstroFeatures`. This is useful when either an warning/error isn't applicable in a specific context or the default one might conflict and confuse users.

To do so, you can add `suppress: "all"` (to suppress both the default and custom message) or `suppress: "default"` (to only suppress the default one):
```ts
setAdapter({
name: 'my-astro-integration',
supportedAstroFeatures: {
staticOutput: "stable",
hybridOutput: "stable",
sharpImageService: {
support: "limited",
message: "The sharp image service isn't available in the deploy environment, but will be used by prerendered pages on build.",
suppress: "default",
},
}
})
```

For more information, see the [Adapter API reference docs](https://docs.astro.build/en/reference/adapter-reference/#astro-features).
7 changes: 7 additions & 0 deletions .changeset/fast-planets-shout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@astrojs/cloudflare": minor
---

Clarifies and reduces a few logs when starting the dev server with `@astrojs/cloudflare`.

Warnings about sharp support will now be suppressed when you have explicitly set an `imageService` option.
68 changes: 38 additions & 30 deletions packages/astro/src/integrations/features-validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ function getSupportMessage(supportKind: AdapterSupport): string | undefined {
return typeof supportKind === 'object' ? supportKind.message : undefined;
}

function getSupportMessageSuppression(supportKind: AdapterSupport): 'all' | 'default' | undefined {
return typeof supportKind === 'object' ? supportKind.suppress : undefined;
}

function validateSupportKind(
supportKind: AdapterSupport,
adapterName: string,
Expand All @@ -117,6 +121,7 @@ function validateSupportKind(
): boolean {
const supportValue = unwrapSupportKind(supportKind);
const message = getSupportMessage(supportKind);
const suppress = getSupportMessageSuppression(supportKind);

if (!supportValue) {
return false;
Expand All @@ -126,7 +131,7 @@ function validateSupportKind(
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);
logFeatureSupport(adapterName, logger, featureName, supportValue, message, suppress);
}

return false;
Expand All @@ -138,38 +143,41 @@ function logFeatureSupport(
featureName: string,
supportKind: AdapterSupport,
adapterMessage?: string,
suppress?: 'all' | 'default',
) {
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;
if (!suppress) {
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;
}
}

// If the adapter specified a custom message, log it after the default message
if (adapterMessage) {
// If the adapter specified a custom message, log it after the default message (when not suppressed)
if (adapterMessage && suppress !== 'all') {
logger.warn('adapter', adapterMessage);
}
}
Expand Down
9 changes: 9 additions & 0 deletions packages/astro/src/types/public/integrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ export type AdapterSupportsKind =
export type AdapterSupportWithMessage = {
support: Exclude<AdapterSupportsKind, 'stable'>;
message: string;
/**
* Determines if a feature support warning/error in the adapter should be suppressed:
* - `"default"`: Suppresses the default warning/error message.
* - `"all"`: Suppresses both the custom and the default warning/error message.
*
* This is useful when the warning/error might not be applicable in certain contexts,
* or the default message might cause confusion and conflict with a custom one.
*/
suppress?: 'all' | 'default';
};

export type AdapterSupport = AdapterSupportsKind | AdapterSupportWithMessage;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { defineConfig } from 'astro/config';
export default defineConfig({
integrations: [
{
name: 'astro-test-feature-support-message-suppression',
hooks: {
'astro:config:done': ({ setAdapter }) => {
setAdapter({
name: 'astro-test-feature-support-message-suppression',
supportedAstroFeatures: {
staticOutput: "stable",
hybridOutput: "stable",
serverOutput: {
support: "experimental",
message: "This should be logged.",
suppress: "default",
},
sharpImageService: {
support: 'limited',
message: 'This shouldn\'t be logged.',
suppress: "all",
},
}
})
},
},
},
],
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "@test/feature-support-message-suppresion",
"type": "module",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"astro": "workspace:*"
}
}
25 changes: 16 additions & 9 deletions packages/integrations/cloudflare/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ import {
} from './utils/cloudflare-module-loader.js';
import { createGetEnv } from './utils/env.js';
import { createRoutesFile, getParts } from './utils/generate-routes-json.js';
import { setImageConfig } from './utils/image-config.js';
import { type ImageService, setImageConfig } from './utils/image-config.js';

export type { Runtime } from './entrypoints/server.js';

export type Options = {
/** Options for handling images. */
imageService?: 'passthrough' | 'cloudflare' | 'compile' | 'custom';
imageService?: ImageService;
/** Configuration for `_routes.json` generation. A _routes.json file controls when your Function is invoked. This file will include three different properties:
*
* - version: Defines the version of the schema. Currently there is only one version of the schema (version 1), however, we may add more in the future and aim to be backwards compatible.
Expand Down Expand Up @@ -148,12 +148,16 @@ export default function createIntegration(args?: Options): AstroIntegration {
if (!session?.driver) {
const sessionDir = isBuild ? undefined : createCodegenDir();
const bindingName = args?.sessionKVBindingName ?? 'SESSION';
logger.info(
`Enabling sessions with ${isBuild ? 'Cloudflare KV' : 'filesystem storage'}. Be sure to define a KV binding named "${bindingName}".`,
);
logger.info(
`If you see the error "Invalid binding \`${bindingName}\`" in your build output, you need to add the binding to your wrangler config file.`,
);

if (isBuild) {
logger.info(
`Enabling sessions with Cloudflare KV for production with the "${bindingName}" KV binding.`,
);
logger.info(
`If you see the error "Invalid binding \`${bindingName}\`" in your build output, you need to add the binding to your wrangler config file.`,
);
}

session = isBuild
? {
...session,
Expand Down Expand Up @@ -241,7 +245,10 @@ export default function createIntegration(args?: Options): AstroIntegration {
sharpImageService: {
support: 'limited',
message:
'Cloudflare does not support sharp. You can use the `compile` image service to compile images at build time. It will not work for any on-demand rendered images.',
'Cloudflare does not support sharp at runtime. However, you can configure `imageService: "compile"` to optimize images with sharp on prerendered pages during build time.',
// For explicitly set image services, we suppress the warning about sharp not being supported at runtime,
// inferring the user is aware of the limitations.
suppress: args?.imageService ? 'all' : 'default',
},
envGetSecret: 'stable',
},
Expand Down
6 changes: 4 additions & 2 deletions packages/integrations/cloudflare/src/utils/image-config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import type { AstroConfig, AstroIntegrationLogger, HookParameters } from 'astro';
import { passthroughImageService, sharpImageService } from 'astro/config';

export type ImageService = 'passthrough' | 'cloudflare' | 'compile' | 'custom';

export function setImageConfig(
service: string,
service: ImageService,
config: AstroConfig['image'],
command: HookParameters<'astro:config:setup'>['command'],
logger: AstroIntegrationLogger,
Expand Down Expand Up @@ -35,7 +37,7 @@ export function setImageConfig(
default:
if (config.service.entrypoint === 'astro/assets/services/sharp') {
logger.warn(
`The current configuration does not support image optimization. To allow your project to build with the original, unoptimized images, the image service has been automatically switched to the 'noop' option. See https://docs.astro.build/en/reference/configuration-reference/#imageservice`,
`The current configuration does not support image optimization. To allow your project to build with the original, unoptimized images, the image service has been automatically switched to the 'passthrough' option. See https://docs.astro.build/en/reference/configuration-reference/#imageservice`,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit of an extra, the option name itself is not noop (although yes, it's a non-operational service). Mostly to make things consistent.

);
return { ...config, service: passthroughImageService() };
}
Expand Down
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading