astro 5.0.0-alpha.7 → 5.0.0-beta.1

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/client.d.ts CHANGED
@@ -116,8 +116,12 @@ declare module 'astro:transitions' {
116
116
  export const fade: TransitionModule['fade'];
117
117
  export const createAnimationScope: TransitionModule['createAnimationScope'];
118
118
 
119
- type ViewTransitionsModule = typeof import('./components/ViewTransitions.astro');
120
- export const ViewTransitions: ViewTransitionsModule['default'];
119
+ type ClientRouterModule = typeof import('./components/ClientRouter.astro');
120
+ /**
121
+ * @deprecated The ViewTransitions component has been renamed to ClientRouter
122
+ */
123
+ export const ViewTransitions: ClientRouterModule['default'];
124
+ export const ClientRouter: ClientRouterModule['default'];
121
125
  }
122
126
 
123
127
  declare module 'astro:transitions/client' {
@@ -36,6 +36,7 @@ async function printInfo({ flags }) {
36
36
  await copyToClipboard(output);
37
37
  }
38
38
  async function copyToClipboard(text) {
39
+ text = text.trim();
39
40
  const system = platform();
40
41
  let command = "";
41
42
  if (system === "darwin") {
@@ -43,15 +44,22 @@ async function copyToClipboard(text) {
43
44
  } else if (system === "win32") {
44
45
  command = "clip";
45
46
  } else {
46
- try {
47
- const output = execSync("which xclip", { encoding: "utf8" });
48
- if (output[0] !== "/") {
49
- return;
47
+ const unixCommands = [
48
+ ["xclip", "-sel clipboard -l 1"],
49
+ ["wl-copy", '"$0"']
50
+ ];
51
+ for (const [unixCommand, args] of unixCommands) {
52
+ try {
53
+ const output = execSync(`which ${unixCommand}`, { encoding: "utf8", stdio: "pipe" });
54
+ if (output[0] !== "/") {
55
+ continue;
56
+ }
57
+ command = `${unixCommand} ${args}`;
58
+ } catch {
59
+ continue;
50
60
  }
51
- command = "xclip -sel clipboard -l 1";
52
- } catch {
53
- return;
54
61
  }
62
+ if (!command) return;
55
63
  }
56
64
  console.log();
57
65
  const { shouldCopy } = await prompts({
@@ -62,8 +70,9 @@ async function copyToClipboard(text) {
62
70
  });
63
71
  if (!shouldCopy) return;
64
72
  try {
65
- execSync(command, {
66
- input: text.trim(),
73
+ execSync(command.replaceAll("$0", text), {
74
+ stdio: "ignore",
75
+ input: text,
67
76
  encoding: "utf8"
68
77
  });
69
78
  } catch {
@@ -2,6 +2,6 @@ import type { UserConfig as ViteUserConfig } from 'vite';
2
2
  import type { AstroInlineConfig, AstroUserConfig } from '../types/public/config.js';
3
3
  export declare function defineConfig(config: AstroUserConfig): AstroUserConfig;
4
4
  export declare function getViteConfig(userViteConfig: ViteUserConfig, inlineAstroConfig?: AstroInlineConfig): ({ mode, command }: {
5
- mode: string;
5
+ mode: "dev";
6
6
  command: "serve" | "build";
7
7
  }) => Promise<Record<string, any>>;
@@ -1,5 +1,6 @@
1
1
  import { Logger } from "../core/logger/core.js";
2
2
  import { createRouteManifest } from "../core/routing/index.js";
3
+ import { createDevelopmentManifest } from "../vite-plugin-astro-server/plugin.js";
3
4
  function defineConfig(config) {
4
5
  return config;
5
6
  }
@@ -31,6 +32,7 @@ function getViteConfig(userViteConfig, inlineAstroConfig = {}) {
31
32
  let settings = await createSettings(config, userViteConfig.root);
32
33
  settings = await runHookConfigSetup({ settings, command: cmd, logger });
33
34
  const manifest = await createRouteManifest({ settings }, logger);
35
+ const devSSRManifest = createDevelopmentManifest(settings);
34
36
  const viteConfig = await createVite(
35
37
  {
36
38
  mode,
@@ -39,7 +41,7 @@ function getViteConfig(userViteConfig, inlineAstroConfig = {}) {
39
41
  astroContentListenPlugin({ settings, logger, fs })
40
42
  ]
41
43
  },
42
- { settings, logger, mode, sync: false, manifest }
44
+ { settings, logger, mode, sync: false, manifest, ssrManifest: devSSRManifest }
43
45
  );
44
46
  await runHookConfigDone({ settings, logger });
45
47
  return mergeConfig(viteConfig, userViteConfig);
@@ -52,12 +52,7 @@ export declare class App {
52
52
  set setManifestData(newManifestData: ManifestData);
53
53
  removeBase(pathname: string): string;
54
54
  match(request: Request): RouteData | undefined;
55
- render(request: Request, options?: RenderOptions): Promise<Response>;
56
- /**
57
- * @deprecated Instead of passing `RouteData` and locals individually, pass an object with `routeData` and `locals` properties.
58
- * See https://github.com/withastro/astro/pull/9199 for more information.
59
- */
60
- render(request: Request, routeData?: RouteData, locals?: object): Promise<Response>;
55
+ render(request: Request, renderOptions?: RenderOptions): Promise<Response>;
61
56
  setCookieHeaders(response: Response): Generator<string, string[], unknown>;
62
57
  /**
63
58
  * Reads all the cookies written by `Astro.cookie.set()` onto the passed response.
@@ -161,31 +161,15 @@ class App {
161
161
  }
162
162
  return pathname;
163
163
  }
164
- async render(request, routeDataOrOptions, maybeLocals) {
164
+ async render(request, renderOptions) {
165
165
  let routeData;
166
166
  let locals;
167
167
  let clientAddress;
168
168
  let addCookieHeader;
169
- if (routeDataOrOptions && ("addCookieHeader" in routeDataOrOptions || "clientAddress" in routeDataOrOptions || "locals" in routeDataOrOptions || "routeData" in routeDataOrOptions)) {
170
- if ("addCookieHeader" in routeDataOrOptions) {
171
- addCookieHeader = routeDataOrOptions.addCookieHeader;
172
- }
173
- if ("clientAddress" in routeDataOrOptions) {
174
- clientAddress = routeDataOrOptions.clientAddress;
175
- }
176
- if ("routeData" in routeDataOrOptions) {
177
- routeData = routeDataOrOptions.routeData;
178
- }
179
- if ("locals" in routeDataOrOptions) {
180
- locals = routeDataOrOptions.locals;
181
- }
182
- } else {
183
- routeData = routeDataOrOptions;
184
- locals = maybeLocals;
185
- if (routeDataOrOptions || locals) {
186
- this.#logRenderOptionsDeprecationWarning();
187
- }
188
- }
169
+ addCookieHeader = renderOptions?.addCookieHeader;
170
+ clientAddress = renderOptions?.clientAddress;
171
+ routeData = renderOptions?.routeData;
172
+ locals = renderOptions?.locals;
189
173
  if (routeData) {
190
174
  this.#logger.debug(
191
175
  "router",
@@ -254,14 +238,6 @@ class App {
254
238
  Reflect.set(response, responseSentSymbol, true);
255
239
  return response;
256
240
  }
257
- #logRenderOptionsDeprecationWarning() {
258
- if (this.#renderOptionsDeprecationWarningShown) return;
259
- this.#logger.warn(
260
- "deprecated",
261
- `The adapter ${this.#manifest.adapterName} is using a deprecated signature of the 'app.render()' method. From Astro 4.0, locals and routeData are provided as properties on an optional object to this method. Using the old signature will cause an error in Astro 5.0. See https://github.com/withastro/astro/pull/9199 for more information.`
262
- );
263
- this.#renderOptionsDeprecationWarningShown = true;
264
- }
265
241
  setCookieHeaders(response) {
266
242
  return getSetCookiesFromResponse(response);
267
243
  }
@@ -99,16 +99,6 @@ export declare function getPageDatasByClientOnlyID(internals: BuildInternals, vi
99
99
  * @param component The component of the page, used to identify the page
100
100
  */
101
101
  export declare function getPageData(internals: BuildInternals, route: string, component: string): PageBuildData | undefined;
102
- /**
103
- * Map internals.pagesByKeys to a new map with the public key instead of the internal key.
104
- * This function is only used to avoid breaking changes in the Integrations API, after we changed the way
105
- * we identify pages, from the entrypoint component to an internal key.
106
- * If the page component is unique -> the public key is the component path. (old behavior)
107
- * If the page component is shared -> the public key is the internal key. (new behavior)
108
- * The new behavior on shared entrypoint it's not a breaking change, because it was not supported before.
109
- * @param pagesByKeys A map of all page data by their internal key
110
- */
111
- export declare function getPageDatasWithPublicKey(pagesByKeys: Map<string, PageBuildData>): Map<string, PageBuildData>;
112
102
  export declare function getPageDataByViteID(internals: BuildInternals, viteid: ViteID): PageBuildData | undefined;
113
103
  export declare function hasPrerenderedPages(internals: BuildInternals): boolean;
114
104
  interface OrderInfo {
@@ -77,25 +77,6 @@ function getPageData(internals, route, component) {
77
77
  }
78
78
  return void 0;
79
79
  }
80
- function getPageDatasWithPublicKey(pagesByKeys) {
81
- const pagesWithPublicKey = /* @__PURE__ */ new Map();
82
- const pagesByComponentsArray = Array.from(pagesByKeys.values()).map((pageData) => {
83
- return { component: pageData.component, pageData };
84
- });
85
- const pagesWithUniqueComponent = pagesByComponentsArray.filter((page) => {
86
- return pagesByComponentsArray.filter((p) => p.component === page.component).length === 1;
87
- });
88
- pagesWithUniqueComponent.forEach((page) => {
89
- pagesWithPublicKey.set(page.component, page.pageData);
90
- });
91
- const pagesWithSharedComponent = pagesByComponentsArray.filter((page) => {
92
- return pagesByComponentsArray.filter((p) => p.component === page.component).length > 1;
93
- });
94
- pagesWithSharedComponent.forEach((page) => {
95
- pagesWithPublicKey.set(page.pageData.key, page.pageData);
96
- });
97
- return pagesWithPublicKey;
98
- }
99
80
  function getPageDataByViteID(internals, viteid) {
100
81
  if (internals.pagesByViteID.has(viteid)) {
101
82
  return internals.pagesByViteID.get(viteid);
@@ -148,7 +129,6 @@ export {
148
129
  getPageData,
149
130
  getPageDataByViteID,
150
131
  getPageDatasByClientOnlyID,
151
- getPageDatasWithPublicKey,
152
132
  hasPrerenderedPages,
153
133
  mergeInlineCss,
154
134
  trackClientOnlyPageDatas,
@@ -11,10 +11,7 @@ import {
11
11
  hasAnyContentFlag,
12
12
  reverseSymlink
13
13
  } from "../../content/utils.js";
14
- import {
15
- createBuildInternals,
16
- getPageDatasWithPublicKey
17
- } from "../../core/build/internal.js";
14
+ import { createBuildInternals } from "../../core/build/internal.js";
18
15
  import { emptyDir, removeEmptyDirs } from "../../core/fs/index.js";
19
16
  import { appendForwardSlash, prependForwardSlash, removeFileExtension } from "../../core/path.js";
20
17
  import { runHookBuildSetup } from "../../integrations/hooks.js";
@@ -221,7 +218,7 @@ async function ssrBuild(opts, internals, input, container, logger) {
221
218
  };
222
219
  const updatedViteBuildConfig = await runHookBuildSetup({
223
220
  config: settings.config,
224
- pages: getPageDatasWithPublicKey(internals.pagesByKeys),
221
+ pages: internals.pagesByKeys,
225
222
  vite: viteBuildConfig,
226
223
  target: "server",
227
224
  logger: opts.logger
@@ -269,7 +266,7 @@ ${bgGreen(black(" building client (vite) "))}`);
269
266
  };
270
267
  await runHookBuildSetup({
271
268
  config: settings.config,
272
- pages: getPageDatasWithPublicKey(internals.pagesByKeys),
269
+ pages: internals.pagesByKeys,
273
270
  vite: viteBuildConfig,
274
271
  target: "client",
275
272
  logger: opts.logger
@@ -276,7 +276,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
276
276
  themes: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodEnum<[import("shiki").BundledTheme, ...import("shiki").BundledTheme[]]>, z.ZodType<ShikiTheme, z.ZodTypeDef, ShikiTheme>]>>>;
277
277
  defaultColor: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"light">, z.ZodLiteral<"dark">, z.ZodString, z.ZodLiteral<false>]>>;
278
278
  wrap: z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodNull]>>;
279
- transformers: z.ZodDefault<z.ZodEffects<z.ZodArray<z.ZodType<ShikiTransformer, z.ZodTypeDef, ShikiTransformer>, "many">, ShikiTransformer[], ShikiTransformer[]>>;
279
+ transformers: z.ZodDefault<z.ZodArray<z.ZodType<ShikiTransformer, z.ZodTypeDef, ShikiTransformer>, "many">>;
280
280
  }, "strip", z.ZodTypeAny, {
281
281
  langs: ShikiLang[];
282
282
  theme: import("shiki").BundledTheme | ShikiTheme;
@@ -1152,7 +1152,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
1152
1152
  themes: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodEnum<[import("shiki").BundledTheme, ...import("shiki").BundledTheme[]]>, z.ZodType<ShikiTheme, z.ZodTypeDef, ShikiTheme>]>>>;
1153
1153
  defaultColor: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"light">, z.ZodLiteral<"dark">, z.ZodString, z.ZodLiteral<false>]>>;
1154
1154
  wrap: z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodNull]>>;
1155
- transformers: z.ZodDefault<z.ZodEffects<z.ZodArray<z.ZodType<ShikiTransformer, z.ZodTypeDef, ShikiTransformer>, "many">, ShikiTransformer[], ShikiTransformer[]>>;
1155
+ transformers: z.ZodDefault<z.ZodArray<z.ZodType<ShikiTransformer, z.ZodTypeDef, ShikiTransformer>, "many">>;
1156
1156
  }, "strip", z.ZodTypeAny, {
1157
1157
  langs: ShikiLang[];
1158
1158
  theme: import("shiki").BundledTheme | ShikiTheme;
@@ -183,14 +183,7 @@ const AstroConfigSchema = z.object({
183
183
  ).default(ASTRO_CONFIG_DEFAULTS.markdown.shikiConfig.themes),
184
184
  defaultColor: z.union([z.literal("light"), z.literal("dark"), z.string(), z.literal(false)]).optional(),
185
185
  wrap: z.boolean().or(z.null()).default(ASTRO_CONFIG_DEFAULTS.markdown.shikiConfig.wrap),
186
- transformers: z.custom().array().transform((transformers) => {
187
- for (const transformer of transformers) {
188
- if (transformer.token && !("span" in transformer)) {
189
- transformer.span = transformer.token;
190
- }
191
- }
192
- return transformers;
193
- }).default(ASTRO_CONFIG_DEFAULTS.markdown.shikiConfig.transformers)
186
+ transformers: z.custom().array().default(ASTRO_CONFIG_DEFAULTS.markdown.shikiConfig.transformers)
194
187
  }).default({}),
195
188
  remarkPlugins: z.union([
196
189
  z.string(),
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "5.0.0-alpha.7";
1
+ const ASTRO_VERSION = "5.0.0-beta.1";
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";
@@ -3,16 +3,20 @@ import * as vite from 'vite';
3
3
  import type { AstroSettings, ManifestData } from '../types/astro.js';
4
4
  import type { SSRManifest } from './app/types.js';
5
5
  import type { Logger } from './logger/core.js';
6
- interface CreateViteOptions {
6
+ type CreateViteOptions = {
7
7
  settings: AstroSettings;
8
8
  logger: Logger;
9
- mode: 'dev' | 'build' | string;
10
9
  command?: 'dev' | 'build';
11
10
  fs?: typeof nodeFs;
12
11
  sync: boolean;
13
12
  manifest: ManifestData;
13
+ } & ({
14
+ mode: 'dev';
15
+ ssrManifest: SSRManifest;
16
+ } | {
17
+ mode: 'build';
14
18
  ssrManifest?: SSRManifest;
15
- }
19
+ });
16
20
  /** Return a base vite config as a common starting point for all Vite commands. */
17
21
  export declare function createVite(commandConfig: vite.InlineConfig, { settings, logger, mode, command, fs, sync, manifest, ssrManifest }: CreateViteOptions): Promise<vite.InlineConfig>;
18
22
  export {};
@@ -101,7 +101,7 @@ async function createVite(commandConfig, { settings, logger, mode, command, fs =
101
101
  astroScriptsPlugin({ settings }),
102
102
  // The server plugin is for dev only and having it run during the build causes
103
103
  // the build to run very slow as the filewatcher is triggered often.
104
- mode !== "build" && vitePluginAstroServer({ settings, logger, fs, manifest, ssrManifest }),
104
+ mode === "dev" && vitePluginAstroServer({ settings, logger, fs, manifest, ssrManifest }),
105
105
  // ssrManifest is only required in dev mode, where it gets created before a Vite instance is created, and get passed to this function
106
106
  envVitePlugin({ settings }),
107
107
  astroEnv({ settings, mode, sync }),
@@ -22,7 +22,7 @@ async function dev(inlineConfig) {
22
22
  await telemetry.record([]);
23
23
  const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
24
24
  const logger = restart.container.logger;
25
- const currentVersion = "5.0.0-alpha.7";
25
+ const currentVersion = "5.0.0-beta.1";
26
26
  const isPrerelease = currentVersion.includes("-");
27
27
  if (!isPrerelease) {
28
28
  try {
@@ -367,7 +367,7 @@ export declare const AdapterSupportOutputMismatch: {
367
367
  /**
368
368
  * @docs
369
369
  * @see
370
- * - [Server-side Rendering](https://docs.astro.build/en/guides/server-side-rendering/)
370
+ * - [On-demand Rendering](https://5-0-0-beta.docs.astro.build/en/guides/on-demand-rendering/)
371
371
  * @description
372
372
  * To use server islands, the same constraints exist as for sever-side rendering, so an adapter is needed.
373
373
  */
@@ -752,6 +752,17 @@ export declare const LocalsNotAnObject: {
752
752
  message: string;
753
753
  hint: string;
754
754
  };
755
+ /**
756
+ * @docs
757
+ * @description
758
+ * Thrown when a value is being set as the `locals` field on the Astro global or context.
759
+ */
760
+ export declare const LocalsReassigned: {
761
+ name: string;
762
+ title: string;
763
+ message: string;
764
+ hint: string;
765
+ };
755
766
  /**
756
767
  * @docs
757
768
  * @description
@@ -1424,7 +1435,7 @@ export declare const UnsupportedConfigTransformError: {
1424
1435
  /**
1425
1436
  * @docs
1426
1437
  * @see
1427
- * - [On-demand rendering](https://docs.astro.build/en/basics/rendering-modes/#on-demand-rendered)
1438
+ * - [On-demand rendering](https://5-0-0-beta.docs.astro.build/en/guides/on-demand-rendering/)
1428
1439
  * @description
1429
1440
  * Your project must have a server output to create backend functions with Actions.
1430
1441
  */
@@ -117,7 +117,7 @@ const NoAdapterInstalledServerIslands = {
117
117
  name: "NoAdapterInstalledServerIslands",
118
118
  title: "Cannot use Server Islands without an adapter.",
119
119
  message: `Cannot use server islands without an adapter. Please install and configure the appropriate server adapter for your final deployment.`,
120
- hint: "See https://docs.astro.build/en/guides/server-side-rendering/ for more information."
120
+ hint: "See https://5-0-0-beta.docs.astro.build/en/guides/on-demand-rendering/ for more information."
121
121
  };
122
122
  const NoMatchingImport = {
123
123
  name: "NoMatchingImport",
@@ -263,6 +263,12 @@ const LocalsNotAnObject = {
263
263
  message: "`locals` can only be assigned to an object. Other values like numbers, strings, etc. are not accepted.",
264
264
  hint: "If you tried to remove some information from the `locals` object, try to use `delete` or set the property to `undefined`."
265
265
  };
266
+ const LocalsReassigned = {
267
+ name: "LocalsReassigned",
268
+ title: "`locals` must not be reassigned.",
269
+ message: "`locals` can not be assigned directly.",
270
+ hint: "Set a `locals` property instead."
271
+ };
266
272
  const AstroResponseHeadersReassigned = {
267
273
  name: "AstroResponseHeadersReassigned",
268
274
  title: "`Astro.response.headers` must not be reassigned.",
@@ -543,8 +549,8 @@ Full error: ${parseError}`,
543
549
  const ActionsWithoutServerOutputError = {
544
550
  name: "ActionsWithoutServerOutputError",
545
551
  title: "Actions must be used with server output.",
546
- 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.",
547
- hint: "Learn about on-demand rendering: https://docs.astro.build/en/basics/rendering-modes/#on-demand-rendered"
552
+ message: "A server is required to create callable backend functions. To deploy routes to a server, add an adapter to your Astro config and configure your route for on-demand rendering",
553
+ hint: "Add an adapter and enable on-demand rendering: https://5-0-0-beta.docs.astro.build/en/guides/on-demand-rendering/"
548
554
  };
549
555
  const ActionsReturnedInvalidDataError = {
550
556
  name: "ActionsReturnedInvalidDataError",
@@ -615,6 +621,7 @@ export {
615
621
  InvalidPrerenderExport,
616
622
  LocalImageUsedWrongly,
617
623
  LocalsNotAnObject,
624
+ LocalsReassigned,
618
625
  MarkdownFrontmatterParseError,
619
626
  MdxIntegrationMissingError,
620
627
  MiddlewareCantBeLoaded,
@@ -38,7 +38,7 @@ function serverStart({
38
38
  host,
39
39
  base
40
40
  }) {
41
- const version = "5.0.0-alpha.7";
41
+ const version = "5.0.0-beta.1";
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${"5.0.0-alpha.7"}`
273
+ `v${"5.0.0-beta.1"}`
274
274
  )} ${headline}`
275
275
  );
276
276
  }
@@ -69,13 +69,8 @@ function createContext({
69
69
  }
70
70
  return locals;
71
71
  },
72
- // We define a custom property, so we can check the value passed to locals
73
- set locals(val) {
74
- if (typeof val !== "object") {
75
- throw new AstroError(AstroErrorData.LocalsNotAnObject);
76
- } else {
77
- Reflect.set(request, clientLocalsSymbol, val);
78
- }
72
+ set locals(_) {
73
+ throw new AstroError(AstroErrorData.LocalsReassigned);
79
74
  }
80
75
  };
81
76
  return Object.assign(context, {
@@ -14,7 +14,6 @@ import {
14
14
  REWRITE_DIRECTIVE_HEADER_VALUE,
15
15
  ROUTE_TYPE_HEADER,
16
16
  clientAddressSymbol,
17
- clientLocalsSymbol,
18
17
  responseSentSymbol
19
18
  } from "./constants.js";
20
19
  import { AstroCookies, attachCookiesToResponse } from "./cookies/index.js";
@@ -224,14 +223,8 @@ class RenderContext {
224
223
  get locals() {
225
224
  return renderContext.locals;
226
225
  },
227
- // TODO(breaking): disallow replacing the locals object
228
- set locals(val) {
229
- if (typeof val !== "object") {
230
- throw new AstroError(AstroErrorData.LocalsNotAnObject);
231
- } else {
232
- renderContext.locals = val;
233
- Reflect.set(this.request, clientLocalsSymbol, val);
234
- }
226
+ set locals(_) {
227
+ throw new AstroError(AstroErrorData.LocalsReassigned);
235
228
  },
236
229
  params,
237
230
  get preferredLocale() {
@@ -43,18 +43,6 @@ document.addEventListener("DOMContentLoaded", async () => {
43
43
  customElements.define("astro-dev-toolbar-icon", DevToolbarIcon);
44
44
  customElements.define("astro-dev-toolbar-select", DevToolbarSelect);
45
45
  customElements.define("astro-dev-toolbar-radio-checkbox", DevToolbarRadioCheckbox);
46
- const deprecated = (Parent) => class extends Parent {
47
- };
48
- customElements.define("astro-dev-overlay", deprecated(AstroDevToolbar));
49
- customElements.define("astro-dev-overlay-window", deprecated(DevToolbarWindow));
50
- customElements.define("astro-dev-overlay-plugin-canvas", deprecated(DevToolbarCanvas));
51
- customElements.define("astro-dev-overlay-tooltip", deprecated(DevToolbarTooltip));
52
- customElements.define("astro-dev-overlay-highlight", deprecated(DevToolbarHighlight));
53
- customElements.define("astro-dev-overlay-card", deprecated(DevToolbarCard));
54
- customElements.define("astro-dev-overlay-toggle", deprecated(DevToolbarToggle));
55
- customElements.define("astro-dev-overlay-button", deprecated(DevToolbarButton));
56
- customElements.define("astro-dev-overlay-badge", deprecated(DevToolbarBadge));
57
- customElements.define("astro-dev-overlay-icon", deprecated(DevToolbarIcon));
58
46
  overlay = document.createElement("astro-dev-toolbar");
59
47
  const notificationLevels = ["error", "warning", "info"];
60
48
  const notificationSVGs = {
@@ -96,7 +84,6 @@ document.addEventListener("DOMContentLoaded", async () => {
96
84
  await overlay.setAppStatus(app, newState);
97
85
  };
98
86
  eventTarget.addEventListener("toggle-app", onToggleApp);
99
- eventTarget.addEventListener("toggle-plugin", onToggleApp);
100
87
  return app;
101
88
  };
102
89
  const astroMoreApp = {
@@ -7,11 +7,6 @@ const settings = getSettings();
7
7
  function getSettings() {
8
8
  let _settings = { ...defaultSettings };
9
9
  const toolbarSettings = localStorage.getItem("astro:dev-toolbar:settings");
10
- const oldSettings = localStorage.getItem("astro:dev-overlay:settings");
11
- if (oldSettings && !toolbarSettings) {
12
- localStorage.setItem("astro:dev-toolbar:settings", oldSettings);
13
- localStorage.removeItem("astro:dev-overlay:settings");
14
- }
15
10
  if (toolbarSettings) {
16
11
  _settings = { ..._settings, ...JSON.parse(toolbarSettings) };
17
12
  }
@@ -2,7 +2,6 @@ import { serverHelpers } from "./helpers.js";
2
2
  import { settings } from "./settings.js";
3
3
  import { getIconElement, isDefinedIcon } from "./ui-library/icons.js";
4
4
  const WS_EVENT_NAME = "astro-dev-toolbar";
5
- const WS_EVENT_NAME_DEPRECATED = "astro-dev-overlay";
6
5
  const HOVER_DELAY = 2 * 1e3;
7
6
  const DEVBAR_HITBOX_ABOVE = 42;
8
7
  class AstroDevToolbar extends HTMLElement {
@@ -344,7 +343,6 @@ class AstroDevToolbar extends HTMLElement {
344
343
  app.status = "ready";
345
344
  if (import.meta.hot) {
346
345
  import.meta.hot.send(`${WS_EVENT_NAME}:${app.id}:initialized`);
347
- import.meta.hot.send(`${WS_EVENT_NAME_DEPRECATED}:${app.id}:initialized`);
348
346
  }
349
347
  } catch (e) {
350
348
  console.error(`Failed to init app ${app.id}, error: ${e}`);
@@ -421,27 +419,15 @@ class AstroDevToolbar extends HTMLElement {
421
419
  appCanvas.style.display = "none";
422
420
  appCanvas.removeAttribute("data-active");
423
421
  }
424
- [
425
- "app-toggled",
426
- // Deprecated
427
- // TODO: Remove in Astro 5.0
428
- "plugin-toggled"
429
- ].forEach((eventName) => {
430
- app.eventTarget.dispatchEvent(
431
- new CustomEvent(eventName, {
432
- detail: {
433
- state: app.active,
434
- app
435
- }
436
- })
437
- );
438
- });
439
- if (import.meta.hot) {
440
- import.meta.hot.send(`${WS_EVENT_NAME}:${app.id}:toggled`, { state: app.active });
441
- import.meta.hot.send(`${WS_EVENT_NAME_DEPRECATED}:${app.id}:toggled`, {
442
- state: app.active
443
- });
444
- }
422
+ app.eventTarget.dispatchEvent(
423
+ new CustomEvent("app-toggled", {
424
+ detail: {
425
+ state: app.active,
426
+ app
427
+ }
428
+ })
429
+ );
430
+ import.meta.hot?.send(`${WS_EVENT_NAME}:${app.id}:toggled`, { state: app.active });
445
431
  return true;
446
432
  }
447
433
  isHidden() {
@@ -115,8 +115,6 @@ class DevToolbarButton extends HTMLElement {
115
115
  cursor: pointer;
116
116
  }
117
117
 
118
- /* TODO: Remove "astro-dev-overlay-icon" in Astro 5.0 */
119
- ::slotted(astro-dev-overlay-icon),
120
118
  ::slotted(astro-dev-toolbar-icon) {
121
119
  display: inline-block;
122
120
  height: 1em;
@@ -24,7 +24,10 @@ function astroTransitions({ settings }) {
24
24
  if (id === resolvedVirtualModuleId) {
25
25
  return `
26
26
  export * from "astro/virtual-modules/transitions.js";
27
- export { default as ViewTransitions } from "astro/components/ViewTransitions.astro";
27
+ export {
28
+ default as ViewTransitions,
29
+ default as ClientRouter
30
+ } from "astro/components/ClientRouter.astro";
28
31
  `;
29
32
  }
30
33
  if (id === resolvedVirtualClientModuleId) {
@@ -42,7 +45,7 @@ function astroTransitions({ settings }) {
42
45
  }
43
46
  },
44
47
  transform(code, id) {
45
- if (id.includes("ViewTransitions.astro") && id.endsWith(".ts")) {
48
+ if (id.includes("ClientRouter.astro") && id.endsWith(".ts")) {
46
49
  const prefetchDisabled = settings.config.prefetch === false;
47
50
  return code.replace("__PREFETCH_DISABLED__", JSON.stringify(prefetchDisabled));
48
51
  }
@@ -402,8 +402,8 @@ export interface AstroUserConfig {
402
402
  /**
403
403
  * @docs
404
404
  * @name security
405
- * @type {boolean}
406
- * @default `{}`
405
+ * @type {Record<"checkOrigin", boolean> | undefined}
406
+ * @default `{checkOrigin: true}`
407
407
  * @version 4.9.0
408
408
  * @description
409
409
  *
@@ -411,12 +411,16 @@ export interface AstroUserConfig {
411
411
  *
412
412
  * These features only exist for pages rendered on demand (SSR) using `server` mode or pages that opt out of prerendering in `static` mode.
413
413
  *
414
+ * By default, Astro will automatically check that the “origin” header
415
+ * matches the URL sent by each request in on-demand rendered pages. You can
416
+ * disable this behavior by setting `checkOrigin` to `false`:
417
+ *
414
418
  * ```js
415
419
  * // astro.config.mjs
416
420
  * export default defineConfig({
417
421
  * output: "server",
418
422
  * security: {
419
- * checkOrigin: true
423
+ * checkOrigin: false
420
424
  * }
421
425
  * })
422
426
  * ```
@@ -786,7 +790,7 @@ export interface AstroUserConfig {
786
790
  * @type {boolean | object}
787
791
  * @description
788
792
  * Enable prefetching for links on your site to provide faster page transitions.
789
- * (Enabled by default on pages using the `<ViewTransitions />` router. Set `prefetch: false` to opt out of this behaviour.)
793
+ * (Enabled by default on pages using the `<ClientRouter />` router. Set `prefetch: false` to opt out of this behaviour.)
790
794
  *
791
795
  * This configuration automatically adds a prefetch script to every page in the project
792
796
  * giving you access to the `data-astro-prefetch` attribute.
@@ -806,7 +810,7 @@ export interface AstroUserConfig {
806
810
  * @type {boolean}
807
811
  * @description
808
812
  * Enable prefetching for all links, including those without the `data-astro-prefetch` attribute.
809
- * This value defaults to `true` when using the `<ViewTransitions />` router. Otherwise, the default value is `false`.
813
+ * This value defaults to `true` when using the `<ClientRouter />` router. Otherwise, the default value is `false`.
810
814
  *
811
815
  * ```js
812
816
  * prefetch: {
@@ -1529,70 +1533,6 @@ export interface AstroUserConfig {
1529
1533
  * See the [Prefetch Guide](https://docs.astro.build/en/guides/prefetch/) for more `prefetch` options and usage.
1530
1534
  */
1531
1535
  clientPrerender?: boolean;
1532
- /**
1533
- * @docs
1534
- * @name experimental.serverIslands
1535
- * @type {boolean}
1536
- * @default `false`
1537
- * @version 4.12.0
1538
- * @description
1539
- *
1540
- * Enables experimental Server Island features.
1541
- * Server Islands offer the ability to defer a component to render asynchronously after the page has already rendered.
1542
- *
1543
- * To enable, configure an [on-demand server rendering `output` mode](https://docs.astro.build/en/basics/rendering-modes/#on-demand-rendered) with an adapter, and add the `serverIslands` flag to the `experimental` object:
1544
- *
1545
- * ```js
1546
- * {
1547
- * output: 'hybrid', // or 'server'
1548
- * adapter: nodejs({ mode: 'standalone' }),
1549
- * experimental: {
1550
- * serverIslands: true,
1551
- * },
1552
- * }
1553
- * ```
1554
- *
1555
- * Use the `server:defer` directive on any Astro component to delay initial rendering:
1556
- *
1557
- * ```astro "server:defer"
1558
- * ---
1559
- * import Avatar from '~/components/Avatar.astro';
1560
- * ---
1561
- * <Avatar server:defer />
1562
- * ```
1563
- *
1564
- * The outer page will be rendered, either at build time (`hybrid`) or at runtime (`server`) with the island content omitted and a `<script>` tag included in its place.
1565
- *
1566
- * After the page loads in the browser, the script tag will replace itself with the the contents of the island by making a request.
1567
- *
1568
- * Any Astro component can be given the `server: defer` attribute to delay its rendering. There is no special API and you can write `.astro` code as normal:
1569
- *
1570
- * ```astro
1571
- * ---
1572
- * import { getUser } from '../api';
1573
- *
1574
- * const user = await getUser(Astro.locals.userId);
1575
- * ---
1576
- * <img class="avatar" src={user.imageUrl}>
1577
- * ```
1578
- *
1579
- * #### Server island fallback content
1580
- *
1581
- * Since your component will not render with the rest of the page, you may want to add generic content (e.g. a loading message) to temporarily show in its place. This content will be displayed when the page first renders but before the island has loaded.
1582
- *
1583
- * Add placeholder content as a child of your Astro component with the `slot="fallback"` attribute. When your island content is available, the fallback content will be replaced.
1584
- *
1585
- * The example below displays a generic avatar as fallback content, then animates into a personalized avatar using view transitions:
1586
- *
1587
- * ```astro
1588
- * <Avatar server:defer>
1589
- * <svg slot="fallback" class="generic-avatar" transition:name="avatar">...</svg>
1590
- * </Avatar>
1591
- * ```
1592
- *
1593
- * For a complete overview, and to give feedback on this experimental API, see the [Server Islands RFC](https://github.com/withastro/roadmap/pull/963).
1594
- */
1595
- serverIslands?: boolean;
1596
1536
  /**
1597
1537
  * @docs
1598
1538
  * @name experimental.contentIntellisense
@@ -141,7 +141,7 @@ export interface BaseIntegrationHooks {
141
141
  injectScript: (stage: InjectedScriptStage, content: string) => void;
142
142
  injectRoute: (injectRoute: InjectedRoute) => void;
143
143
  addClientDirective: (directive: ClientDirectiveConfig) => void;
144
- addDevToolbarApp: (entrypoint: DevToolbarAppEntry | string) => void;
144
+ addDevToolbarApp: (entrypoint: DevToolbarAppEntry) => void;
145
145
  addMiddleware: (mid: AstroIntegrationMiddleware) => void;
146
146
  logger: AstroIntegrationLogger;
147
147
  }) => void | Promise<void>;
@@ -27,34 +27,10 @@ export type DevToolbarAppEntry = DevToolbarAppMeta & {
27
27
  entrypoint: string;
28
28
  };
29
29
  export type DevToolbarApp = {
30
- /**
31
- * @deprecated The `id`, `name`, and `icon` properties should now be defined when using `addDevToolbarApp`.
32
- *
33
- * Ex: `addDevToolbarApp({ id: 'my-app', name: 'My App', icon: '🚀', entrypoint: '/path/to/app' })`
34
- *
35
- * In the future, putting these properties directly on the app object will be removed.
36
- */
37
- id?: string;
38
- /**
39
- * @deprecated The `id`, `name`, and `icon` properties should now be defined when using `addDevToolbarApp`.
40
- *
41
- * Ex: `addDevToolbarApp({ id: 'my-app', name: 'My App', icon: '🚀', entrypoint: '/path/to/app' })`
42
- *
43
- * In the future, putting these properties directly on the app object will be removed.
44
- */
45
- name?: string;
46
- /**
47
- * @deprecated The `id`, `name`, and `icon` properties should now be defined when using `addDevToolbarApp`.
48
- *
49
- * Ex: `addDevToolbarApp({ id: 'my-app', name: 'My App', icon: '🚀', entrypoint: '/path/to/app' })`
50
- *
51
- * In the future, putting these properties directly on the app object will be removed.
52
- */
53
- icon?: Icon;
54
30
  init?(canvas: ShadowRoot, app: ToolbarAppEventTarget, server: ToolbarServerHelpers): void | Promise<void>;
55
31
  beforeTogglingOff?(canvas: ShadowRoot): boolean | Promise<boolean>;
56
32
  };
57
- export type ResolvedDevToolbarApp = DevToolbarAppMeta & Omit<DevToolbarApp, 'id' | 'name' | 'icon'>;
33
+ export type ResolvedDevToolbarApp = DevToolbarAppMeta & DevToolbarApp;
58
34
  export type DevToolbarMetadata = Window & typeof globalThis & {
59
35
  __astro_dev_toolbar__: {
60
36
  root: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "5.0.0-alpha.7",
3
+ "version": "5.0.0-beta.1",
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",
@@ -147,7 +147,7 @@
147
147
  "ora": "^8.1.0",
148
148
  "p-limit": "^6.1.0",
149
149
  "p-queue": "^8.0.1",
150
- "path-to-regexp": "^6.2.2",
150
+ "path-to-regexp": "6.2.2",
151
151
  "preferred-pm": "^4.0.0",
152
152
  "prompts": "^2.4.2",
153
153
  "rehype": "^13.0.1",
@@ -168,7 +168,7 @@
168
168
  "zod-to-json-schema": "^3.23.2",
169
169
  "zod-to-ts": "^1.2.0",
170
170
  "@astrojs/internal-helpers": "0.4.1",
171
- "@astrojs/markdown-remark": "6.0.0-alpha.1",
171
+ "@astrojs/markdown-remark": "6.0.0-beta.1",
172
172
  "@astrojs/telemetry": "3.1.0"
173
173
  },
174
174
  "optionalDependencies": {
@@ -209,6 +209,7 @@
209
209
  "sass": "^1.78.0",
210
210
  "undici": "^6.19.8",
211
211
  "unified": "^11.0.5",
212
+ "vitest": "^2.1.1",
212
213
  "astro-scripts": "0.0.14"
213
214
  },
214
215
  "engines": {
@@ -27,5 +27,7 @@
27
27
  "allowJs": true,
28
28
  // Allow JSX files (or files that are internally considered JSX, like Astro files) to be imported inside `.js` and `.ts` files.
29
29
  "jsx": "preserve"
30
- }
30
+ },
31
+ "exclude": ["${configDir}/dist"],
32
+ "include": ["${configDir}/.astro/types.d.ts", "${configDir}/**/*"]
31
33
  }