astro 4.12.2 → 4.13.0

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 (50) hide show
  1. package/dist/@types/astro.d.ts +6 -106
  2. package/dist/actions/consts.d.ts +3 -0
  3. package/dist/actions/consts.js +6 -0
  4. package/dist/actions/index.d.ts +12 -2
  5. package/dist/actions/index.js +43 -7
  6. package/dist/actions/runtime/middleware.js +80 -23
  7. package/dist/actions/runtime/route.js +2 -3
  8. package/dist/actions/runtime/utils.d.ts +4 -2
  9. package/dist/actions/runtime/utils.js +1 -1
  10. package/dist/actions/runtime/virtual/server.d.ts +6 -5
  11. package/dist/actions/runtime/virtual/server.js +6 -5
  12. package/dist/actions/runtime/virtual/shared.d.ts +7 -0
  13. package/dist/actions/runtime/virtual/shared.js +11 -1
  14. package/dist/cli/add/index.js +1 -1
  15. package/dist/container/index.js +0 -1
  16. package/dist/content/runtime-assets.d.ts +1 -1
  17. package/dist/content/types-generator.js +5 -3
  18. package/dist/content/vite-plugin-content-assets.js +0 -14
  19. package/dist/core/app/types.d.ts +0 -1
  20. package/dist/core/build/generate.js +10 -4
  21. package/dist/core/build/pipeline.js +0 -1
  22. package/dist/core/build/plugins/plugin-content.js +1 -1
  23. package/dist/core/build/plugins/plugin-manifest.js +0 -1
  24. package/dist/core/config/schema.d.ts +0 -34
  25. package/dist/core/config/schema.js +0 -4
  26. package/dist/core/constants.js +1 -1
  27. package/dist/core/dev/dev.js +1 -1
  28. package/dist/core/errors/dev/utils.js +12 -3
  29. package/dist/core/errors/dev/vite.d.ts +13 -0
  30. package/dist/core/errors/dev/vite.js +18 -4
  31. package/dist/core/errors/errors-data.d.ts +28 -1
  32. package/dist/core/errors/errors-data.js +14 -0
  33. package/dist/core/messages.js +2 -2
  34. package/dist/core/middleware/callMiddleware.d.ts +1 -2
  35. package/dist/core/middleware/callMiddleware.js +2 -12
  36. package/dist/core/render-context.js +13 -37
  37. package/dist/env/runtime.d.ts +2 -2
  38. package/dist/env/runtime.js +1 -1
  39. package/dist/integrations/hooks.js +1 -1
  40. package/dist/runtime/client/dev-toolbar/apps/audit/rules/a11y.js +0 -14
  41. package/dist/runtime/server/render/astro/instance.d.ts +2 -2
  42. package/dist/runtime/server/render/server-islands.js +2 -1
  43. package/dist/transitions/router.js +0 -8
  44. package/dist/vite-plugin-astro-server/error.js +1 -2
  45. package/dist/vite-plugin-astro-server/plugin.js +0 -1
  46. package/dist/vite-plugin-astro-server/route.js +0 -1
  47. package/dist/vite-plugin-astro-server/vite.js +4 -0
  48. package/package.json +22 -22
  49. package/templates/actions.mjs +29 -32
  50. package/templates/env/module.mjs +2 -0
@@ -182,7 +182,7 @@ export interface AstroGlobal<Props extends Record<string, any> = Record<string,
182
182
  * ```
183
183
  */
184
184
  getActionResult: AstroSharedContext['getActionResult'];
185
- /** Redirect to another page (**SSR Only**)
185
+ /** Redirect to another page
186
186
  *
187
187
  * Example usage:
188
188
  * ```typescript
@@ -191,7 +191,7 @@ export interface AstroGlobal<Props extends Record<string, any> = Record<string,
191
191
  * }
192
192
  * ```
193
193
  *
194
- * [Astro reference](https://docs.astro.build/en/guides/server-side-rendering/)
194
+ * [Astro reference](https://docs.astro.build/en/reference/api-reference/#astroredirect)
195
195
  */
196
196
  redirect: AstroSharedContext['redirect'];
197
197
  /**
@@ -1755,53 +1755,6 @@ export interface AstroUserConfig {
1755
1755
  * ```
1756
1756
  */
1757
1757
  contentCollectionCache?: boolean;
