astro 4.0.4 → 4.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/astro-jsx.d.ts +8 -2
  2. package/astro.js +1 -1
  3. package/components/Picture.astro +1 -1
  4. package/dist/assets/build/generate.js +2 -1
  5. package/dist/assets/endpoint/config.d.ts +2 -0
  6. package/dist/assets/endpoint/config.js +12 -0
  7. package/dist/assets/endpoint/generic.js +2 -1
  8. package/dist/assets/endpoint/node.js +2 -1
  9. package/dist/assets/internal.d.ts +2 -6
  10. package/dist/assets/internal.js +12 -31
  11. package/dist/assets/services/service.js +2 -1
  12. package/dist/assets/utils/imageKind.d.ts +3 -0
  13. package/dist/assets/utils/imageKind.js +10 -0
  14. package/dist/assets/utils/index.d.ts +2 -0
  15. package/dist/assets/utils/index.js +17 -0
  16. package/dist/assets/utils/remotePattern.d.ts +2 -0
  17. package/dist/assets/utils/remotePattern.js +11 -0
  18. package/dist/assets/utils/transformToPath.js +1 -1
  19. package/dist/assets/vite-plugin-assets.js +1 -1
  20. package/dist/core/app/index.js +19 -7
  21. package/dist/core/build/index.js +1 -1
  22. package/dist/core/build/static-build.js +1 -1
  23. package/dist/core/config/schema.d.ts +360 -360
  24. package/dist/core/constants.js +1 -1
  25. package/dist/core/create-vite.js +2 -0
  26. package/dist/core/dev/container.js +1 -1
  27. package/dist/core/dev/dev.js +1 -1
  28. package/dist/core/errors/errors-data.d.ts +6 -0
  29. package/dist/core/errors/errors-data.js +12 -2
  30. package/dist/core/messages.js +2 -2
  31. package/dist/core/routing/manifest/create.js +1 -1
  32. package/dist/integrations/astroFeaturesValidation.js +7 -7
  33. package/dist/transitions/router.js +7 -5
  34. package/dist/vite-plugin-astro-server/error.d.ts +7 -0
  35. package/dist/vite-plugin-astro-server/error.js +24 -0
  36. package/dist/vite-plugin-astro-server/plugin.js +33 -7
  37. package/dist/vite-plugin-astro-server/request.js +3 -16
  38. package/dist/vite-plugin-fileurl/index.d.ts +2 -0
  39. package/dist/vite-plugin-fileurl/index.js +14 -0
  40. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "4.0.4";
