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.
- package/dist/@types/astro.d.ts +6 -106
- package/dist/actions/consts.d.ts +3 -0
- package/dist/actions/consts.js +6 -0
- package/dist/actions/index.d.ts +12 -2
- package/dist/actions/index.js +43 -7
- package/dist/actions/runtime/middleware.js +80 -23
- package/dist/actions/runtime/route.js +2 -3
- package/dist/actions/runtime/utils.d.ts +4 -2
- package/dist/actions/runtime/utils.js +1 -1
- package/dist/actions/runtime/virtual/server.d.ts +6 -5
- package/dist/actions/runtime/virtual/server.js +6 -5
- package/dist/actions/runtime/virtual/shared.d.ts +7 -0
- package/dist/actions/runtime/virtual/shared.js +11 -1
- package/dist/cli/add/index.js +1 -1
- package/dist/container/index.js +0 -1
- package/dist/content/runtime-assets.d.ts +1 -1
- package/dist/content/types-generator.js +5 -3
- package/dist/content/vite-plugin-content-assets.js +0 -14
- package/dist/core/app/types.d.ts +0 -1
- package/dist/core/build/generate.js +10 -4
- package/dist/core/build/pipeline.js +0 -1
- package/dist/core/build/plugins/plugin-content.js +1 -1
- package/dist/core/build/plugins/plugin-manifest.js +0 -1
- package/dist/core/config/schema.d.ts +0 -34
- package/dist/core/config/schema.js +0 -4
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/errors/dev/utils.js +12 -3
- package/dist/core/errors/dev/vite.d.ts +13 -0
- package/dist/core/errors/dev/vite.js +18 -4
- package/dist/core/errors/errors-data.d.ts +28 -1
- package/dist/core/errors/errors-data.js +14 -0
- package/dist/core/messages.js +2 -2
- package/dist/core/middleware/callMiddleware.d.ts +1 -2
- package/dist/core/middleware/callMiddleware.js +2 -12
- package/dist/core/render-context.js +13 -37
- package/dist/env/runtime.d.ts +2 -2
- package/dist/env/runtime.js +1 -1
- package/dist/integrations/hooks.js +1 -1
- package/dist/runtime/client/dev-toolbar/apps/audit/rules/a11y.js +0 -14
- package/dist/runtime/server/render/astro/instance.d.ts +2 -2
- package/dist/runtime/server/render/server-islands.js +2 -1
- package/dist/transitions/router.js +0 -8
- package/dist/vite-plugin-astro-server/error.js +1 -2
- package/dist/vite-plugin-astro-server/plugin.js +0 -1
- package/dist/vite-plugin-astro-server/route.js +0 -1
- package/dist/vite-plugin-astro-server/vite.js +4 -0
- package/package.json +22 -22
- package/templates/actions.mjs +29 -32
- package/templates/env/module.mjs +2 -0
package/dist/@types/astro.d.ts
CHANGED
|
@@ -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
|
|
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/
|
|
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:
|
|
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
|
|
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
|
/**
|
package/dist/actions/consts.d.ts
CHANGED
|
@@ -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";
|
package/dist/actions/consts.js
CHANGED
|
@@ -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
|
};
|
package/dist/actions/index.d.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import fsMod from 'node:fs';
|
|
2
|
-
import type {
|
|
3
|
-
|
|
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;
|
package/dist/actions/index.js
CHANGED
|
@@ -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 {
|
|
6
|
-
|
|
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
|
-
|
|
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 {
|
|
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 (
|
|
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
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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() !==
|
|
30
|
-
|
|
62
|
+
if (actionFn.toString() !== getActionQueryString(actionName)) {
|
|
63
|
+
return Promise.resolve(void 0);
|
|
64
|
+
}
|
|
65
|
+
return actionResult;
|
|
31
66
|
},
|
|
32
|
-
actionResult
|
|
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 (
|
|
73
|
+
if (actionResult.error) {
|
|
38
74
|
return new Response(response.body, {
|
|
39
|
-
status:
|
|
40
|
-
statusText:
|
|
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, () =>
|
|
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 `
|
|
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<
|
|
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(
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
const safeServerHandler = async (unparsedInput) => {
|
|
14
|
+
return callSafely(() => serverHandler(unparsedInput));
|
|
15
|
+
};
|
|
16
|
+
Object.assign(safeServerHandler, {
|
|
17
|
+
orThrow: serverHandler
|
|
17
18
|
});
|
|
18
|
-
return
|
|
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:
|
|
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
|
};
|
package/dist/cli/add/index.js
CHANGED
|
@@ -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([
|
package/dist/container/index.js
CHANGED
|
@@ -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,
|
|
@@ -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 (
|
|
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 (
|
|
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
|
};
|
package/dist/core/app/types.d.ts
CHANGED