astro 4.14.4 → 4.14.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 (36) hide show
  1. package/dist/@types/astro.d.ts +7 -6
  2. package/dist/actions/runtime/utils.d.ts +1 -1
  3. package/dist/actions/runtime/virtual/server.d.ts +2 -3
  4. package/dist/actions/runtime/virtual/server.js +17 -3
  5. package/dist/actions/runtime/virtual/shared.d.ts +2 -1
  6. package/dist/actions/runtime/virtual/shared.js +21 -4
  7. package/dist/actions/utils.d.ts +1 -1
  8. package/dist/actions/utils.js +0 -1
  9. package/dist/content/utils.d.ts +1 -1
  10. package/dist/content/utils.js +1 -1
  11. package/dist/core/build/plugins/plugin-content.d.ts +1 -1
  12. package/dist/core/build/plugins/plugin-content.js +0 -1
  13. package/dist/core/build/plugins/plugin-pages.d.ts +1 -1
  14. package/dist/core/build/plugins/plugin-pages.js +0 -1
  15. package/dist/core/config/schema.d.ts +14 -14
  16. package/dist/core/constants.d.ts +4 -0
  17. package/dist/core/constants.js +3 -1
  18. package/dist/core/create-vite.js +1 -1
  19. package/dist/core/dev/dev.js +1 -1
  20. package/dist/core/errors/errors-data.d.ts +13 -0
  21. package/dist/core/errors/errors-data.js +8 -1
  22. package/dist/core/messages.js +2 -2
  23. package/dist/core/render-context.js +2 -2
  24. package/dist/core/viteUtils.d.ts +4 -0
  25. package/dist/core/viteUtils.js +6 -2
  26. package/dist/prefetch/index.js +1 -0
  27. package/dist/runtime/client/dev-toolbar/toolbar.d.ts +1 -1
  28. package/dist/runtime/client/dev-toolbar/toolbar.js +0 -1
  29. package/dist/vite-plugin-astro-server/pipeline.d.ts +1 -1
  30. package/dist/vite-plugin-astro-server/pipeline.js +0 -1
  31. package/dist/vite-plugin-fileurl/index.d.ts +1 -1
  32. package/dist/vite-plugin-fileurl/index.js +2 -1
  33. package/dist/vite-plugin-scanner/index.d.ts +1 -1
  34. package/dist/vite-plugin-scanner/index.js +0 -1
  35. package/package.json +14 -14
  36. package/templates/actions.mjs +3 -1