1
+ const ASTRO_VERSION = "4.0.6";
2
2
  const SUPPORTED_MARKDOWN_FILE_EXTENSIONS = [
3
3
  ".markdown",
4
4
  ".mdown",
@@ -31,6 +31,7 @@ import { vitePluginSSRManifest } from "../vite-plugin-ssr-manifest/index.js";
31
31
  import { createViteLogger } from "./logger/vite.js";
32
32
  import { vitePluginMiddleware } from "./middleware/vite-plugin.js";
33
33
  import { joinPaths } from "./path.js";
34
+ import vitePluginFileURL from "../vite-plugin-fileurl/index.js";
34
35
  const ALWAYS_NOEXTERNAL = [
35
36
  // This is only because Vite's native ESM doesn't resolve "exports" correctly.
36
37
  "astro",
@@ -113,6 +114,7 @@ async function createVite(commandConfig, { settings, logger, mode, command, fs =
113
114
  astroPrefetch({ settings }),
114
115
  astroTransitions({ settings }),
115
116
  astroDevOverlay({ settings, logger }),
117
+ vitePluginFileURL({}),
116
118
  !!settings.config.i18n && astroInternationalization({ settings })
117
119
  ],
118
120
  publicDir: fileURLToPath(settings.config.publicDir),
@@ -1,6 +1,6 @@
1
1
  import nodeFs from "node:fs";
2
2
  import * as vite from "vite";
3
- import { injectImageEndpoint } from "../../assets/internal.js";
3
+ import { injectImageEndpoint } from "../../assets/endpoint/config.js";
4
4
  import {
5
5
  runHookConfigDone,
6
6
  runHookConfigSetup,
@@ -21,7 +21,7 @@ async function dev(inlineConfig) {
21
21
  base: restart.container.settings.config.base
22
22
  })
23
23
  );
24
- const currentVersion = "4.0.4";
24
+ const currentVersion = "4.0.6";
25
25
  if (currentVersion.includes("-")) {
26
26
  logger.warn("SKIP_FORMAT", msg.prerelease({ currentVersion }));
27
27
  }
@@ -1155,3 +1155,9 @@ export declare const UnknownError: {
1155
1155
  name: string;
1156
1156
  title: string;
1157
1157
  };
1158
+ export declare const UnhandledRejection: {
1159
+ name: string;
1160
+ title: string;
1161
+ message: (stack: string) => string;
1162
+ hint: string;
1163
+ };
@@ -230,8 +230,8 @@ const ResponseSentError = {
230
230
  };
231
231
  const MiddlewareNoDataOrNextCalled = {
232
232
  name: "MiddlewareNoDataOrNextCalled",
233
- title: "The middleware didn't return a response or call `next`.",
234
- message: "The middleware needs to either return a `Response` object or call the `next` function."
233
+ title: "The middleware didn't return a `Response`.",
234
+ message: "Make sure your middleware returns a `Response` object, either directly or by returning the `Response` from calling the `next` function."
235
235
  };
236
236
  const MiddlewareNotAResponse = {
237
237
  name: "MiddlewareNotAResponse",
@@ -440,6 +440,15 @@ const CantRenderPage = {
440
440
  hint: "If you expect to find a route here, this may be an Astro bug. Please file an issue/restart the dev server"
441
441
  };
442
442
  const UnknownError = { name: "UnknownError", title: "Unknown Error." };
443
+ const UnhandledRejection = {
444
+ name: "UnhandledRejection",
445
+ title: "Unhandled rejection",
446
+ message: (stack) => {
447
+ return `Astro detected an unhandled rejection. Here's the stack trace:
448
+ ${stack}`;
449
+ },
450
+ hint: "Make sure your promises all have an `await` or a `.catch()` handler."
451
+ };
443
452
  export {
444
453
  AstroGlobNoMatch,
445
454
  AstroGlobUsedOutside,
@@ -503,6 +512,7 @@ export {
503
512
  ResponseSentError,
504
513
  StaticClientAddressNotAvailable,
505
514
  StaticRedirectNotAvailable,
515
+ UnhandledRejection,
506
516
  UnknownCLIError,
507
517
  UnknownCSSError,
508
518
  UnknownCompilerError,
@@ -36,7 +36,7 @@ function serverStart({
36
36
  host,
37
37
  base
38
38
  }) {
39
- const version = "4.0.4";
39
+ const version = "4.0.6";
40
40
  const localPrefix = `${dim("\u2503")} Local `;
41
41
  const networkPrefix = `${dim("\u2503")} Network `;
42
42
  const emptyPrefix = " ".repeat(11);
@@ -258,7 +258,7 @@ function printHelp({
258
258
  message.push(
259
259
  linebreak(),
260
260
  ` ${bgGreen(black(` ${commandName} `))} ${green(
261
- `v${"4.0.4"}`
261
+ `v${"4.0.6"}`
262
262
  )} ${headline}`
263
263
  );
264
264
  }
@@ -318,7 +318,7 @@ This route collides with: "${collision.component}".`
318
318
  if (/^https?:\/\//.test(destination)) {
319
319
  logger.warn(
320
320
  "redirects",
321
- `Redirecting to an external URL is not officially supported: ${from} -> ${to}`
321
+ `Redirecting to an external URL is not officially supported: ${from} -> ${destination}`
322
322
  );
323
323
  }
324
324
  }
@@ -43,9 +43,9 @@ function validateSupportKind(supportKind, adapterName, logger, featureName, hasC
43
43
  if (supportKind === STABLE) {
44
44
  return true;
45
45
  } else if (supportKind === DEPRECATED) {
46
- featureIsDeprecated(adapterName, logger);
46
+ featureIsDeprecated(adapterName, logger, featureName);
47
47
  } else if (supportKind === EXPERIMENTAL) {
48
- featureIsExperimental(adapterName, logger);
48
+ featureIsExperimental(adapterName, logger, featureName);
49
49
  }
50
50
  if (hasCorrectConfig() && supportKind === UNSUPPORTED) {
51
51
  featureIsUnsupported(adapterName, logger, featureName);
@@ -55,18 +55,18 @@ function validateSupportKind(supportKind, adapterName, logger, featureName, hasC
55
55
  }
56
56
  }
57
57
  function featureIsUnsupported(adapterName, logger, featureName) {
58
- logger.error("config", `The feature ${featureName} is not supported (used by ${adapterName}).`);
58
+ logger.error("config", `The feature "${featureName}" is not supported (used by ${adapterName}).`);
59
59
  }
60
- function featureIsExperimental(adapterName, logger) {
60
+ function featureIsExperimental(adapterName, logger, featureName) {
61
61
  logger.warn(
62
62
  "config",
63
- `The feature is experimental and subject to change (used by ${adapterName}).`
63
+ `The feature "${featureName}" is experimental and subject to change (used by ${adapterName}).`
64
64
  );
65
65
  }
66
- function featureIsDeprecated(adapterName, logger) {
66
+ function featureIsDeprecated(adapterName, logger, featureName) {
67
67
  logger.warn(
68
68
  "config",
69
- `The feature is deprecated and will be removed in the future (used by ${adapterName}).`
69
+ `The feature "${featureName}" is deprecated and will be removed in the future (used by ${adapterName}).`
70
70
  );
71
71
  }
72
72
  const SHARP_SERVICE = "astro/assets/services/sharp";
@@ -1,11 +1,13 @@
1
1
  import { TRANSITION_AFTER_SWAP, doPreparation, doSwap } from "./events.js";
2
+ const inBrowser = import.meta.env.SSR === false;
3
+ const pushState = inBrowser && history.pushState.bind(history);
4
+ const replaceState = inBrowser && history.replaceState.bind(history);
2
5
  const updateScrollPosition = (positions) => {
3
6
  if (history.state) {
4
7
  history.scrollRestoration = "manual";
5
- history.replaceState({ ...history.state, ...positions }, "");
8
+ replaceState({ ...history.state, ...positions }, "");
6
9
  }
7
10
  };
8
- const inBrowser = import.meta.env.SSR === false;
9
11
  const supportsViewTransitions = inBrowser && !!document.startViewTransition;
10
12
  const transitionEnabledOnThisPage = () => inBrowser && !!document.querySelector('[name="astro-view-transitions-enabled"]');
11
13
  const samePage = (thisLocation, otherLocation) => thisLocation.pathname === otherLocation.pathname && thisLocation.search === otherLocation.search;
@@ -43,7 +45,7 @@ if (inBrowser) {
43
45
  currentHistoryIndex = history.state.index;
44
46
  scrollTo({ left: history.state.scrollX, top: history.state.scrollY });
45
47
  } else if (transitionEnabledOnThisPage()) {
46
- history.replaceState({ index: currentHistoryIndex, scrollX, scrollY }, "");
48
+ replaceState({ index: currentHistoryIndex, scrollX, scrollY }, "");
47
49
  history.scrollRestoration = "manual";
48
50
  }
49
51
  }
@@ -117,7 +119,7 @@ const moveToLocation = (to, from, options, historyState) => {
117
119
  if (to.href !== location.href && !historyState) {
118
120
  if (options.history === "replace") {
119
121
  const current = history.state;
120
- history.replaceState(
122
+ replaceState(
121
123
  {
122
124
  ...options.state,
123
125
  index: current.index,
@@ -128,7 +130,7 @@ const moveToLocation = (to, from, options, historyState) => {
128
130
  to.href
129
131
  );
130
132
  } else {
131
- history.pushState(
133
+ pushState(
132
134
  { ...options.state, index: ++currentHistoryIndex, scrollX: 0, scrollY: 0 },
133
135
  "",
134
136
  to.href
@@ -0,0 +1,7 @@
1
+ import type { ModuleLoader } from '../core/module-loader/index.js';
2
+ import type { AstroConfig } from '../@types/astro.js';
3
+ import type DevPipeline from './devPipeline.js';
4
+ export declare function recordServerError(loader: ModuleLoader, config: AstroConfig, pipeline: DevPipeline, _err: unknown): {
5
+ error: Error;
6
+ errorWithMetadata: import("../core/errors/errors.js").ErrorWithMetadata;
7
+ };
@@ -0,0 +1,24 @@
1
+ import { collectErrorMetadata } from "../core/errors/dev/index.js";
2
+ import { createSafeError } from "../core/errors/index.js";
3
+ import { formatErrorMessage } from "../core/messages.js";
4
+ import { eventError, telemetry } from "../events/index.js";
5
+ function recordServerError(loader, config, pipeline, _err) {
6
+ const err = createSafeError(_err);
7
+ try {
8
+ loader.fixStacktrace(err);
9
+ } catch {
10
+ }
11
+ const errorWithMetadata = collectErrorMetadata(err, config.root);
12
+ telemetry.record(eventError({ cmd: "dev", err: errorWithMetadata, isFatal: false }));
13
+ pipeline.logger.error(
14
+ null,
15
+ formatErrorMessage(errorWithMetadata, pipeline.logger.level() === "debug")
16
+ );
17
+ return {
18
+ error: err,
19
+ errorWithMetadata
20
+ };
21
+ }
22
+ export {
23
+ recordServerError
24
+ };
@@ -5,6 +5,12 @@ import { baseMiddleware } from "./base.js";
5
5
  import { createController } from "./controller.js";
6
6
  import DevPipeline from "./devPipeline.js";
7
7
  import { handleRequest } from "./request.js";
8
+ import { AstroError, AstroErrorData } from "../core/errors/index.js";
9
+ import { getViteErrorPayload } from "../core/errors/dev/index.js";
10
+ import { AsyncLocalStorage } from "node:async_hooks";
11
+ import { IncomingMessage } from "node:http";
12
+ import { setRouteError } from "./server-state.js";
13
+ import { recordServerError } from "./error.js";
8
14
  function createVitePluginAstroServer({
9
15
  settings,
10
16
  logger,
@@ -18,6 +24,7 @@ function createVitePluginAstroServer({
18
24
  const pipeline = new DevPipeline({ logger, manifest, settings, loader });
19
25
  let manifestData = createRouteManifest({ settings, fsMod }, logger);
20
26
  const controller = createController({ loader });
27
+ const localStorage = new AsyncLocalStorage();
21
28
  function rebuildManifest(needsManifestRebuild) {
22
29
  pipeline.clearRouteCache();
23
30
  if (needsManifestRebuild) {
@@ -27,6 +34,23 @@ function createVitePluginAstroServer({
27
34
  viteServer.watcher.on("add", rebuildManifest.bind(null, true));
28
35
  viteServer.watcher.on("unlink", rebuildManifest.bind(null, true));
29
36
  viteServer.watcher.on("change", rebuildManifest.bind(null, false));
37
+ function handleUnhandledRejection(rejection) {
38
+ const error = new AstroError({
39
+ ...AstroErrorData.UnhandledRejection,
40
+ message: AstroErrorData.UnhandledRejection.message(rejection?.stack || rejection)
41
+ });
42
+ const store = localStorage.getStore();
43
+ if (store instanceof IncomingMessage) {
44
+ const request = store;
45
+ setRouteError(controller.state, request.url, error);
46
+ }
47
+ const { errorWithMetadata } = recordServerError(loader, settings.config, pipeline, error);
48
+ setTimeout(
49
+ async () => loader.webSocketSend(await getViteErrorPayload(errorWithMetadata)),
50
+ 200
51
+ );
52
+ }
53
+ process.on("unhandledRejection", handleUnhandledRejection);
30
54
  return () => {
31
55
  viteServer.middlewares.stack.unshift({
32
56
  route: "",
@@ -38,13 +62,15 @@ function createVitePluginAstroServer({
38
62
  response.end();
39
63
  return;
40
64
  }
41
- handleRequest({
42
- pipeline,
43
- manifestData,
44
- controller,
45
- incomingRequest: request,
46
- incomingResponse: response,
47
- manifest
65
+ localStorage.run(request, () => {
66
+ handleRequest({
67
+ pipeline,
68
+ manifestData,
69
+ controller,
70
+ incomingRequest: request,
71
+ incomingResponse: response,
72
+ manifest
73
+ });
48
74
  });
49
75
  });
50
76
  };
@@ -1,12 +1,9 @@
1
- import { collectErrorMetadata } from "../core/errors/dev/index.js";
2
- import { createSafeError } from "../core/errors/index.js";
3
- import { formatErrorMessage } from "../core/messages.js";
4
1
  import { collapseDuplicateSlashes, removeTrailingForwardSlash } from "../core/path.js";
5
- import { eventError, telemetry } from "../events/index.js";
6
2
  import { isServerLikeOutput } from "../prerender/utils.js";
7
3
  import { runWithErrorHandling } from "./controller.js";
8
4
  import { handle500Response } from "./response.js";
9
5
  import { handleRoute, matchRoute } from "./route.js";
6
+ import { recordServerError } from "./error.js";
10
7
  async function handleRequest({
11
8
  pipeline,
12
9
  manifestData,
@@ -64,19 +61,9 @@ async function handleRequest({
64
61
  });
65
62
  },
66
63
  onError(_err) {
67
- const err = createSafeError(_err);
68
- try {
69
- moduleLoader.fixStacktrace(err);
70
- } catch {
71
- }
72
- const errorWithMetadata = collectErrorMetadata(err, config.root);
73
- telemetry.record(eventError({ cmd: "dev", err: errorWithMetadata, isFatal: false }));
74
- pipeline.logger.error(
75
- null,
76
- formatErrorMessage(errorWithMetadata, pipeline.logger.level() === "debug")
77
- );
64
+ const { error, errorWithMetadata } = recordServerError(moduleLoader, config, pipeline, _err);
78
65
  handle500Response(moduleLoader, incomingResponse, errorWithMetadata);
79
- return err;
66
+ return error;
80
67
  }
81
68
  });
82
69
  }
@@ -0,0 +1,2 @@
1
+ import type { Plugin as VitePlugin } from 'vite';
2
+ export default function vitePluginFileURL({}: {}): VitePlugin;
@@ -0,0 +1,14 @@
1
+ function vitePluginFileURL({}) {
2
+ return {
3
+ name: "astro:vite-plugin-file-url",
4
+ resolveId(source, importer) {
5
+ if (source.startsWith("file://")) {
6
+ const rest = source.slice(7);
7
+ return this.resolve(rest, importer);
8
+ }
9
+ }
10
+ };
11
+ }
12
+ export {
13
+ vitePluginFileURL as default
14
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "4.0.4",
3
+ "version": "4.0.6",
4
4
  "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
5
5
  "type": "module",
6
6
  "author": "withastro",
@@ -99,7 +99,7 @@
99
99
  "vendor"
100
100
  ],
101
101
  "dependencies": {
102
- "@astrojs/compiler": "^2.3.2",
102
+ "@astrojs/compiler": "^2.3.4",
103
103
  "@babel/core": "^7.23.3",
104
104
  "@babel/generator": "^7.23.3",
105
105
  "@babel/parser": "^7.23.3",