1758
- /**
1759
- * @docs
1760
- * @name experimental.contentCollectionJsonSchema
1761
- * @type {boolean}
1762
- * @default `false`
1763
- * @version 4.5.0
1764
- * @description
1765
- * This feature will auto-generate a JSON schema for content collections of `type: 'data'` which can be used as the `$schema` value for TypeScript-style autocompletion/hints in tools like VSCode.
1766
- *
1767
- * To enable this feature, add the experimental flag:
1768
- *
1769
- * ```diff
1770
- * import { defineConfig } from 'astro/config';
1771
-
1772
- * export default defineConfig({
1773
- * experimental: {
1774
- * + contentCollectionJsonSchema: true
1775
- * }
1776
- * });
1777
- * ```
1778
- *
1779
- * This experimental implementation requires you to manually reference the schema in each data entry file of the collection:
1780
- *
1781
- * ```diff
1782
- * // src/content/test/entry.json
1783
- * {
1784
- * + "$schema": "../../../.astro/collections/test.schema.json",
1785
- * "test": "test"
1786
- * }
1787
- * ```
1788
- *
1789
- * Alternatively, you can set this in your [VSCode `json.schemas` settings](https://code.visualstudio.com/docs/languages/json#_json-schemas-and-settings):
1790
- *
1791
- * ```diff
1792
- * "json.schemas": [
1793
- * {
1794
- * "fileMatch": [
1795
- * "/src/content/test/**"
1796
- * ],
1797
- * "url": "./.astro/collections/test.schema.json"
1798
- * }
1799
- * ]
1800
- * ```
1801
- *
1802
- * Note that this initial implementation uses a library with [known issues for advanced Zod schemas](https://github.com/StefanTerdell/zod-to-json-schema#known-issues), so you may wish to consult these limitations before enabling the experimental flag.
1803
- */
1804
- contentCollectionJsonSchema?: boolean;
1805
1758
  /**
1806
1759
  * @docs
1807
1760
  * @name experimental.clientPrerender
@@ -1866,61 +1819,6 @@ export interface AstroUserConfig {
1866
1819
  * In the event of route collisions, where two routes of equal route priority attempt to build the same URL, Astro will log a warning identifying the conflicting routes.
1867
1820
  */
1868
1821
  globalRoutePriority?: boolean;
1869
- /**
1870
- * @docs
1871
- * @name experimental.rewriting
1872
- * @type {boolean}
1873
- * @default `false`
1874
- * @version 4.8.0
1875
- * @description
1876
- *
1877
- * Enables a routing feature for rewriting requests in Astro pages, endpoints and Astro middleware, giving you programmatic control over your routes.
1878
- *
1879
- * ```js
1880
- * {
1881
- * experimental: {
1882
- * rewriting: true,
1883
- * },
1884
- * }
1885
- * ```
1886
- *
1887
- * Use `Astro.rewrite` in your `.astro` files to reroute to a different page:
1888
- *
1889
- * ```astro "rewrite"
1890
- * ---
1891
- * // src/pages/dashboard.astro
1892
- * if (!Astro.props.allowed) {
1893
- * return Astro.rewrite("/")
1894
- * }
1895
- * ---
1896
- * ```
1897
- *
1898
- * Use `context.rewrite` in your endpoint files to reroute to a different page:
1899
- *
1900
- * ```js
1901
- * // src/pages/api.js
1902
- * export function GET(ctx) {
1903
- * if (!ctx.locals.allowed) {
1904
- * return ctx.rewrite("/")
1905
- * }
1906
- * }
1907
- * ```
1908
- *
1909
- * Use `next("/")` in your middleware file to reroute to a different page, and then call the next middleware function:
1910
- *
1911
- * ```js
1912
- * // src/middleware.js
1913
- * export function onRequest(ctx, next) {
1914
- * if (!ctx.cookies.get("allowed")) {
1915
- * return next("/") // new signature
1916
- * }
1917
- * return next();
1918
- * }
1919
- * ```
1920
- *
1921
- * For a complete overview, and to give feedback on this experimental API, see the [Rerouting RFC](https://github.com/withastro/roadmap/blob/feat/reroute/proposals/0047-rerouting.md).
1922
- */
1923
- rewriting?: boolean;
1924
1822
  /**
1925
1823
  * @docs
1926
1824
  * @name experimental.env
@@ -2482,7 +2380,7 @@ export interface Page<T = any> {
2482
2380
  total: number;
2483
2381
  /** the current page number, starting from 1 */