@@ -4,7 +4,8 @@ import type { MarkdownHeading, MarkdownVFile, RehypePlugins, RemarkPlugins, Rema
4
4
  import type * as babel from '@babel/core';
5
5
  import type * as rollup from 'rollup';
6
6
  import type * as vite from 'vite';
7
- import type { ActionAccept, ActionClient, ActionInputSchema, ActionReturnType } from '../actions/runtime/virtual/server.js';
7
+ import type { z } from 'zod';
8
+ import type { ActionAccept, ActionClient, ActionReturnType } from '../actions/runtime/virtual/server.js';
8
9
  import type { RemotePattern } from '../assets/utils/remotePattern.js';
9
10
  import type { DataEntry, RenderedContent } from '../content/data-store.js';
10
11
  import type { AssetsPrefix, SSRManifest, SerializedSSRManifest } from '../core/app/types.js';
@@ -24,7 +25,7 @@ import type { DevToolbarBadge, DevToolbarButton, DevToolbarCard, DevToolbarHighl
24
25
  import type { AstroComponentFactory, AstroComponentInstance } from '../runtime/server/index.js';
25
26
  import type { TransitionBeforePreparationEvent, TransitionBeforeSwapEvent } from '../transitions/events.js';
26
27
  import type { DeepPartial, OmitIndexSignature, Simplify } from '../type-utils.js';
27
- import type { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './../core/constants.js';
28
+ import type { REDIRECT_STATUS_CODES, SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './../core/constants.js';
28
29
  export type { AstroIntegrationLogger, ToolbarServerHelpers };
29
30
  export type { MarkdownHeading, RehypePlugins, RemarkPlugins, ShikiConfig, } from '@astrojs/markdown-remark';
30
31
  export type { ExternalImageService, ImageService, LocalImageService, } from '../assets/services/service.js';
@@ -2160,7 +2161,7 @@ export interface AstroUserConfig {
2160
2161
  *
2161
2162
  * const post = await getEntry('blog', Astro.params.slug);
2162
2163
  *
2163
- * const { Content, headings } = await render(entry);
2164
+ * const { Content, headings } = await render(post);
2164
2165
  * ---
2165
2166
  *
2166
2167
  * <Content />
@@ -2734,7 +2735,7 @@ export interface AstroAdapter {
2734
2735
  */
2735
2736
  supportedAstroFeatures: AstroFeatureMap;
2736
2737
  }
2737
- export type ValidRedirectStatus = 300 | 301 | 302 | 303 | 304 | 307 | 308;
2738
+ export type ValidRedirectStatus = (typeof REDIRECT_STATUS_CODES)[number];
2738
2739
  interface AstroSharedContext<Props extends Record<string, any> = Record<string, any>, RouteParams extends Record<string, string | undefined> = Record<string, string | undefined>> {
2739
2740
  /**
2740
2741
  * The address (usually IP address) of the user.
@@ -2757,11 +2758,11 @@ interface AstroSharedContext<Props extends Record<string, any> = Record<string,
2757
2758
  /**
2758
2759
  * Get action result on the server when using a form POST.
2759
2760
  */
2760
- getActionResult: <TAccept extends ActionAccept, TInputSchema extends ActionInputSchema<TAccept>, TAction extends ActionClient<unknown, TAccept, TInputSchema>>(action: TAction) => ActionReturnType<TAction> | undefined;
2761
+ getActionResult: <TAccept extends ActionAccept, TInputSchema extends z.ZodType, TAction extends ActionClient<unknown, TAccept, TInputSchema>>(action: TAction) => ActionReturnType<TAction> | undefined;
2761
2762
  /**
2762
2763
  * Call action handler from the server.
2763
2764
  */
2764
- callAction: <TAccept extends ActionAccept, TInputSchema extends ActionInputSchema<TAccept>, TOutput, TAction extends ActionClient<TOutput, TAccept, TInputSchema> | ActionClient<TOutput, TAccept, TInputSchema>['orThrow']>(action: TAction, input: Parameters<TAction>[0]) => Promise<ActionReturnType<TAction>>;
2765
+ callAction: <TAccept extends ActionAccept, TInputSchema extends z.ZodType, TOutput, TAction extends ActionClient<TOutput, TAccept, TInputSchema> | ActionClient<TOutput, TAccept, TInputSchema>['orThrow']>(action: TAction, input: Parameters<TAction>[0]) => Promise<ActionReturnType<TAction>>;
2765
2766
  /**
2766
2767
  * Route parameters for this request if this is a dynamic route.
2767
2768
  */
@@ -1,7 +1,7 @@
1
1
  import type { APIContext } from '../../@types/astro.js';
2
2
  export declare const formContentTypes: string[];
3
3
  export declare function hasContentType(contentType: string, expected: string[]): boolean;
4
- export type ActionAPIContext = Omit<APIContext, 'getActionResult' | 'callAction' | 'props'>;
4
+ export type ActionAPIContext = Omit<APIContext, 'getActionResult' | 'callAction' | 'props' | 'redirect'>;
5
5
  export type MaybePromise<T> = T | Promise<T>;
6
6
  /**
7
7
  * Used to preserve the input schema type in the error object.
@@ -4,16 +4,15 @@ import { type SafeResult } from './shared.js';
4
4
  export * from './shared.js';
5
5
  export { z } from 'zod';
6
6
  export type ActionAccept = 'form' | 'json';
7
- export type ActionInputSchema<T extends ActionAccept | undefined> = T extends 'form' ? z.AnyZodObject | z.ZodType<FormData> : z.ZodType;
8
7
  export type ActionHandler<TInputSchema, TOutput> = TInputSchema extends z.ZodType ? (input: z.infer<TInputSchema>, context: ActionAPIContext) => MaybePromise<TOutput> : (input: any, context: ActionAPIContext) => MaybePromise<TOutput>;
9
8
  export type ActionReturnType<T extends ActionHandler<any, any>> = Awaited<ReturnType<T>>;
10
- export type ActionClient<TOutput, TAccept extends ActionAccept | undefined, TInputSchema extends ActionInputSchema<TAccept> | undefined> = TInputSchema extends z.ZodType ? ((input: TAccept extends 'form' ? FormData : z.input<TInputSchema>) => Promise<SafeResult<z.input<TInputSchema> extends ErrorInferenceObject ? z.input<TInputSchema> : ErrorInferenceObject, Awaited<TOutput>>>) & {
9
+ export type ActionClient<TOutput, TAccept extends ActionAccept | undefined, TInputSchema extends z.ZodType | undefined> = TInputSchema extends z.ZodType ? ((input: TAccept extends 'form' ? FormData : z.input<TInputSchema>) => Promise<SafeResult<z.input<TInputSchema> extends ErrorInferenceObject ? z.input<TInputSchema> : ErrorInferenceObject, Awaited<TOutput>>>) & {
11
10
  queryString: string;
12
11
  orThrow: (input: TAccept extends 'form' ? FormData : z.input<TInputSchema>) => Promise<Awaited<TOutput>>;
13
12
  } : ((input?: any) => Promise<SafeResult<never, Awaited<TOutput>>>) & {
14
13
  orThrow: (input?: any) => Promise<Awaited<TOutput>>;
15
14
  };
16
- export declare function defineAction<TOutput, TAccept extends ActionAccept | undefined = undefined, TInputSchema extends ActionInputSchema<ActionAccept> | undefined = TAccept extends 'form' ? z.ZodType<FormData> : undefined>({ accept, input: inputSchema, handler, }: {
15
+ export declare function defineAction<TOutput, TAccept extends ActionAccept | undefined = undefined, TInputSchema extends z.ZodType | undefined = TAccept extends 'form' ? z.ZodType<FormData> : undefined>({ accept, input: inputSchema, handler, }: {
17
16
  input?: TInputSchema;
18
17
  accept?: TAccept;
19
18
  handler: ActionHandler<TInputSchema, TOutput>;
@@ -34,8 +34,11 @@ function getFormServerHandler(handler, inputSchema) {
34
34
  message: "This action only accepts FormData."
35
35
  });
36
36
  }
37
- if (!(inputSchema instanceof z.ZodObject)) return await handler(unparsedInput, context);
38
- const parsed = await inputSchema.safeParseAsync(formDataToObject(unparsedInput, inputSchema));
37
+ if (!inputSchema) return await handler(unparsedInput, context);
38
+ const baseSchema = unwrapSchemaEffects(inputSchema);
39
+ const parsed = await inputSchema.safeParseAsync(
40
+ baseSchema instanceof z.ZodObject ? formDataToObject(unparsedInput, baseSchema) : unparsedInput
41
+ );
39
42
  if (!parsed.success) {
40
43
  throw new ActionInputError(parsed.error.issues);
41
44
  }
@@ -59,7 +62,7 @@ function getJsonServerHandler(handler, inputSchema) {
59
62
  };
60
63
  }
61
64
  function formDataToObject(formData, schema) {
62
- const obj = {};
65
+ const obj = schema._def.unknownKeys === "passthrough" ? Object.fromEntries(formData.entries()) : {};
63
66
  for (const [key, baseValidator] of Object.entries(schema.shape)) {
64
67
  let validator = baseValidator;
65
68
  while (validator instanceof z.ZodOptional || validator instanceof z.ZodNullable || validator instanceof z.ZodDefault) {
@@ -98,6 +101,17 @@ function handleFormDataGet(key, formData, validator, baseValidator) {
98
101
  }
99
102
  return validator instanceof z.ZodNumber ? Number(value) : value;
100
103
  }
104
+ function unwrapSchemaEffects(schema) {
105
+ while (schema instanceof z.ZodEffects || schema instanceof z.ZodPipeline) {
106
+ if (schema instanceof z.ZodEffects) {
107
+ schema = schema._def.schema;
108
+ }
109
+ if (schema instanceof z.ZodPipeline) {
110
+ schema = schema._def.in;
111
+ }
112
+ }
113
+ return schema;
114
+ }
101
115
  export {
102
116
  defineAction,
103
117
  formDataToObject,
@@ -1,5 +1,6 @@
1
1
  import type { z } from 'zod';
2
- import type { ErrorInferenceObject, MaybePromise } from '../utils.js';
2
+ import type { ErrorInferenceObject, MaybePromise, ActionAPIContext as _ActionAPIContext } from '../utils.js';
3
+ export type ActionAPIContext = _ActionAPIContext;
3
4
  export declare const ACTION_QUERY_PARAMS: {
4
5
  actionName: string;
5
6
  actionPayload: string;
@@ -1,4 +1,7 @@
1
1
  import { parse as devalueParse, stringify as devalueStringify } from "devalue";
2
+ import { REDIRECT_STATUS_CODES } from "../../../core/constants.js";
3
+ import { ActionsReturnedInvalidDataError } from "../../../core/errors/errors-data.js";
4
+ import { AstroError } from "../../../core/errors/errors.js";
2
5
  import { ACTION_QUERY_PARAMS as _ACTION_QUERY_PARAMS } from "../../consts.js";
3
6
  const ACTION_QUERY_PARAMS = _ACTION_QUERY_PARAMS;
4
7
  const ACTION_ERROR_CODES = [
@@ -151,14 +154,28 @@ function serializeActionResult(res) {
151
154
  status: 204
152
155
  };
153
156
  }
157
+ let body;
158
+ try {
159
+ body = devalueStringify(res.data, {
160
+ // Add support for URL objects
161
+ URL: (value) => value instanceof URL && value.href
162
+ });
163
+ } catch (e) {
164
+ let hint = ActionsReturnedInvalidDataError.hint;
165
+ if (res.data instanceof Response) {
166
+ hint = REDIRECT_STATUS_CODES.includes(res.data.status) ? "If you need to redirect when the action succeeds, trigger a redirect where the action is called. See the Actions guide for server and client redirect examples: https://docs.astro.build/en/guides/actions." : "If you need to return a Response object, try using a server endpoint instead. See https://docs.astro.build/en/guides/endpoints/#server-endpoints-api-routes";
167
+ }
168
+ throw new AstroError({
169
+ ...ActionsReturnedInvalidDataError,
170
+ message: ActionsReturnedInvalidDataError.message(String(e)),
171
+ hint
172
+ });
173
+ }
154
174
  return {
155
175
  type: "data",
156
176
  status: 200,
157
177
  contentType: "application/json+devalue",
158
- body: devalueStringify(res.data, {
159
- // Add support for URL objects
160
- URL: (value) => value instanceof URL && value.href
161
- })
178
+ body
162
179
  };
163
180
  }
164
181
  function deserializeActionResult(res) {
@@ -1,6 +1,6 @@
1
1
  import type { APIContext } from '../@types/astro.js';
2
2
  import type { Locals } from './runtime/middleware.js';
3
- import { type ActionAPIContext } from './runtime/utils.js';
3
+ import type { ActionAPIContext } from './runtime/utils.js';
4
4
  export declare function hasActionPayload(locals: APIContext['locals']): locals is Locals;
5
5
  export declare function createGetActionResult(locals: APIContext['locals']): APIContext['getActionResult'];
6
6
  export declare function createCallAction(context: ActionAPIContext): APIContext['callAction'];
@@ -1,4 +1,3 @@
1
- import {} from "./runtime/utils.js";
2
1
  import { deserializeActionResult, getActionQueryString } from "./runtime/virtual/shared.js";
3
2
  function hasActionPayload(locals) {
4
3
  return "_actionPayload" in locals;
@@ -1,7 +1,7 @@
1
1
  import fsMod from 'node:fs';
2
2
  import matter from 'gray-matter';
3
3
  import type { PluginContext } from 'rollup';
4
- import { type ViteDevServer } from 'vite';
4
+ import type { ViteDevServer } from 'vite';
5
5
  import { z } from 'zod';
6
6
  import type { AstroConfig, AstroSettings, ContentEntryType, DataEntryType } from '../@types/astro.js';
7
7
  import type { Logger } from '../core/logger/core.js';
@@ -3,11 +3,11 @@ import path from "node:path";
3
3
  import { fileURLToPath, pathToFileURL } from "node:url";
4
4
  import { slug as githubSlug } from "github-slugger";
5
5
  import matter from "gray-matter";
6
- import { normalizePath } from "vite";
7
6
  import xxhash from "xxhash-wasm";
8
7
  import { z } from "zod";
9
8
  import { AstroError, AstroErrorData, MarkdownError, errorMap } from "../core/errors/index.js";
10
9
  import { isYAMLException } from "../core/errors/utils.js";
10
+ import { normalizePath } from "../core/viteUtils.js";
11
11
  import {
12
12
  CONTENT_FLAGS,
13
13
  CONTENT_LAYER_TYPE,
@@ -1,4 +1,4 @@
1
- import { type BuildInternals } from '../internal.js';
1
+ import type { BuildInternals } from '../internal.js';
2
2
  import type { AstroBuildPlugin } from '../plugin.js';
3
3
  import type { StaticBuildOptions } from '../types.js';
4
4
  export declare function copyContentToCache(opts: StaticBuildOptions): Promise<string[]>;
@@ -21,7 +21,6 @@ import {
21
21
  import { isContentCollectionsCacheEnabled } from "../../util.js";
22
22
  import { addRollupInput } from "../add-rollup-input.js";
23
23
  import { CHUNKS_PATH, CONTENT_PATH } from "../consts.js";
24
- import {} from "../internal.js";
25
24
  import { copyFiles } from "../static-build.js";
26
25
  import { encodeName } from "../util.js";
27
26
  import { extendManualChunks } from "./util.js";
@@ -1,4 +1,4 @@
1
- import { type BuildInternals } from '../internal.js';
1
+ import type { BuildInternals } from '../internal.js';
2
2
  import type { AstroBuildPlugin } from '../plugin.js';
3
3
  import type { StaticBuildOptions } from '../types.js';
4
4
  export declare const ASTRO_PAGE_MODULE_ID = "@astro-page:";
@@ -1,6 +1,5 @@
1
1
  import { routeIsRedirect } from "../../redirects/index.js";
2
2
  import { addRollupInput } from "../add-rollup-input.js";
3
- import {} from "../internal.js";
4
3
  import { RENDERERS_MODULE_ID } from "./plugin-renderers.js";
5
4
  import { getPagesFromVirtualModulePageName, getVirtualModulePageName } from "./util.js";
6
5
  const ASTRO_PAGE_MODULE_ID = "@astro-page:";
@@ -172,10 +172,10 @@ export declare const AstroConfigSchema: z.ZodObject<{
172
172
  status: z.ZodUnion<[z.ZodLiteral<300>, z.ZodLiteral<301>, z.ZodLiteral<302>, z.ZodLiteral<303>, z.ZodLiteral<304>, z.ZodLiteral<307>, z.ZodLiteral<308>]>;
173
173
  destination: z.ZodString;
174
174
  }, "strip", z.ZodTypeAny, {
175
- status: 300 | 301 | 302 | 303 | 304 | 307 | 308;
175
+ status: 301 | 302 | 303 | 307 | 308 | 300 | 304;
176
176
  destination: string;
177
177
  }, {
178
- status: 300 | 301 | 302 | 303 | 304 | 307 | 308;
178
+ status: 301 | 302 | 303 | 307 | 308 | 300 | 304;
179
179
  destination: string;
180
180
  }>]>>>;
181
181
  prefetch: z.ZodOptional<z.ZodUnion<[z.ZodBoolean, z.ZodObject<{
@@ -743,7 +743,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
743
743
  headers?: OutgoingHttpHeaders | undefined;
744
744
  };
745
745
  redirects: Record<string, string | {
746
- status: 300 | 301 | 302 | 303 | 304 | 307 | 308;
746
+ status: 301 | 302 | 303 | 307 | 308 | 300 | 304;
747
747
  destination: string;
748
748
  }>;
749
749
  root: URL;
@@ -892,7 +892,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
892
892
  } | undefined;
893
893
  server?: unknown;
894
894
  redirects?: Record<string, string | {
895
- status: 300 | 301 | 302 | 303 | 304 | 307 | 308;
895
+ status: 301 | 302 | 303 | 307 | 308 | 300 | 304;
896
896
  destination: string;
897
897
  }> | undefined;
898
898
  root?: string | undefined;
@@ -1125,10 +1125,10 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
1125
1125
  status: z.ZodUnion<[z.ZodLiteral<300>, z.ZodLiteral<301>, z.ZodLiteral<302>, z.ZodLiteral<303>, z.ZodLiteral<304>, z.ZodLiteral<307>, z.ZodLiteral<308>]>;
1126
1126
  destination: z.ZodString;
1127
1127
  }, "strip", z.ZodTypeAny, {
1128
- status: 300 | 301 | 302 | 303 | 304 | 307 | 308;
1128
+ status: 301 | 302 | 303 | 307 | 308 | 300 | 304;
1129
1129
  destination: string;
1130
1130
  }, {
1131
- status: 300 | 301 | 302 | 303 | 304 | 307 | 308;
1131
+ status: 301 | 302 | 303 | 307 | 308 | 300 | 304;
1132
1132
  destination: string;
1133
1133
  }>]>>>;
1134
1134
  prefetch: z.ZodOptional<z.ZodUnion<[z.ZodBoolean, z.ZodObject<{
@@ -1771,7 +1771,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
1771
1771
  headers?: OutgoingHttpHeaders | undefined;
1772
1772
  };
1773
1773
  redirects: Record<string, string | {
1774
- status: 300 | 301 | 302 | 303 | 304 | 307 | 308;
1774
+ status: 301 | 302 | 303 | 307 | 308 | 300 | 304;
1775
1775
  destination: string;
1776
1776
  }>;
1777
1777
  root: import("url").URL;
@@ -1920,7 +1920,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
1920
1920
  } | undefined;
1921
1921
  server?: unknown;
1922
1922
  redirects?: Record<string, string | {
1923
- status: 300 | 301 | 302 | 303 | 304 | 307 | 308;
1923
+ status: 301 | 302 | 303 | 307 | 308 | 300 | 304;
1924
1924
  destination: string;
1925
1925
  }> | undefined;
1926
1926
  root?: string | undefined;
@@ -2066,7 +2066,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
2066
2066
  headers?: OutgoingHttpHeaders | undefined;
2067
2067
  };
2068
2068
  redirects: Record<string, string | {
2069
- status: 300 | 301 | 302 | 303 | 304 | 307 | 308;
2069
+ status: 301 | 302 | 303 | 307 | 308 | 300 | 304;
2070
2070
  destination: string;
2071
2071
  }>;
2072
2072
  root: import("url").URL;
@@ -2215,7 +2215,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
2215
2215
  } | undefined;
2216
2216
  server?: unknown;
2217
2217
  redirects?: Record<string, string | {
2218
- status: 300 | 301 | 302 | 303 | 304 | 307 | 308;
2218
+ status: 301 | 302 | 303 | 307 | 308 | 300 | 304;
2219
2219
  destination: string;
2220
2220
  }> | undefined;
2221
2221
  root?: string | undefined;
@@ -2361,7 +2361,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
2361
2361
  headers?: OutgoingHttpHeaders | undefined;
2362
2362
  };
2363
2363
  redirects: Record<string, string | {
2364
- status: 300 | 301 | 302 | 303 | 304 | 307 | 308;
2364
+ status: 301 | 302 | 303 | 307 | 308 | 300 | 304;
2365
2365
  destination: string;
2366
2366
  }>;
2367
2367
  root: import("url").URL;
@@ -2510,7 +2510,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
2510
2510
  } | undefined;
2511
2511
  server?: unknown;
2512
2512
  redirects?: Record<string, string | {
2513
- status: 300 | 301 | 302 | 303 | 304 | 307 | 308;
2513
+ status: 301 | 302 | 303 | 307 | 308 | 300 | 304;
2514
2514
  destination: string;
2515
2515
  }> | undefined;
2516
2516
  root?: string | undefined;
@@ -2656,7 +2656,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
2656
2656
  headers?: OutgoingHttpHeaders | undefined;
2657
2657
  };
2658
2658
  redirects: Record<string, string | {
2659
- status: 300 | 301 | 302 | 303 | 304 | 307 | 308;
2659
+ status: 301 | 302 | 303 | 307 | 308 | 300 | 304;
2660
2660
  destination: string;
2661
2661
  }>;
2662
2662
  root: import("url").URL;
@@ -2805,7 +2805,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
2805
2805
  } | undefined;
2806
2806
  server?: unknown;
2807
2807
  redirects?: Record<string, string | {
2808
- status: 300 | 301 | 302 | 303 | 304 | 307 | 308;
2808
+ status: 301 | 302 | 303 | 307 | 308 | 300 | 304;
2809
2809
  destination: string;
2810
2810
  }> | undefined;
2811
2811
  root?: string | undefined;
@@ -38,6 +38,10 @@ export declare const DEFAULT_404_COMPONENT = "astro-default-404.astro";
38
38
  * The value of the `component` field of the default 500 page, which is used when there is no user-provided 404.astro page.
39
39
  */
40
40
  export declare const DEFAULT_500_COMPONENT = "astro-default-500.astro";
41
+ /**
42
+ * A response with one of these status codes will create a redirect response.
43
+ */
44
+ export declare const REDIRECT_STATUS_CODES: readonly [301, 302, 303, 307, 308, 300, 304];
41
45
  /**
42
46
  * A response with one of these status codes will be rewritten
43
47
  * with the result of rendering the respective error page.
@@ -1,10 +1,11 @@
1
- const ASTRO_VERSION = "4.14.4";
1
+ const ASTRO_VERSION = "4.14.6";
2
2
  const REROUTE_DIRECTIVE_HEADER = "X-Astro-Reroute";
3
3
  const REWRITE_DIRECTIVE_HEADER_KEY = "X-Astro-Rewrite";
4
4
  const REWRITE_DIRECTIVE_HEADER_VALUE = "yes";
5
5
  const ROUTE_TYPE_HEADER = "X-Astro-Route-Type";
6
6
  const DEFAULT_404_COMPONENT = "astro-default-404.astro";
7
7
  const DEFAULT_500_COMPONENT = "astro-default-500.astro";
8
+ const REDIRECT_STATUS_CODES = [301, 302, 303, 307, 308, 300, 304];
8
9
  const REROUTABLE_STATUS_CODES = [404, 500];
9
10
  const clientAddressSymbol = Symbol.for("astro.clientAddress");
10
11
  const clientLocalsSymbol = Symbol.for("astro.locals");
@@ -23,6 +24,7 @@ export {
23
24
  DEFAULT_404_COMPONENT,
24
25
  DEFAULT_500_COMPONENT,
25
26
  MIDDLEWARE_PATH_SEGMENT_NAME,
27
+ REDIRECT_STATUS_CODES,
26
28
  REROUTABLE_STATUS_CODES,
27
29
  REROUTE_DIRECTIVE_HEADER,
28
30
  REWRITE_DIRECTIVE_HEADER_KEY,
@@ -121,7 +121,7 @@ async function createVite(commandConfig, { settings, logger, mode, command, fs =
121
121
  astroPrefetch({ settings }),
122
122
  astroTransitions({ settings }),
123
123
  astroDevToolbar({ settings, logger }),
124
- vitePluginFileURL({}),
124
+ vitePluginFileURL(),
125
125
  astroInternationalization({ settings }),
126
126
  settings.config.experimental.serverIslands && vitePluginServerIslands({ settings }),
127
127
  astroContainer()
@@ -23,7 +23,7 @@ async function dev(inlineConfig) {
23
23
  await telemetry.record([]);
24
24
  const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
25
25
  const logger = restart.container.logger;
26
- const currentVersion = "4.14.4";
26
+ const currentVersion = "4.14.6";
27
27
  const isPrerelease = currentVersion.includes("-");
28
28
  if (!isPrerelease) {
29
29
  try {
@@ -1493,6 +1493,19 @@ export declare const ActionsUsedWithForGetError: {
1493
1493
  message: (actionName: string) => string;
1494
1494
  hint: string;
1495
1495
  };
1496
+ /**
1497
+ * @docs
1498
+ * @see
1499
+ * - [Actions RFC](https://github.com/withastro/roadmap/blob/actions/proposals/0046-actions.md)
1500
+ * @description
1501
+ * Action handler returned invalid data. Handlers should return serializable data types, and cannot return a Response object.
1502
+ */
1503
+ export declare const ActionsReturnedInvalidDataError: {
1504
+ name: string;
1505
+ title: string;
1506
+ message: (error: string) => string;
1507
+ hint: string;
1508
+ };
1496
1509
  /**
1497
1510
  * @docs
1498
1511
  * @see
@@ -168,7 +168,7 @@ const InvalidImageService = {
168
168
  const MissingImageDimension = {
169
169
  name: "MissingImageDimension",
170
170
  title: "Missing image dimensions",
171
- message: (missingDimension, imageURL) => `Missing ${missingDimension === "both" ? "width and height attributes" : `${missingDimension} attribute`} for ${imageURL}. When using remote images, both dimensions are required unless in order to avoid CLS.`,
171
+ message: (missingDimension, imageURL) => `Missing ${missingDimension === "both" ? "width and height attributes" : `${missingDimension} attribute`} for ${imageURL}. When using remote images, both dimensions are required in order to avoid CLS.`,
172
172
  hint: "If your image is inside your `src` folder, you probably meant to import it instead. See [the Imports guide for more information](https://docs.astro.build/en/guides/imports/#other-assets). You can also use `inferSize={true}` for remote images to get the original dimensions."
173
173
  };
174
174
  const FailedToFetchRemoteImageDimensions = {
@@ -571,6 +571,12 @@ const ActionsUsedWithForGetError = {
571
571
  message: (actionName) => `Action ${actionName} was called from a form using a GET request, but only POST requests are supported. This often occurs if \`method="POST"\` is missing on the form.`,
572
572
  hint: "Actions are experimental. Visit the RFC for usage instructions: https://github.com/withastro/roadmap/blob/actions/proposals/0046-actions.md"
573
573
  };
574
+ const ActionsReturnedInvalidDataError = {
575
+ name: "ActionsReturnedInvalidDataError",
576
+ title: "Action handler returned invalid data.",
577
+ message: (error) => `Action handler returned invalid data. Handlers should return serializable data types like objects, arrays, strings, and numbers. Parse error: ${error}`,
578
+ hint: "See the devalue library for all supported types: https://github.com/rich-harris/devalue"
579
+ };
574
580
  const ActionQueryStringInvalidError = {
575
581
  name: "ActionQueryStringInvalidError",
576
582
  title: "An invalid Action query string was passed by a form.",
@@ -587,6 +593,7 @@ const UnknownError = { name: "UnknownError", title: "Unknown Error." };
587
593
  export {
588
594
  ActionCalledFromServerError,
589
595
  ActionQueryStringInvalidError,
596
+ ActionsReturnedInvalidDataError,
590
597
  ActionsUsedWithForGetError,
591
598
  ActionsWithoutServerOutputError,
592
599
  AstroGlobNoMatch,
@@ -38,7 +38,7 @@ function serverStart({
38
38
  host,
39
39
  base
40
40
  }) {
41
- const version = "4.14.4";
41
+ const version = "4.14.6";
42
42
  const localPrefix = `${dim("\u2503")} Local `;
43
43
  const networkPrefix = `${dim("\u2503")} Network `;
44
44
  const emptyPrefix = " ".repeat(11);
@@ -270,7 +270,7 @@ function printHelp({
270
270
  message.push(
271
271
  linebreak(),
272
272
  ` ${bgGreen(black(` ${commandName} `))} ${green(
273
- `v${"4.14.4"}`
273
+ `v${"4.14.6"}`
274
274
  )} ${headline}`
275
275
  );
276
276
  }
@@ -169,8 +169,10 @@ class RenderContext {
169
169
  }
170
170
  createAPIContext(props, isPrerendered) {
171
171
  const context = this.createActionAPIContext();
172
+ const redirect = (path, status = 302) => new Response(null, { status, headers: { Location: path } });
172
173
  return Object.assign(context, {
173
174
  props,
175
+ redirect,
174
176
  getActionResult: createGetActionResult(context.locals),
175
177
  callAction: createCallAction(context),
176
178
  // Used internally by Actions middleware.
@@ -205,7 +207,6 @@ class RenderContext {
205
207
  const renderContext = this;
206
208
  const { cookies, params, pipeline, url } = this;
207
209
  const generator = `Astro v${ASTRO_VERSION}`;
208
- const redirect = (path, status = 302) => new Response(null, { status, headers: { Location: path } });
209
210
  const rewrite = async (reroutePayload) => {
210
211
  return await this.#executeRewrite(reroutePayload);
211
212
  };
@@ -237,7 +238,6 @@ class RenderContext {
237
238
  get preferredLocaleList() {
238
239
  return renderContext.computePreferredLocaleList();
239
240
  },
240
- redirect,
241
241
  rewrite,
242
242
  request: this.request,
243
243
  site: pipeline.site,
@@ -1,4 +1,8 @@
1
1
  import type { ModuleLoader } from './module-loader/index.js';
2
+ /**
3
+ * Re-implementation of Vite's normalizePath that can be used without Vite
4
+ */
5
+ export declare function normalizePath(id: string): string;
2
6
  /**
3
7
  * Resolve the hydration paths so that it can be imported in the client
4
8
  */
@@ -1,8 +1,11 @@
1
1
  import path from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
- import { normalizePath } from "vite";
4
- import { prependForwardSlash } from "../core/path.js";
3
+ import { prependForwardSlash, slash } from "../core/path.js";
5
4
  import { VALID_ID_PREFIX, resolveJsToTs, unwrapId, viteID } from "./util.js";
5
+ const isWindows = typeof process !== "undefined" && process.platform === "win32";
6
+ function normalizePath(id) {
7
+ return path.posix.normalize(isWindows ? slash(id) : id);
8
+ }
6
9
  function resolvePath(specifier, importer) {
7
10
  if (specifier.startsWith(".")) {
8
11
  const absoluteSpecifier = path.resolve(path.dirname(importer), specifier);
@@ -43,6 +46,7 @@ async function resolveIdToUrl(loader, id, root) {
43
46
  return VALID_ID_PREFIX + resultId;
44
47
  }
45
48
  export {
49
+ normalizePath,
46
50
  resolveIdToUrl,
47
51
  resolvePath,
48
52
  rootRelativePath
@@ -119,6 +119,7 @@ function initLoadStrategy() {
119
119
  });
120
120
  }
121
121
  function prefetch(url, opts) {
122
+ url = url.replace(/#.*/, "");
122
123
  const ignoreSlowConnection = opts?.ignoreSlowConnection ?? false;
123
124
  if (!canPrefetchUrl(url, ignoreSlowConnection)) return;
124
125
  prefetchedUrls.add(url);
@@ -1,7 +1,7 @@
1
1
  import type { ResolvedDevToolbarApp as DevToolbarAppDefinition } from '../../../@types/astro.js';
2
2
  import { type ToolbarAppEventTarget } from './helpers.js';
3
3
  import { type Icon } from './ui-library/icons.js';
4
- import { type Placement } from './ui-library/window.js';
4
+ import type { Placement } from './ui-library/window.js';
5
5
  export type DevToolbarApp = DevToolbarAppDefinition & {
6
6
  builtIn: boolean;
7
7
  active: boolean;
@@ -1,7 +1,6 @@
1
1
  import { serverHelpers } from "./helpers.js";
2
2
  import { settings } from "./settings.js";
3
3
  import { getIconElement, isDefinedIcon } from "./ui-library/icons.js";
4
- import {} from "./ui-library/window.js";
5
4
  const WS_EVENT_NAME = "astro-dev-toolbar";
6
5
  const WS_EVENT_NAME_DEPRECATED = "astro-dev-overlay";
7
6
  const HOVER_DELAY = 2 * 1e3;
@@ -1,5 +1,5 @@
1
1
  import type { AstroSettings, ComponentInstance, ManifestData, RewritePayload, RouteData, SSRLoadedRenderer, SSRManifest } from '../@types/astro.js';
2
- import { type HeadElements } from '../core/base-pipeline.js';
2
+ import type { HeadElements } from '../core/base-pipeline.js';
3
3
  import type { Logger } from '../core/logger/core.js';
4
4
  import type { ModuleLoader } from '../core/module-loader/index.js';
5
5
  import { Pipeline } from '../core/render/index.js';
@@ -1,6 +1,5 @@
1
1
  import { fileURLToPath } from "node:url";
2
2
  import { getInfoOutput } from "../cli/info/index.js";
3
- import {} from "../core/base-pipeline.js";
4
3
  import { ASTRO_VERSION } from "../core/constants.js";
5
4
  import { enhanceViteSSRError } from "../core/errors/dev/index.js";
6
5
  import { AggregateError, CSSError, MarkdownError } from "../core/errors/index.js";
@@ -1,2 +1,2 @@
1
1
  import type { Plugin as VitePlugin } from 'vite';
2
- export default function vitePluginFileURL({}: {}): VitePlugin;
2
+ export default function vitePluginFileURL(): VitePlugin;
@@ -1,6 +1,7 @@
1
- function vitePluginFileURL({}) {
1
+ function vitePluginFileURL() {
2
2
  return {
3
3
  name: "astro:vite-plugin-file-url",
4
+ enforce: "pre",
4
5
  resolveId(source, importer) {
5
6
  if (source.startsWith("file://")) {
6
7
  const rest = source.slice(7);
@@ -1,6 +1,6 @@
1
1
  import type { Plugin as VitePlugin } from 'vite';
2
2
  import type { AstroSettings } from '../@types/astro.js';
3
- import { type Logger } from '../core/logger/core.js';
3
+ import type { Logger } from '../core/logger/core.js';
4
4
  export interface AstroPluginScannerOptions {
5
5
  settings: AstroSettings;
6
6
  logger: Logger;
@@ -1,7 +1,6 @@
1
1
  import { extname } from "node:path";
2
2
  import { bold } from "kleur/colors";
3
3
  import { normalizePath } from "vite";
4
- import {} from "../core/logger/core.js";
5
4
  import { isEndpoint, isPage, isServerLikeOutput } from "../core/util.js";
6
5
  import { rootRelativePath } from "../core/viteUtils.js";
7
6
  import { runHookRouteSetup } from "../integrations/hooks.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "4.14.4",
3
+ "version": "4.14.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",
@@ -110,11 +110,11 @@
110
110
  "dependencies": {
111
111
  "@astrojs/compiler": "^2.10.3",
112
112
  "@babel/core": "^7.25.2",
113
- "@babel/generator": "^7.25.0",
114
- "@babel/parser": "^7.25.3",
113
+ "@babel/generator": "^7.25.5",
114
+ "@babel/parser": "^7.25.4",
115
115
  "@babel/plugin-transform-react-jsx": "^7.25.2",
116
- "@babel/traverse": "^7.25.3",
117
- "@babel/types": "^7.25.2",
116
+ "@babel/traverse": "^7.25.4",
117
+ "@babel/types": "^7.25.4",
118
118
  "@oslojs/encoding": "^0.4.1",
119
119
  "@rollup/pluginutils": "^5.1.0",
120
120
  "@types/babel__core": "^7.20.5",
@@ -147,10 +147,10 @@
147
147
  "js-yaml": "^4.1.0",
148
148
  "kleur": "^4.1.5",
149
149
  "magic-string": "^0.30.11",
150
- "micromatch": "^4.0.7",
150
+ "micromatch": "^4.0.8",
151
151
  "mrmime": "^2.0.0",
152
152
  "neotraverse": "^0.6.18",
153
- "ora": "^8.0.1",
153
+ "ora": "^8.1.0",
154
154
  "p-limit": "^6.1.0",
155
155
  "p-queue": "^8.0.1",
156
156
  "path-to-regexp": "^6.2.2",
@@ -163,8 +163,8 @@
163
163
  "strip-ansi": "^7.1.0",
164
164
  "tsconfck": "^3.1.1",
165
165
  "unist-util-visit": "^5.0.0",
166
- "vfile": "^6.0.2",
167
- "vite": "^5.4.1",
166
+ "vfile": "^6.0.3",
167
+ "vite": "^5.4.2",
168
168
  "vitefu": "^0.2.5",
169
169
  "which-pm": "^3.0.0",
170
170
  "xxhash-wasm": "^1.0.2",
@@ -172,8 +172,8 @@
172
172
  "zod": "^3.23.8",
173
173
  "zod-to-json-schema": "^3.23.2",
174
174
  "zod-to-ts": "^1.2.0",
175
- "@astrojs/markdown-remark": "5.2.0",
176
175
  "@astrojs/internal-helpers": "0.4.1",
176
+ "@astrojs/markdown-remark": "5.2.0",
177
177
  "@astrojs/telemetry": "3.1.0"
178
178
  },
179
179
  "optionalDependencies": {
@@ -201,9 +201,9 @@
201
201
  "@types/yargs-parser": "^21.0.3",
202
202
  "cheerio": "1.0.0",
203
203
  "eol": "^0.9.1",
204
- "expect-type": "^0.19.0",
204
+ "expect-type": "^0.20.0",
205
205
  "mdast-util-mdx": "^3.0.0",
206
- "mdast-util-mdx-jsx": "^3.1.2",
206
+ "mdast-util-mdx-jsx": "^3.1.3",
207
207
  "memfs": "^4.11.1",
208
208
  "node-mocks-http": "^1.15.1",
209
209
  "parse-srcset": "^1.0.2",
@@ -211,9 +211,9 @@
211
211
  "rehype-slug": "^6.0.0",
212
212
  "rehype-toc": "^3.0.2",
213
213
  "remark-code-titles": "^0.1.2",
214
- "rollup": "^4.21.0",
214
+ "rollup": "^4.21.1",
215
215
  "sass": "^1.77.8",
216
- "undici": "^6.19.7",
216
+ "undici": "^6.19.8",
217
217
  "unified": "^11.0.5",
218
218
  "astro-scripts": "0.0.14"
219
219
  },
@@ -93,7 +93,9 @@ async function handleAction(param, path, context) {
93
93
  body,
94
94
  headers,
95
95
  });
96
- if (rawResult.status === 204) return;
96
+ if (rawResult.status === 204) {
97
+ return deserializeActionResult({ type: 'empty', status: 204 });
98
+ }
97
99
 
98
100
  return deserializeActionResult({
99
101
  type: rawResult.ok ? 'data' : 'error',