astro 4.8.3 → 4.8.4
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/astro-jsx.d.ts +3 -0
- package/client.d.ts +1 -1
- package/config.d.ts +5 -1
- package/dist/@types/astro.d.ts +7 -5
- package/dist/actions/index.js +8 -1
- package/dist/actions/runtime/middleware.js +1 -0
- package/dist/actions/runtime/route.js +20 -9
- package/dist/actions/runtime/utils.d.ts +1 -1
- package/dist/actions/runtime/utils.js +2 -2
- package/dist/actions/runtime/virtual/shared.d.ts +1 -0
- package/dist/actions/runtime/virtual/shared.js +14 -7
- package/dist/core/build/internal.d.ts +8 -0
- package/dist/core/build/internal.js +15 -1
- package/dist/core/build/plugins/plugin-analyzer.js +15 -4
- package/dist/core/build/plugins/plugin-css.js +14 -3
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +2 -1
- package/dist/core/errors/errors-data.d.ts +13 -0
- package/dist/core/errors/errors-data.js +7 -0
- package/dist/core/messages.js +2 -2
- package/dist/prefetch/index.d.ts +6 -2
- package/dist/prefetch/index.js +10 -12
- package/dist/runtime/server/render/script.js +6 -2
- package/package.json +4 -2
- package/templates/actions.mjs +4 -0
package/astro-jsx.d.ts
CHANGED
|
@@ -605,6 +605,7 @@ declare namespace astroHTML.JSX {
|
|
|
605
605
|
href?: string | URL | undefined | null;
|
|
606
606
|
hreflang?: string | undefined | null;
|
|
607
607
|
media?: string | undefined | null;
|
|
608
|
+
name?: string | undefined | null;
|
|
608
609
|
ping?: string | undefined | null;
|
|
609
610
|
rel?: string | undefined | null;
|
|
610
611
|
target?: HTMLAttributeAnchorTarget | undefined | null;
|
|
@@ -649,6 +650,7 @@ declare namespace astroHTML.JSX {
|
|
|
649
650
|
type?: 'submit' | 'reset' | 'button' | undefined | null;
|
|
650
651
|
value?: string | string[] | number | undefined | null;
|
|
651
652
|
popovertarget?: string | undefined | null;
|
|
653
|
+
popovertargetaction?: 'hide' | 'show' | 'toggle' | undefined | null;
|
|
652
654
|
}
|
|
653
655
|
|
|
654
656
|
interface CanvasHTMLAttributes extends HTMLAttributes {
|
|
@@ -815,6 +817,7 @@ declare namespace astroHTML.JSX {
|
|
|
815
817
|
value?: string | string[] | number | undefined | null;
|
|
816
818
|
width?: number | string | undefined | null;
|
|
817
819
|
popovertarget?: string | undefined | null;
|
|
820
|
+
popovertargetaction?: 'hide' | 'show' | 'toggle' | undefined | null;
|
|
818
821
|
}
|
|
819
822
|
|
|
820
823
|
interface KeygenHTMLAttributes extends HTMLAttributes {
|
package/client.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ interface ImportMetaEnv {
|
|
|
12
12
|
/**
|
|
13
13
|
* The prefix for Astro-generated asset links if the build.assetsPrefix config option is set. This can be used to create asset links not handled by Astro.
|
|
14
14
|
*/
|
|
15
|
-
readonly ASSETS_PREFIX: string
|
|
15
|
+
readonly ASSETS_PREFIX: string | Record<string, string>;
|
|
16
16
|
/**
|
|
17
17
|
* This is set to the site option specified in your project’s Astro config file.
|
|
18
18
|
*/
|
package/config.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
type ViteUserConfig = import('vite').UserConfig;
|
|
2
2
|
type ViteUserConfigFn = import('vite').UserConfigFn;
|
|
3
3
|
type AstroUserConfig = import('./dist/@types/astro.js').AstroUserConfig;
|
|
4
|
+
type AstroInlineConfig = import('./dist/@types/astro.js').AstroInlineConfig;
|
|
4
5
|
type ImageServiceConfig = import('./dist/@types/astro.js').ImageServiceConfig;
|
|
5
6
|
type SharpImageServiceConfig = import('./dist/assets/services/sharp.js').SharpImageServiceConfig;
|
|
6
7
|
|
|
@@ -13,7 +14,10 @@ export function defineConfig(config: AstroUserConfig): AstroUserConfig;
|
|
|
13
14
|
/**
|
|
14
15
|
* Use Astro to generate a fully resolved Vite config
|
|
15
16
|
*/
|
|
16
|
-
export function getViteConfig(
|
|
17
|
+
export function getViteConfig(
|
|
18
|
+
config: ViteUserConfig,
|
|
19
|
+
inlineAstroConfig?: AstroInlineConfig
|
|
20
|
+
): ViteUserConfigFn;
|
|
17
21
|
|
|
18
22
|
/**
|
|
19
23
|
* Return the configuration needed to use the Sharp-based image service
|
package/dist/@types/astro.d.ts
CHANGED
|
@@ -1612,7 +1612,7 @@ export interface AstroUserConfig {
|
|
|
1612
1612
|
*
|
|
1613
1613
|
* Declare all your actions in `src/actions/index.ts`. This file is the global actions handler.
|
|
1614
1614
|
*
|
|
1615
|
-
* Define an action using the `defineAction()` utility from the `astro:actions` module.
|
|
1615
|
+
* Define an action using the `defineAction()` utility from the `astro:actions` module. An action accepts the `handler` property to define your server-side request handler. If your action accepts arguments, apply the `input` property to validate parameters with Zod.
|
|
1616
1616
|
*
|
|
1617
1617
|
* This example defines two actions: `like` and `comment`. The `like` action accepts a JSON object with a `postId` string, while the `comment` action accepts [FormData](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects) with `postId`, `author`, and `body` strings. Each `handler` updates your database and return a type-safe response.
|
|
1618
1618
|
*
|
|
@@ -1645,12 +1645,14 @@ export interface AstroUserConfig {
|
|
|
1645
1645
|
* };
|
|
1646
1646
|
* ```
|
|
1647
1647
|
*
|
|
1648
|
-
* Then, call an action from your client components using the `actions` object from `astro:actions`. You can pass a type-safe object when using JSON, or a [FormData](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects) object when using `accept: 'form'` in your action definition
|
|
1648
|
+
* Then, call an action from your client components using the `actions` object from `astro:actions`. You can pass a type-safe object when using JSON, or a [FormData](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects) object when using `accept: 'form'` in your action definition.
|
|
1649
|
+
*
|
|
1650
|
+
* This example calls the `like` and `comment` actions from a React component:
|
|
1649
1651
|
*
|
|
1650
1652
|
* ```tsx "actions"
|
|
1651
1653
|
* // src/components/blog.tsx
|
|
1652
1654
|
* import { actions } from "astro:actions";
|
|
1653
|
-
* import { useState } from "
|
|
1655
|
+
* import { useState } from "react";
|
|
1654
1656
|
*
|
|
1655
1657
|
* export function Like({ postId }: { postId: string }) {
|
|
1656
1658
|
* const [likes, setLikes] = useState(0);
|
|
@@ -1671,13 +1673,13 @@ export interface AstroUserConfig {
|
|
|
1671
1673
|
* <form
|
|
1672
1674
|
* onSubmit={async (e) => {
|
|
1673
1675
|
* e.preventDefault();
|
|
1674
|
-
* const formData = new FormData(e.target);
|
|
1676
|
+
* const formData = new FormData(e.target as HTMLFormElement);
|
|
1675
1677
|
* const result = await actions.blog.comment(formData);
|
|
1676
1678
|
* // handle result
|
|
1677
1679
|
* }}
|
|
1678
1680
|
* >
|
|
1679
1681
|
* <input type="hidden" name="postId" value={postId} />
|
|
1680
|
-
* <label
|
|
1682
|
+
* <label htmlFor="author">Author</label>
|
|
1681
1683
|
* <input id="author" type="text" name="author" />
|
|
1682
1684
|
* <textarea rows={10} name="body"></textarea>
|
|
1683
1685
|
* <button type="submit">Post</button>
|
package/dist/actions/index.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
-
import {
|
|
2
|
+
import { ActionsWithoutServerOutputError } from "../core/errors/errors-data.js";
|
|
3
|
+
import { AstroError } from "../core/errors/errors.js";
|
|
4
|
+
import { isServerLikeOutput, viteID } from "../core/util.js";
|
|
3
5
|
import { ACTIONS_TYPES_FILE, RESOLVED_VIRTUAL_MODULE_ID, VIRTUAL_MODULE_ID } from "./consts.js";
|
|
4
6
|
function astroActions() {
|
|
5
7
|
return {
|
|
6
8
|
name: VIRTUAL_MODULE_ID,
|
|
7
9
|
hooks: {
|
|
8
10
|
async "astro:config:setup"(params) {
|
|
11
|
+
if (!isServerLikeOutput(params.config)) {
|
|
12
|
+
const error = new AstroError(ActionsWithoutServerOutputError);
|
|
13
|
+
error.stack = void 0;
|
|
14
|
+
throw error;
|
|
15
|
+
}
|
|
9
16
|
const stringifiedActionsImport = JSON.stringify(
|
|
10
17
|
viteID(new URL("./actions", params.config.srcDir))
|
|
11
18
|
);
|
|
@@ -14,6 +14,7 @@ const onRequest = defineMiddleware(async (context, next) => {
|
|
|
14
14
|
if (typeof actionPath !== "string") return nextWithLocalsStub(next, locals);
|
|
15
15
|
const actionPathKeys = actionPath.replace("/_actions/", "").split(".");
|
|
16
16
|
const action = await getAction(actionPathKeys);
|
|
17
|
+
if (!action) return nextWithLocalsStub(next, locals);
|
|
17
18
|
const result = await ApiContextStorage.run(context, () => callSafely(() => action(formData)));
|
|
18
19
|
const actionsInternal = {
|
|
19
20
|
getActionResult: (actionFn) => {
|
|
@@ -5,9 +5,15 @@ const POST = async (context) => {
|
|
|
5
5
|
const { request, url } = context;
|
|
6
6
|
const actionPathKeys = url.pathname.replace("/_actions/", "").split(".");
|
|
7
7
|
const action = await getAction(actionPathKeys);
|
|
8
|
+
if (!action) {
|
|
9
|
+
return new Response(null, { status: 404 });
|
|
10
|
+
}
|
|
8
11
|
const contentType = request.headers.get("Content-Type");
|
|
12
|
+
const contentLength = request.headers.get("Content-Length");
|
|
9
13
|
let args;
|
|
10
|
-
if (
|
|
14
|
+
if (contentLength === "0") {
|
|
15
|
+
args = void 0;
|
|
16
|
+
} else if (contentType && hasContentType(contentType, formContentTypes)) {
|
|
11
17
|
args = await request.clone().formData();
|
|
12
18
|
} else if (contentType && hasContentType(contentType, ["application/json"])) {
|
|
13
19
|
args = await request.clone().json();
|
|
@@ -16,17 +22,22 @@ const POST = async (context) => {
|
|
|
16
22
|
}
|
|
17
23
|
const result = await ApiContextStorage.run(context, () => callSafely(() => action(args)));
|
|
18
24
|
if (result.error) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
return new Response(
|
|
26
|
+
JSON.stringify({
|
|
27
|
+
...result.error,
|
|
28
|
+
message: result.error.message,
|
|
29
|
+
stack: import.meta.env.PROD ? void 0 : result.error.stack
|
|
30
|
+
}),
|
|
31
|
+
{
|
|
32
|
+
status: result.error.status,
|
|
33
|
+
headers: {
|
|
34
|
+
"Content-Type": "application/json"
|
|
35
|
+
}
|
|
26
36
|
}
|
|
27
|
-
|
|
37
|
+
);
|
|
28
38
|
}
|
|
29
39
|
return new Response(JSON.stringify(result.data), {
|
|
40
|
+
status: result.data ? 200 : 204,
|
|
30
41
|
headers: {
|
|
31
42
|
"Content-Type": "application/json"
|
|
32
43
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare const formContentTypes: string[];
|
|
2
2
|
export declare function hasContentType(contentType: string, expected: string[]): boolean;
|
|
3
3
|
export type MaybePromise<T> = T | Promise<T>;
|
|
4
|
-
export declare function getAction(pathKeys: string[]): Promise<(param: unknown) => MaybePromise<unknown
|
|
4
|
+
export declare function getAction(pathKeys: string[]): Promise<((param: unknown) => MaybePromise<unknown>) | undefined>;
|
|
@@ -7,12 +7,12 @@ async function getAction(pathKeys) {
|
|
|
7
7
|
let { server: actionLookup } = await import(import.meta.env.ACTIONS_PATH);
|
|
8
8
|
for (const key of pathKeys) {
|
|
9
9
|
if (!(key in actionLookup)) {
|
|
10
|
-
|
|
10
|
+
return void 0;
|
|
11
11
|
}
|
|
12
12
|
actionLookup = actionLookup[key];
|
|
13
13
|
}
|
|
14
14
|
if (typeof actionLookup !== "function") {
|
|
15
|
-
|
|
15
|
+
return void 0;
|
|
16
16
|
}
|
|
17
17
|
return actionLookup;
|
|
18
18
|
}
|
|
@@ -9,6 +9,7 @@ export declare class ActionError<T extends ErrorInferenceObject = ErrorInference
|
|
|
9
9
|
constructor(params: {
|
|
10
10
|
message?: string;
|
|
11
11
|
code: ActionErrorCode;
|
|
12
|
+
stack?: string;
|
|
12
13
|
});
|
|
13
14
|
static codeToStatus(code: ActionErrorCode): number;
|
|
14
15
|
static statusToCode(status: number): ActionErrorCode;
|
|
@@ -28,6 +28,9 @@ class ActionError extends Error {
|
|
|
28
28
|
super(params.message);
|
|
29
29
|
this.code = params.code;
|
|
30
30
|
this.status = ActionError.codeToStatus(params.code);
|
|
31
|
+
if (params.stack) {
|
|
32
|
+
this.stack = params.stack;
|
|
33
|
+
}
|
|
31
34
|
}
|
|
32
35
|
static codeToStatus(code) {
|
|
33
36
|
return codeToStatusMap[code];
|
|
@@ -36,15 +39,16 @@ class ActionError extends Error {
|
|
|
36
39
|
return statusToCodeMap[status] ?? "INTERNAL_SERVER_ERROR";
|
|
37
40
|
}
|
|
38
41
|
static async fromResponse(res) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
const body = await res.clone().json();
|
|
43
|
+
if (typeof body === "object" && body?.type === "AstroActionInputError" && Array.isArray(body.issues)) {
|
|
44
|
+
return new ActionInputError(body.issues);
|
|
45
|
+
}
|
|
46
|
+
if (typeof body === "object" && body?.type === "AstroActionError") {
|
|
47
|
+
return new ActionError(body);
|
|
44
48
|
}
|
|
45
49
|
return new ActionError({
|
|
46
50
|
message: res.statusText,
|
|
47
|
-
code:
|
|
51
|
+
code: ActionError.statusToCode(res.status)
|
|
48
52
|
});
|
|
49
53
|
}
|
|
50
54
|
}
|
|
@@ -59,7 +63,10 @@ class ActionInputError extends ActionError {
|
|
|
59
63
|
issues;
|
|
60
64
|
fields;
|
|
61
65
|
constructor(issues) {
|
|
62
|
-
super({
|
|
66
|
+
super({
|
|
67
|
+
message: `Failed to validate: ${JSON.stringify(issues, null, 2)}`,
|
|
68
|
+
code: "BAD_REQUEST"
|
|
69
|
+
});
|
|
63
70
|
this.issues = issues;
|
|
64
71
|
this.fields = {};
|
|
65
72
|
for (const issue of issues) {
|
|
@@ -40,6 +40,10 @@ export interface BuildInternals {
|
|
|
40
40
|
* A map for page-specific information by a client:only component
|
|
41
41
|
*/
|
|
42
42
|
pagesByClientOnly: Map<string, Set<PageBuildData>>;
|
|
43
|
+
/**
|
|
44
|
+
* A map for page-specific information by a script in an Astro file
|
|
45
|
+
*/
|
|
46
|
+
pagesByScriptId: Map<string, Set<PageBuildData>>;
|
|
43
47
|
/**
|
|
44
48
|
* A map of hydrated components to export names that are discovered during the SSR build.
|
|
45
49
|
* These will be used as the top-level entrypoints for the client build.
|
|
@@ -96,6 +100,10 @@ export declare function trackPageData(internals: BuildInternals, component: stri
|
|
|
96
100
|
* Tracks client-only components to the pages they are associated with.
|
|
97
101
|
*/
|
|
98
102
|
export declare function trackClientOnlyPageDatas(internals: BuildInternals, pageData: PageBuildData, clientOnlys: string[]): void;
|
|
103
|
+
/**
|
|
104
|
+
* Tracks scripts to the pages they are associated with. (experimental.directRenderScript)
|
|
105
|
+
*/
|
|
106
|
+
export declare function trackScriptPageDatas(internals: BuildInternals, pageData: PageBuildData, scriptIds: string[]): void;
|
|
99
107
|
export declare function getPageDatasByChunk(internals: BuildInternals, chunk: Rollup.RenderedChunk): Generator<PageBuildData, void, unknown>;
|
|
100
108
|
export declare function getPageDatasByClientOnlyID(internals: BuildInternals, viteid: ViteID): Generator<PageBuildData, void, unknown>;
|
|
101
109
|
/**
|
|
@@ -16,6 +16,7 @@ function createBuildInternals() {
|
|
|
16
16
|
pageOptionsByPage: /* @__PURE__ */ new Map(),
|
|
17
17
|
pagesByViteID: /* @__PURE__ */ new Map(),
|
|
18
18
|
pagesByClientOnly: /* @__PURE__ */ new Map(),
|
|
19
|
+
pagesByScriptId: /* @__PURE__ */ new Map(),
|
|
19
20
|
propagatedStylesMap: /* @__PURE__ */ new Map(),
|
|
20
21
|
propagatedScriptsMap: /* @__PURE__ */ new Map(),
|
|
21
22
|
discoveredHydratedComponents: /* @__PURE__ */ new Map(),
|
|
@@ -45,6 +46,18 @@ function trackClientOnlyPageDatas(internals, pageData, clientOnlys) {
|
|
|
45
46
|
pageDataSet.add(pageData);
|
|
46
47
|
}
|
|
47
48
|
}
|
|
49
|
+
function trackScriptPageDatas(internals, pageData, scriptIds) {
|
|
50
|
+
for (const scriptId of scriptIds) {
|
|
51
|
+
let pageDataSet;
|
|
52
|
+
if (internals.pagesByScriptId.has(scriptId)) {
|
|
53
|
+
pageDataSet = internals.pagesByScriptId.get(scriptId);
|
|
54
|
+
} else {
|
|
55
|
+
pageDataSet = /* @__PURE__ */ new Set();
|
|
56
|
+
internals.pagesByScriptId.set(scriptId, pageDataSet);
|
|
57
|
+
}
|
|
58
|
+
pageDataSet.add(pageData);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
48
61
|
function* getPageDatasByChunk(internals, chunk) {
|
|
49
62
|
const pagesByViteID = internals.pagesByViteID;
|
|
50
63
|
for (const [modulePath] of Object.entries(chunk.modules)) {
|
|
@@ -180,5 +193,6 @@ export {
|
|
|
180
193
|
hasPrerenderedPages,
|
|
181
194
|
mergeInlineCss,
|
|
182
195
|
trackClientOnlyPageDatas,
|
|
183
|
-
trackPageData
|
|
196
|
+
trackPageData,
|
|
197
|
+
trackScriptPageDatas
|
|
184
198
|
};
|
|
@@ -5,7 +5,11 @@ import {
|
|
|
5
5
|
getTopLevelPageModuleInfos,
|
|
6
6
|
moduleIsTopLevelPage
|
|
7
7
|
} from "../graph.js";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
getPageDataByViteID,
|
|
10
|
+
trackClientOnlyPageDatas,
|
|
11
|
+
trackScriptPageDatas
|
|
12
|
+
} from "../internal.js";
|
|
9
13
|
function isPropagatedAsset(id) {
|
|
10
14
|
try {
|
|
11
15
|
return new URL("file://" + id).searchParams.has(PROPAGATED_ASSET_FLAG);
|
|
@@ -120,9 +124,16 @@ function vitePluginAnalyzer(options, internals) {
|
|
|
120
124
|
}
|
|
121
125
|
}
|
|
122
126
|
if (options.settings.config.experimental.directRenderScript && astro.scripts.length) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
127
|
+
const scriptIds = astro.scripts.map(
|
|
128
|
+
(_, i) => `${id.replace("/@fs", "")}?astro&type=script&index=${i}&lang.ts`
|
|
129
|
+
);
|
|
130
|
+
for (const scriptId of scriptIds) {
|
|
131
|
+
internals.discoveredScripts.add(scriptId);
|
|
132
|
+
}
|
|
133
|
+
for (const pageInfo of getTopLevelPageModuleInfos(id, this)) {
|
|
134
|
+
const newPageData = getPageDataByViteID(internals, pageInfo.id);
|
|
135
|
+
if (!newPageData) continue;
|
|
136
|
+
trackScriptPageDatas(internals, newPageData, scriptIds);
|
|
126
137
|
}
|
|
127
138
|
}
|
|
128
139
|
}
|
|
@@ -92,9 +92,20 @@ function rollupPluginAstroBuildCSS(options) {
|
|
|
92
92
|
if (pageData) {
|
|
93
93
|
appendCSSToPage(pageData, meta, pagesToCss, depth, order);
|
|
94
94
|
}
|
|
95
|
-
} else if (options.target === "client"
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
} else if (options.target === "client") {
|
|
96
|
+
if (buildOptions.settings.config.experimental.directRenderScript) {
|
|
97
|
+
const pageDatas = internals.pagesByScriptId.get(pageInfo.id);
|
|
98
|
+
if (pageDatas) {
|
|
99
|
+
for (const pageData of pageDatas) {
|
|
100
|
+
appendCSSToPage(pageData, meta, pagesToCss, -1, order);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
if (internals.hoistedScriptIdToPagesMap.has(pageInfo.id)) {
|
|
105
|
+
for (const pageData of getPageDatasByHoistedScriptId(internals, pageInfo.id)) {
|
|
106
|
+
appendCSSToPage(pageData, meta, pagesToCss, -1, order);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
98
109
|
}
|
|
99
110
|
}
|
|
100
111
|
}
|
package/dist/core/constants.js
CHANGED
package/dist/core/dev/dev.js
CHANGED
|
@@ -19,7 +19,7 @@ async function dev(inlineConfig) {
|
|
|
19
19
|
await telemetry.record([]);
|
|
20
20
|
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
|
|
21
21
|
const logger = restart.container.logger;
|
|
22
|
-
const currentVersion = "4.8.
|
|
22
|
+
const currentVersion = "4.8.4";
|
|
23
23
|
const isPrerelease = currentVersion.includes("-");
|
|
24
24
|
if (!isPrerelease) {
|
|
25
25
|
try {
|
|
@@ -42,6 +42,7 @@ async function dev(inlineConfig) {
|
|
|
42
42
|
);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
+
}).catch(() => {
|
|
45
46
|
});
|
|
46
47
|
} catch (e) {
|
|
47
48
|
}
|
|
@@ -1334,6 +1334,19 @@ export declare const DuplicateContentEntrySlugError: {
|
|
|
1334
1334
|
title: string;
|
|
1335
1335
|
message(collection: string, slug: string, preExisting: string, alsoFound: string): string;
|
|
1336
1336
|
};
|
|
1337
|
+
/**
|
|
1338
|
+
* @docs
|
|
1339
|
+
* @see
|
|
1340
|
+
* - [On-demand rendering](https://docs.astro.build/en/basics/rendering-modes/#on-demand-rendered)
|
|
1341
|
+
* @description
|
|
1342
|
+
* Your project must have a server output to create backend functions with Actions.
|
|
1343
|
+
*/
|
|
1344
|
+
export declare const ActionsWithoutServerOutputError: {
|
|
1345
|
+
name: string;
|
|
1346
|
+
title: string;
|
|
1347
|
+
message: string;
|
|
1348
|
+
hint: string;
|
|
1349
|
+
};
|
|
1337
1350
|
/**
|
|
1338
1351
|
* @docs
|
|
1339
1352
|
* @see
|
|
@@ -502,6 +502,12 @@ Entries:
|
|
|
502
502
|
- ${alsoFound}`;
|
|
503
503
|
}
|
|
504
504
|
};
|
|
505
|
+
const ActionsWithoutServerOutputError = {
|
|
506
|
+
name: "ActionsWithoutServerOutputError",
|
|
507
|
+
title: "Actions must be used with server output.",
|
|
508
|
+
message: "Actions enabled without setting a server build output. A server is required to create callable backend functions. To deploy routes to a server, add a server adapter to your astro config.",
|
|
509
|
+
hint: "Learn about on-demand rendering: https://docs.astro.build/en/basics/rendering-modes/#on-demand-rendered"
|
|
510
|
+
};
|
|
505
511
|
const UnsupportedConfigTransformError = {
|
|
506
512
|
name: "UnsupportedConfigTransformError",
|
|
507
513
|
title: "Unsupported transform in content config.",
|
|
@@ -511,6 +517,7 @@ Full error: ${parseError}`,
|
|
|
511
517
|
};
|
|
512
518
|
const UnknownError = { name: "UnknownError", title: "Unknown Error." };
|
|
513
519
|
export {
|
|
520
|
+
ActionsWithoutServerOutputError,
|
|
514
521
|
AstroGlobNoMatch,
|
|
515
522
|
AstroGlobUsedOutside,
|
|
516
523
|
AstroResponseHeadersReassigned,
|
package/dist/core/messages.js
CHANGED
|
@@ -37,7 +37,7 @@ function serverStart({
|
|
|
37
37
|
host,
|
|
38
38
|
base
|
|
39
39
|
}) {
|
|
40
|
-
const version = "4.8.
|
|
40
|
+
const version = "4.8.4";
|
|
41
41
|
const localPrefix = `${dim("\u2503")} Local `;
|
|
42
42
|
const networkPrefix = `${dim("\u2503")} Network `;
|
|
43
43
|
const emptyPrefix = " ".repeat(11);
|
|
@@ -269,7 +269,7 @@ function printHelp({
|
|
|
269
269
|
message.push(
|
|
270
270
|
linebreak(),
|
|
271
271
|
` ${bgGreen(black(` ${commandName} `))} ${green(
|
|
272
|
-
`v${"4.8.
|
|
272
|
+
`v${"4.8.4"}`
|
|
273
273
|
)} ${headline}`
|
|
274
274
|
);
|
|
275
275
|
}
|
package/dist/prefetch/index.d.ts
CHANGED
|
@@ -11,8 +11,12 @@ export declare function init(defaultOpts?: InitOptions): void;
|
|
|
11
11
|
export interface PrefetchOptions {
|
|
12
12
|
/**
|
|
13
13
|
* How the prefetch should prioritize the URL. (default `'link'`)
|
|
14
|
-
* - `'link'`: use `<link rel="prefetch"
|
|
15
|
-
* - `'fetch'`: use `fetch()
|
|
14
|
+
* - `'link'`: use `<link rel="prefetch">`.
|
|
15
|
+
* - `'fetch'`: use `fetch()`.
|
|
16
|
+
*
|
|
17
|
+
* @deprecated It is recommended to not use this option, and let prefetch use `'link'` whenever it's supported,
|
|
18
|
+
* or otherwise fall back to `'fetch'`. `'link'` works better if the URL doesn't set an appropriate cache header,
|
|
19
|
+
* as the browser will continue to cache it as long as it's used subsequently.
|
|
16
20
|
*/
|
|
17
21
|
with?: 'link' | 'fetch';
|
|
18
22
|
/**
|
package/dist/prefetch/index.js
CHANGED
|
@@ -24,7 +24,7 @@ function initTapStrategy() {
|
|
|
24
24
|
event,
|
|
25
25
|
(e) => {
|
|
26
26
|
if (elMatchesStrategy(e.target, "tap")) {
|
|
27
|
-
prefetch(e.target.href, {
|
|
27
|
+
prefetch(e.target.href, { ignoreSlowConnection: true });
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
{ passive: true }
|
|
@@ -59,7 +59,7 @@ function initHoverStrategy() {
|
|
|
59
59
|
clearTimeout(timeout);
|
|
60
60
|
}
|
|
61
61
|
timeout = setTimeout(() => {
|
|
62
|
-
prefetch(href
|
|
62
|
+
prefetch(href);
|
|
63
63
|
}, 80);
|
|
64
64
|
}
|
|
65
65
|
function handleHoverOut() {
|
|
@@ -97,7 +97,7 @@ function createViewportIntersectionObserver() {
|
|
|
97
97
|
setTimeout(() => {
|
|
98
98
|
observer.unobserve(anchor);
|
|
99
99
|
timeouts.delete(anchor);
|
|
100
|
-
prefetch(anchor.href
|
|
100
|
+
prefetch(anchor.href);
|
|
101
101
|
}, 300)
|
|
102
102
|
);
|
|
103
103
|
} else {
|
|
@@ -113,7 +113,7 @@ function initLoadStrategy() {
|
|
|
113
113
|
onPageLoad(() => {
|
|
114
114
|
for (const anchor of document.getElementsByTagName("a")) {
|
|
115
115
|
if (elMatchesStrategy(anchor, "load")) {
|
|
116
|
-
prefetch(anchor.href
|
|
116
|
+
prefetch(anchor.href);
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
});
|
|
@@ -122,20 +122,18 @@ function prefetch(url, opts) {
|
|
|
122
122
|
const ignoreSlowConnection = opts?.ignoreSlowConnection ?? false;
|
|
123
123
|
if (!canPrefetchUrl(url, ignoreSlowConnection)) return;
|
|
124
124
|
prefetchedUrls.add(url);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (clientPrerender && HTMLScriptElement.supports && HTMLScriptElement.supports("speculationrules")) {
|
|
125
|
+
if (clientPrerender && HTMLScriptElement.supports?.("speculationrules")) {
|
|
126
|
+
debug?.(`[astro] Prefetching ${url} with <script type="speculationrules">`);
|
|
128
127
|
appendSpeculationRules(url);
|
|
129
|
-
} else if (
|
|
128
|
+
} else if (document.createElement("link").relList?.supports?.("prefetch") && opts?.with !== "fetch") {
|
|
129
|
+
debug?.(`[astro] Prefetching ${url} with <link rel="prefetch">`);
|
|
130
130
|
const link = document.createElement("link");
|
|
131
131
|
link.rel = "prefetch";
|
|
132
132
|
link.setAttribute("href", url);
|
|
133
133
|
document.head.append(link);
|
|
134
134
|
} else {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
console.error(e);
|
|
138
|
-
});
|
|
135
|
+
debug?.(`[astro] Prefetching ${url} with fetch`);
|
|
136
|
+
fetch(url, { priority: "low" });
|
|
139
137
|
}
|
|
140
138
|
}
|
|
141
139
|
function canPrefetchUrl(url, ignoreSlowConnection) {
|
|
@@ -3,8 +3,12 @@ async function renderScript(result, id) {
|
|
|
3
3
|
if (result._metadata.renderedScripts.has(id)) return;
|
|
4
4
|
result._metadata.renderedScripts.add(id);
|
|
5
5
|
const inlined = result.inlinedScripts.get(id);
|
|
6
|
-
if (inlined) {
|
|
7
|
-
|
|
6
|
+
if (inlined != null) {
|
|
7
|
+
if (inlined) {
|
|
8
|
+
return markHTMLString(`<script type="module">${inlined}</script>`);
|
|
9
|
+
} else {
|
|
10
|
+
return "";
|
|
11
|
+
}
|
|
8
12
|
}
|
|
9
13
|
const resolved = await result.resolve(id);
|
|
10
14
|
return markHTMLString(`<script type="module" src="${resolved}"></script>`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro",
|
|
3
|
-
"version": "4.8.
|
|
3
|
+
"version": "4.8.4",
|
|
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",
|
|
@@ -229,8 +229,10 @@
|
|
|
229
229
|
"postbuild": "astro-scripts copy \"src/**/*.astro\" && astro-scripts copy \"src/**/*.wasm\"",
|
|
230
230
|
"test": "pnpm run test:node",
|
|
231
231
|
"test:match": "pnpm run test:node --match",
|
|
232
|
-
"test:e2e": "
|
|
232
|
+
"test:e2e": "pnpm test:e2e:chrome && pnpm test:e2e:firefox",
|
|
233
233
|
"test:e2e:match": "playwright test -g",
|
|
234
|
+
"test:e2e:chrome": "playwright test",
|
|
235
|
+
"test:e2e:firefox": "playwright test --config playwright.firefox.config.js",
|
|
234
236
|
"test:node": "astro-scripts test \"test/**/*.test.js\""
|
|
235
237
|
}
|
|
236
238
|
}
|
package/templates/actions.mjs
CHANGED
|
@@ -45,6 +45,7 @@ async function actionHandler(clientParam, path) {
|
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
headers.set('Content-Type', 'application/json');
|
|
48
|
+
headers.set('Content-Length', body?.length.toString() ?? '0');
|
|
48
49
|
}
|
|
49
50
|
const res = await fetch(path, {
|
|
50
51
|
method: 'POST',
|
|
@@ -54,6 +55,9 @@ async function actionHandler(clientParam, path) {
|
|
|
54
55
|
if (!res.ok) {
|
|
55
56
|
throw await ActionError.fromResponse(res);
|
|
56
57
|
}
|
|
58
|
+
// Check if response body is empty before parsing.
|
|
59
|
+
if (res.status === 204) return;
|
|
60
|
+
|
|
57
61
|
const json = await res.json();
|
|
58
62
|
return json;
|
|
59
63
|
}
|