2484
2382
  currentPage: number;
2485
- /** number of items per page (default: 25) */
2383
+ /** number of items per page (default: 10) */
2486
2384
  size: number;
2487
2385
  /** number of last page */
2488
2386
  lastPage: number;
@@ -2593,7 +2491,7 @@ interface AstroSharedContext<Props extends Record<string, any> = Record<string,
2593
2491
  /**
2594
2492
  * Get action result on the server when using a form POST.
2595
2493
  */
2596
- getActionResult: <TAccept extends ActionAccept, TInputSchema extends ActionInputSchema<TAccept>, TAction extends ActionClient<unknown, TAccept, TInputSchema>>(action: TAction) => Awaited<ReturnType<TAction['safe']>> | undefined;
2494
+ getActionResult: <TAccept extends ActionAccept, TInputSchema extends ActionInputSchema<TAccept>, TAction extends ActionClient<unknown, TAccept, TInputSchema>>(action: TAction) => Awaited<ReturnType<TAction>> | undefined;
2597
2495
  /**
2598
2496
  * Route parameters for this request if this is a dynamic route.
2599
2497
  */
@@ -3013,6 +2911,7 @@ export interface SSRResult {
3013
2911
  * Whether the page has failed with a non-recoverable error, or the client disconnected.
3014
2912
  */
3015
2913
  cancelled: boolean;
2914
+ base: string;
3016
2915
  styles: Set<SSRElement>;
3017
2916
  scripts: Set<SSRElement>;
3018
2917
  links: Set<SSRElement>;
@@ -3037,6 +2936,7 @@ export interface SSRResult {
3037
2936
  pathname: string;
3038
2937
  cookies: AstroCookies | undefined;
3039
2938
  serverIslandNameMap: Map<string, string>;
2939
+ trailingSlash: AstroConfig['trailingSlash'];
3040
2940
  _metadata: SSRMetadata;
3041
2941
  }
3042
2942
  /**
@@ -1,3 +1,6 @@
1
1
  export declare const VIRTUAL_MODULE_ID = "astro:actions";
2
2
  export declare const RESOLVED_VIRTUAL_MODULE_ID: string;
3
3
  export declare const ACTIONS_TYPES_FILE = "actions.d.ts";
4
+ export declare const VIRTUAL_INTERNAL_MODULE_ID = "astro:internal-actions";
5
+ export declare const RESOLVED_VIRTUAL_INTERNAL_MODULE_ID = "\0astro:internal-actions";
6
+ export declare const NOOP_ACTIONS = "\0noop-actions";
@@ -1,8 +1,14 @@
1
1
  const VIRTUAL_MODULE_ID = "astro:actions";
2
2
  const RESOLVED_VIRTUAL_MODULE_ID = "\0" + VIRTUAL_MODULE_ID;
3
3
  const ACTIONS_TYPES_FILE = "actions.d.ts";
4
+ const VIRTUAL_INTERNAL_MODULE_ID = "astro:internal-actions";
5
+ const RESOLVED_VIRTUAL_INTERNAL_MODULE_ID = "\0astro:internal-actions";
6
+ const NOOP_ACTIONS = "\0noop-actions";
4
7
  export {
5
8
  ACTIONS_TYPES_FILE,
9
+ NOOP_ACTIONS,
10
+ RESOLVED_VIRTUAL_INTERNAL_MODULE_ID,
6
11
  RESOLVED_VIRTUAL_MODULE_ID,
12
+ VIRTUAL_INTERNAL_MODULE_ID,
7
13
  VIRTUAL_MODULE_ID
8
14
  };
@@ -1,5 +1,15 @@
1
1
  import fsMod from 'node:fs';
2
- import type { AstroIntegration } from '../@types/astro.js';
3
- export default function astroActions({ fs }: {
2
+ import type { Plugin as VitePlugin } from 'vite';
3
+ import type { AstroIntegration, AstroSettings } from '../@types/astro.js';
4
+ export default function astroActions({ fs, settings, }: {
4
5
  fs?: typeof fsMod;
6
+ settings: AstroSettings;
5
7
  }): AstroIntegration;
8
+ /**
9
+ * This plugin is responsible to load the known file `actions/index.js` / `actions.js`
10
+ * If the file doesn't exist, it returns an empty object.
11
+ * @param settings
12
+ */
13
+ export declare function vitePluginUserActions({ settings }: {
14
+ settings: AstroSettings;
15
+ }): VitePlugin;
@@ -2,8 +2,18 @@ import fsMod from "node:fs";
2
2
  import { ActionsWithoutServerOutputError } from "../core/errors/errors-data.js";
3
3
  import { AstroError } from "../core/errors/errors.js";
4
4
  import { isServerLikeOutput, viteID } from "../core/util.js";
5
- import { ACTIONS_TYPES_FILE, RESOLVED_VIRTUAL_MODULE_ID, VIRTUAL_MODULE_ID } from "./consts.js";
6
- function astroActions({ fs = fsMod }) {
5
+ import {
6
+ ACTIONS_TYPES_FILE,
7
+ NOOP_ACTIONS,
8
+ RESOLVED_VIRTUAL_INTERNAL_MODULE_ID,
9
+ RESOLVED_VIRTUAL_MODULE_ID,
10
+ VIRTUAL_INTERNAL_MODULE_ID,
11
+ VIRTUAL_MODULE_ID
12
+ } from "./consts.js";
13
+ function astroActions({
14
+ fs = fsMod,
15
+ settings
16
+ }) {
7
17
  return {
8
18
  name: VIRTUAL_MODULE_ID,
9
19
  hooks: {
@@ -18,10 +28,7 @@ function astroActions({ fs = fsMod }) {
18
28
  );
19
29
  params.updateConfig({
20
30
  vite: {
21
- define: {
22
- "import.meta.env.ACTIONS_PATH": stringifiedActionsImport
23
- },
24
- plugins: [vitePluginActions(fs)]
31
+ plugins: [vitePluginUserActions({ settings }), vitePluginActions(fs)]
25
32
  }
26
33
  });
27
34
  params.injectRoute({
@@ -42,6 +49,34 @@ function astroActions({ fs = fsMod }) {
42
49
  }
43
50
  };
44
51
  }
52
+ function vitePluginUserActions({ settings }) {
53
+ let resolvedActionsId;
54
+ return {
55
+ name: "@astro/plugin-actions",
56
+ async resolveId(id) {
57
+ if (id === NOOP_ACTIONS) {
58
+ return NOOP_ACTIONS;
59
+ }
60
+ if (id === VIRTUAL_INTERNAL_MODULE_ID) {
61
+ const resolvedModule = await this.resolve(
62
+ `${decodeURI(new URL("actions", settings.config.srcDir).pathname)}`
63
+ );
64
+ if (!resolvedModule) {
65
+ return NOOP_ACTIONS;
66
+ }
67
+ resolvedActionsId = resolvedModule.id;
68
+ return RESOLVED_VIRTUAL_INTERNAL_MODULE_ID;
69
+ }
70
+ },
71
+ load(id) {
72
+ if (id === NOOP_ACTIONS) {
73
+ return "export const server = {}";
74
+ } else if (id === RESOLVED_VIRTUAL_INTERNAL_MODULE_ID) {
75
+ return `export { server } from '${resolvedActionsId}';`;
76
+ }
77
+ }
78
+ };
79
+ }
45
80
  const vitePluginActions = (fs) => ({
46
81
  name: VIRTUAL_MODULE_ID,
47
82
  enforce: "pre",
@@ -81,5 +116,6 @@ async function typegen({
81
116
  await fs.promises.writeFile(new URL(ACTIONS_TYPES_FILE, dotAstroDir), content);
82
117
  }
83
118
  export {
84
- astroActions as default
119
+ astroActions as default,
120
+ vitePluginUserActions
85
121
  };
@@ -1,49 +1,106 @@
1
1
  import { yellow } from "kleur/colors";
2
+ import {
3
+ ActionQueryStringInvalidError,
4
+ ActionsUsedWithForGetError
5
+ } from "../../core/errors/errors-data.js";
6
+ import { AstroError } from "../../core/errors/errors.js";
2
7
  import { defineMiddleware } from "../../core/middleware/index.js";
3
8
  import { ApiContextStorage } from "./store.js";
4
9
  import { formContentTypes, getAction, hasContentType } from "./utils.js";
5
- import { callSafely } from "./virtual/shared.js";
10
+ import { getActionQueryString } from "./virtual/shared.js";
6
11
  const onRequest = defineMiddleware(async (context, next) => {
7
12
  const locals = context.locals;
13
+ const { request } = context;
8
14
  if (locals._actionsInternal) return ApiContextStorage.run(context, () => next());
9
- if (context.request.method === "GET") {
10
- return nextWithLocalsStub(next, context);
11
- }
12
- if (context.request.method === "POST" && context.request.body === null) {
15
+ if (request.method === "POST" && request.body === null) {
13
16
  return nextWithStaticStub(next, context);
14
17
  }
15
- const { request, url } = context;
16
- const contentType = request.headers.get("Content-Type");
17
- if (url.pathname.startsWith("/_actions")) return nextWithLocalsStub(next, context);
18
- if (!contentType || !hasContentType(contentType, formContentTypes)) {
19
- return nextWithLocalsStub(next, context);
18
+ const actionName = context.url.searchParams.get("_astroAction");
19
+ if (context.request.method === "POST" && actionName) {
20
+ return handlePost({ context, next, actionName });
21
+ }
22
+ if (context.request.method === "GET" && actionName) {
23
+ throw new AstroError({
24
+ ...ActionsUsedWithForGetError,
25
+ message: ActionsUsedWithForGetError.message(actionName)
26
+ });
20
27
  }
21
- const formData = await request.clone().formData();
22
- const actionPath = formData.get("_astroAction");
23
- if (typeof actionPath !== "string") return nextWithLocalsStub(next, context);
24
- const action = await getAction(actionPath);
25
- if (!action) return nextWithLocalsStub(next, context);
26
- const result = await ApiContextStorage.run(context, () => callSafely(() => action(formData)));
28
+ if (context.request.method === "POST") {
29
+ return handlePostLegacy({ context, next });
30
+ }
31
+ return nextWithLocalsStub(next, context);
32
+ });
33
+ async function handlePost({
34
+ context,
35
+ next,
36
+ actionName
37
+ }) {
38
+ const { request } = context;
39
+ const action = await getAction(actionName);
40
+ if (!action) {
41
+ throw new AstroError({
42
+ ...ActionQueryStringInvalidError,
43
+ message: ActionQueryStringInvalidError.message(actionName)
44
+ });
45
+ }
46
+ const contentType = request.headers.get("content-type");
47
+ let formData;
48
+ if (contentType && hasContentType(contentType, formContentTypes)) {
49
+ formData = await request.clone().formData();
50
+ }
51
+ const actionResult = await ApiContextStorage.run(context, () => action(formData));
52
+ return handleResult({ context, next, actionName, actionResult });
53
+ }
54
+ function handleResult({
55
+ context,
56
+ next,
57
+ actionName,
58
+ actionResult
59
+ }) {
27
60
  const actionsInternal = {
28
61
  getActionResult: (actionFn) => {
29
- if (actionFn.toString() !== actionPath) return Promise.resolve(void 0);
30
- return result;
62
+ if (actionFn.toString() !== getActionQueryString(actionName)) {
63
+ return Promise.resolve(void 0);
64
+ }
65
+ return actionResult;
31
66
  },
32
- actionResult: result
67
+ actionResult
33
68
  };
69
+ const locals = context.locals;
34
70
  Object.defineProperty(locals, "_actionsInternal", { writable: false, value: actionsInternal });
35
71
  return ApiContextStorage.run(context, async () => {
36
72
  const response = await next();
37
- if (result.error) {
73
+ if (actionResult.error) {
38
74
  return new Response(response.body, {
39
- status: result.error.status,
40
- statusText: result.error.name,
75
+ status: actionResult.error.status,
76
+ statusText: actionResult.error.type,
41
77
  headers: response.headers
42
78
  });
43
79
  }
44
80
  return response;
45
81
  });
46
- });
82
+ }
83
+ async function handlePostLegacy({ context, next }) {
84
+ const { request } = context;
85
+ if (context.url.pathname.startsWith("/_actions")) return nextWithLocalsStub(next, context);
86
+ const contentType = request.headers.get("content-type");
87
+ let formData;
88
+ if (contentType && hasContentType(contentType, formContentTypes)) {
89
+ formData = await request.clone().formData();
90
+ }
91
+ if (!formData) return nextWithLocalsStub(next, context);
92
+ const actionName = formData.get("_astroAction");
93
+ if (!actionName) return nextWithLocalsStub(next, context);
94
+ const action = await getAction(actionName);
95
+ if (!action) {
96
+ throw new AstroError({
97
+ ...ActionQueryStringInvalidError,
98
+ message: ActionQueryStringInvalidError.message(actionName)
99
+ });
100
+ }
101
+ const actionResult = await ApiContextStorage.run(context, () => action(formData));
102
+ return handleResult({ context, next, actionName, actionResult });
103
+ }
47
104
  function nextWithStaticStub(next, context) {
48
105
  Object.defineProperty(context.locals, "_actionsInternal", {
49
106
  writable: false,
@@ -1,6 +1,5 @@
1
1
  import { ApiContextStorage } from "./store.js";
2
2
  import { formContentTypes, getAction, hasContentType } from "./utils.js";
3
- import { callSafely } from "./virtual/shared.js";
4
3
  const POST = async (context) => {
5
4
  const { request, url } = context;
6
5
  const action = await getAction(url.pathname);
@@ -19,7 +18,7 @@ const POST = async (context) => {
19
18
  } else {
20
19
  return new Response(null, { status: 415 });
21
20
  }
22
- const result = await ApiContextStorage.run(context, () => callSafely(() => action(args)));
21
+ const result = await ApiContextStorage.run(context, () => action(args));
23
22
  if (result.error) {
24
23
  return new Response(
25
24
  JSON.stringify({
@@ -36,7 +35,7 @@ const POST = async (context) => {
36
35
  );
37
36
  }
38
37
  return new Response(JSON.stringify(result.data), {
39
- status: result.data ? 200 : 204,
38
+ status: result.data !== void 0 ? 200 : 204,
40
39
  headers: {
41
40
  "Content-Type": "application/json"
42
41
  }
@@ -1,12 +1,14 @@
1
+ import type { ZodType } from 'zod';
2
+ import type { ActionAccept, ActionClient } from './virtual/server.js';
1
3
  export declare const formContentTypes: string[];
2
4
  export declare function hasContentType(contentType: string, expected: string[]): boolean;
3
5
  export type MaybePromise<T> = T | Promise<T>;
4
6
  /**
5
7
  * Get server-side action based on the route path.
6
- * Imports from `import.meta.env.ACTIONS_PATH`, which maps to
8
+ * Imports from the virtual module `astro:internal-actions`, which maps to
7
9
  * the user's `src/actions/index.ts` file at build-time.
8
10
  */
9
- export declare function getAction(path: string): Promise<((param: unknown) => MaybePromise<unknown>) | undefined>;
11
+ export declare function getAction(path: string): Promise<ActionClient<unknown, ActionAccept, ZodType> | undefined>;
10
12
  /**
11
13
  * Used to preserve the input schema type in the error object.
12
14
  * This allows for type inference on the `fields` property
@@ -5,7 +5,7 @@ function hasContentType(contentType, expected) {
5
5
  }
6
6
  async function getAction(path) {
7
7
  const pathKeys = path.replace("/_actions/", "").split(".");
8
- let { server: actionLookup } = await import(import.meta.env.ACTIONS_PATH);
8
+ let { server: actionLookup } = await import("astro:internal-actions");
9
9
  for (const key of pathKeys) {
10
10
  if (!(key in actionLookup)) {
11
11
  return void 0;
@@ -10,15 +10,16 @@ export type ActionAccept = 'form' | 'json';
10
10
  export type ActionInputSchema<T extends ActionAccept | undefined> = T extends 'form' ? z.AnyZodObject | z.ZodType<FormData> : z.ZodType;
11
11
  export type ActionHandler<TInputSchema, TOutput> = TInputSchema extends z.ZodType ? (input: z.infer<TInputSchema>, context: ActionAPIContext) => MaybePromise<TOutput> : (input: any, context: ActionAPIContext) => MaybePromise<TOutput>;
12
12
  export type ActionReturnType<T extends ActionHandler<any, any>> = Awaited<ReturnType<T>>;
13
- 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<Awaited<TOutput>>) & {
14
- safe: (input: TAccept extends 'form' ? FormData : z.input<TInputSchema>) => Promise<SafeResult<z.input<TInputSchema> extends ErrorInferenceObject ? z.input<TInputSchema> : ErrorInferenceObject, Awaited<TOutput>>>;
15
- } : ((input?: any) => Promise<Awaited<TOutput>>) & {
16
- safe: (input?: any) => Promise<SafeResult<never, Awaited<TOutput>>>;
13
+ 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>>>) & {
14
+ queryString: string;
15
+ orThrow: (input: TAccept extends 'form' ? FormData : z.input<TInputSchema>) => Promise<Awaited<TOutput>>;
16
+ } : (input?: any) => Promise<SafeResult<never, Awaited<TOutput>>> & {
17
+ orThrow: (input?: any) => Promise<Awaited<TOutput>>;
17
18
  };
18
19
  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, }: {
19
20
  input?: TInputSchema;
20
21
  accept?: TAccept;
21
22
  handler: ActionHandler<TInputSchema, TOutput>;
22
- }): ActionClient<TOutput, TAccept, TInputSchema>;
23
+ }): ActionClient<TOutput, TAccept, TInputSchema> & string;
23
24
  /** Transform form data to an object based on a Zod schema. */
24
25
  export declare function formDataToObject<T extends z.AnyZodObject>(formData: FormData, schema: T): Record<string, unknown>;
@@ -10,12 +10,13 @@ function defineAction({
10
10
  handler
11
11
  }) {
12
12
  const serverHandler = accept === "form" ? getFormServerHandler(handler, inputSchema) : getJsonServerHandler(handler, inputSchema);
13
- Object.assign(serverHandler, {
14
- safe: async (unparsedInput) => {
15
- return callSafely(() => serverHandler(unparsedInput));
16
- }
13
+ const safeServerHandler = async (unparsedInput) => {
14
+ return callSafely(() => serverHandler(unparsedInput));
15
+ };
16
+ Object.assign(safeServerHandler, {
17
+ orThrow: serverHandler
17
18
  });
18
- return serverHandler;
19
+ return safeServerHandler;
19
20
  }
20
21
  function getFormServerHandler(handler, inputSchema) {
21
22
  return async (unparsedInput) => {
@@ -31,6 +31,13 @@ export declare class ActionInputError<T extends ErrorInferenceObject> extends Ac
31
31
  constructor(issues: z.ZodIssue[]);
32
32
  }
33
33
  export declare function callSafely<TOutput>(handler: () => MaybePromise<TOutput>): Promise<SafeResult<z.ZodType, TOutput>>;
34
+ export declare function getActionQueryString(name: string): string;
35
+ /**
36
+ * @deprecated You can now pass action functions
37
+ * directly to the `action` attribute on a form.
38
+ *
39
+ * Example: `<form action={actions.like} />`
40
+ */
34
41
  export declare function getActionProps<T extends (args: FormData) => MaybePromise<unknown>>(action: T): {
35
42
  readonly type: "hidden";
36
43
  readonly name: "_astroAction";
@@ -110,11 +110,20 @@ async function callSafely(handler) {
110
110
  };
111
111
  }
112
112
  }
113
+ function getActionQueryString(name) {
114
+ const searchParams = new URLSearchParams({ _astroAction: name });
115
+ return `?${searchParams.toString()}`;
116
+ }
113
117
  function getActionProps(action) {
118
+ const params = new URLSearchParams(action.toString());
119
+ const actionName = params.get("_astroAction");
120
+ if (!actionName) {
121
+ throw new Error("Invalid actions function was passed to getActionProps()");
122
+ }
114
123
  return {
115
124
  type: "hidden",
116
125
  name: "_astroAction",
117
- value: action.toString()
126
+ value: actionName
118
127
  };
119
128
  }
120
129
  export {
@@ -123,5 +132,6 @@ export {
123
132
  ActionInputError,
124
133
  callSafely,
125
134
  getActionProps,
135
+ getActionQueryString,
126
136
  isInputError
127
137
  };
@@ -569,7 +569,7 @@ async function resolveRangeToInstallSpecifier(name, range) {
569
569
  const versions = await fetchPackageVersions(name);
570
570
  if (versions instanceof Error) return name;
571
571
  const stableVersions = versions.filter((v) => !v.includes("-"));
572
- const maxStable = maxSatisfying(stableVersions, range);
572
+ const maxStable = maxSatisfying(stableVersions.length !== 0 ? stableVersions : versions, range);
573
573
  return `${name}@^${maxStable}`;
574
574
  }
575
575
  const INHERITED_FLAGS = /* @__PURE__ */ new Set([
@@ -15,7 +15,6 @@ function createManifest(manifest, renderers, middleware) {
15
15
  };
16
16
  return {
17
17
  hrefRoot: import.meta.url,
18
- rewritingEnabled: false,
19
18
  trailingSlash: manifest?.trailingSlash ?? ASTRO_CONFIG_DEFAULTS.trailingSlash,
20
19
  buildFormat: manifest?.buildFormat ?? ASTRO_CONFIG_DEFAULTS.build.format,
21
20
  compressHTML: manifest?.compressHTML ?? ASTRO_CONFIG_DEFAULTS.compressHTML,
@@ -7,5 +7,5 @@ export declare function createImage(pluginContext: PluginContext, shouldEmitFile
7
7
  height: number;
8
8
  src: string;
9
9
  fsPath: string;
10
- orientation?: number;
10
+ orientation?: number | undefined;
11
11
  }, string>;
@@ -283,7 +283,7 @@ async function writeContentFiles({
283
283
  let contentTypesStr = "";
284
284
  let dataTypesStr = "";
285
285
  const collectionSchemasDir = new URL("./collections/", settings.dotAstroDir);
286
- if (settings.config.experimental.contentCollectionJsonSchema && !fs.existsSync(collectionSchemasDir)) {
286
+ if (!fs.existsSync(collectionSchemasDir)) {
287
287
  fs.mkdirSync(collectionSchemasDir, { recursive: true });
288
288
  }
289
289
  for (const [collection, config] of Object.entries(contentConfig?.collections ?? {})) {
@@ -376,7 +376,7 @@ async function writeContentFiles({
376
376
  dataTypesStr += `};
377
377
  `;
378
378
  }
379
- if (settings.config.experimental.contentCollectionJsonSchema && collectionConfig?.schema) {
379
+ if (collectionConfig?.schema) {
380
380
  let zodSchemaForJson = typeof collectionConfig.schema === "function" ? collectionConfig.schema({ image: () => z.string() }) : collectionConfig.schema;
381
381
  if (zodSchemaForJson instanceof z.ZodObject) {
382
382
  zodSchemaForJson = zodSchemaForJson.extend({
@@ -390,7 +390,9 @@ async function writeContentFiles({
390
390
  zodToJsonSchema(zodSchemaForJson, {
391
391
  name: collectionKey.replace(/"/g, ""),
392
392
  markdownDescription: true,
393
- errorMessages: true
393
+ errorMessages: true,
394
+ // Fix for https://github.com/StefanTerdell/zod-to-json-schema/issues/110
395
+ dateStrategy: ["format:date-time", "format:date", "integer"]
394
396
  }),
395
397
  null,
396
398
  2
@@ -92,22 +92,9 @@ function astroContentAssetPropagationPlugin({
92
92
  };
93
93
  }
94
94
  function astroConfigBuildPlugin(options, internals) {
95
- let ssrPluginContext = void 0;
96
95
  return {
97
96
  targets: ["server"],
98
97
  hooks: {
99
- "build:before": ({ target }) => {
100
- return {
101
- vitePlugin: {
102
- name: "astro:content-build-plugin",
103
- generateBundle() {
104
- if (target === "server") {
105
- ssrPluginContext = this;
106
- }
107
- }
108
- }
109
- };
110
- },
111
98
  "build:post": ({ ssrOutputs, clientOutputs, mutate }) => {
112
99
  const outputs = ssrOutputs.flatMap((o) => o.output);
113
100
  const prependBase = (src) => {
@@ -187,7 +174,6 @@ function astroConfigBuildPlugin(options, internals) {
187
174
  mutate(chunk, ["server"], newCode);
188
175
  }
189
176
  }
190
- ssrPluginContext = void 0;
191
177
  }
192
178
  }
193
179
  };
@@ -55,7 +55,6 @@ export type SSRManifest = {
55
55
  i18n: SSRManifestI18n | undefined;
56
56
  middleware: MiddlewareHandler;
57
57
  checkOrigin: boolean;
58
- rewritingEnabled: boolean;
59
58
  experimentalEnvGetSecretEnabled: boolean;
60
59
  };
61
60
  export type SSRManifestI18n = {