astro 5.4.1 → 5.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/client.d.ts +2 -2
  2. package/components/Debug.astro +3 -2
  3. package/dist/actions/consts.d.ts +2 -2
  4. package/dist/actions/consts.js +4 -4
  5. package/dist/actions/integration.js +1 -5
  6. package/dist/actions/loadActions.d.ts +8 -0
  7. package/dist/actions/loadActions.js +13 -0
  8. package/dist/actions/plugins.d.ts +8 -0
  9. package/dist/actions/plugins.js +24 -5
  10. package/dist/actions/runtime/virtual/server.d.ts +2 -2
  11. package/dist/actions/runtime/virtual/server.js +1 -2
  12. package/dist/actions/runtime/virtual/shared.d.ts +2 -0
  13. package/dist/actions/runtime/virtual/shared.js +8 -1
  14. package/dist/assets/utils/imageKind.d.ts +18 -0
  15. package/dist/assets/utils/imageKind.js +5 -1
  16. package/dist/assets/utils/index.d.ts +6 -1
  17. package/dist/assets/utils/index.js +0 -2
  18. package/dist/assets/utils/metadata.d.ts +8 -0
  19. package/dist/assets/utils/metadata.js +16 -15
  20. package/dist/assets/utils/node/emitAsset.d.ts +9 -0
  21. package/dist/assets/utils/node/emitAsset.js +1 -1
  22. package/dist/assets/utils/queryParams.d.ts +9 -0
  23. package/dist/assets/utils/remoteProbe.d.ts +7 -0
  24. package/dist/assets/utils/transformToPath.d.ts +30 -0
  25. package/dist/cli/add/index.js +44 -73
  26. package/dist/cli/install-package.d.ts +0 -6
  27. package/dist/cli/install-package.js +17 -54
  28. package/dist/content/content-layer.js +3 -3
  29. package/dist/content/runtime.js +2 -1
  30. package/dist/core/app/types.d.ts +6 -0
  31. package/dist/core/base-pipeline.d.ts +9 -1
  32. package/dist/core/base-pipeline.js +40 -1
  33. package/dist/core/build/generate.js +5 -3
  34. package/dist/core/build/internal.d.ts +2 -1
  35. package/dist/core/build/internal.js +3 -1
  36. package/dist/core/build/plugins/index.js +2 -0
  37. package/dist/core/build/plugins/plugin-actions.d.ts +4 -0
  38. package/dist/core/build/plugins/plugin-actions.js +16 -0
  39. package/dist/core/build/plugins/plugin-css.js +1 -27
  40. package/dist/core/build/plugins/plugin-middleware.d.ts +0 -1
  41. package/dist/core/build/plugins/plugin-middleware.js +0 -2
  42. package/dist/core/build/plugins/plugin-ssr.js +4 -1
  43. package/dist/core/build/static-build.js +9 -1
  44. package/dist/core/constants.js +1 -1
  45. package/dist/core/dev/dev.js +1 -1
  46. package/dist/core/errors/errors-data.d.ts +11 -0
  47. package/dist/core/errors/errors-data.js +6 -0
  48. package/dist/core/messages.js +6 -5
  49. package/dist/core/render-context.d.ts +7 -5
  50. package/dist/core/render-context.js +28 -13
  51. package/dist/transitions/router.js +5 -2
  52. package/dist/transitions/swap-functions.d.ts +1 -0
  53. package/dist/transitions/swap-functions.js +15 -11
  54. package/dist/vite-plugin-astro/index.d.ts +2 -2
  55. package/dist/vite-plugin-astro/index.js +3 -9
  56. package/dist/vite-plugin-astro/types.d.ts +0 -20
  57. package/dist/vite-plugin-astro-server/pipeline.d.ts +0 -1
  58. package/dist/vite-plugin-astro-server/pipeline.js +0 -10
  59. package/dist/vite-plugin-astro-server/plugin.js +1 -1
  60. package/dist/vite-plugin-astro-server/route.js +5 -1
  61. package/package.json +18 -19
  62. package/templates/actions.mjs +8 -4
  63. package/dist/actions/runtime/middleware.d.ts +0 -1
  64. package/dist/actions/runtime/middleware.js +0 -14
  65. package/dist/actions/runtime/virtual/get-action.d.ts +0 -8
  66. package/dist/actions/runtime/virtual/get-action.js +0 -29
@@ -5,12 +5,6 @@ type GetPackageOptions = {
5
5
  cwd?: string;
6
6
  };
7
7
  export declare function getPackage<T>(packageName: string, logger: Logger, options: GetPackageOptions, otherDeps?: string[]): Promise<T | undefined>;
8
- /**
9
- * Get the command to execute and download a package (e.g. `npx`, `yarn dlx`, `pnpm dlx`, etc.)
10
- * @param packageManager - Optional package manager to use. If not provided, Astro will attempt to detect the preferred package manager.
11
- * @returns The command to execute and download a package
12
- */
13
- export declare function getExecCommand(packageManager?: string): Promise<string>;
14
8
  export declare function fetchPackageJson(scope: string | undefined, name: string, tag: string): Promise<Record<string, any> | Error>;
15
9
  export declare function fetchPackageVersions(packageName: string): Promise<string[] | Error>;
16
10
  export {};
@@ -2,9 +2,8 @@ import { createRequire } from "node:module";
2
2
  import boxen from "boxen";
3
3
  import ci from "ci-info";
4
4
  import { bold, cyan, dim, magenta } from "kleur/colors";
5
- import preferredPM from "preferred-pm";
5
+ import { detect, resolveCommand } from "package-manager-detector";
6
6
  import prompts from "prompts";
7
- import whichPm from "which-pm";
8
7
  import yoctoSpinner from "yocto-spinner";
9
8
  import { exec } from "./exec.js";
10
9
  const require2 = createRequire(import.meta.url);
@@ -34,48 +33,17 @@ async function getPackage(packageName, logger, options, otherDeps = []) {
34
33
  }
35
34
  }
36
35
  }
37
- function getInstallCommand(packages, packageManager) {
38
- switch (packageManager) {
39
- case "npm":
40
- return { pm: "npm", command: "install", flags: [], dependencies: packages };
41
- case "yarn":
42
- return { pm: "yarn", command: "add", flags: [], dependencies: packages };
43
- case "pnpm":
44
- return { pm: "pnpm", command: "add", flags: [], dependencies: packages };
45
- case "bun":
46
- return { pm: "bun", command: "add", flags: [], dependencies: packages };
47
- default:
48
- return null;
49
- }
50
- }
51
- async function getExecCommand(packageManager) {
52
- if (!packageManager) {
53
- packageManager = (await preferredPM(process.cwd()))?.name ?? "npm";
54
- }
55
- switch (packageManager) {
56
- case "npm":
57
- return "npx";
58
- case "yarn":
59
- return "yarn dlx";
60
- case "pnpm":
61
- return "pnpm dlx";
62
- case "bun":
63
- return "bunx";
64
- default:
65
- return "npx";
66
- }
67
- }
68
36
  async function installPackage(packageNames, options, logger) {
69
37
  const cwd = options.cwd ?? process.cwd();
70
- const packageManager = (await whichPm(cwd))?.name ?? "npm";
71
- const installCommand = getInstallCommand(packageNames, packageManager);
72
- if (!installCommand) {
73
- return false;
74
- }
75
- const coloredOutput = `${bold(installCommand.pm)} ${installCommand.command}${[
76
- "",
77
- ...installCommand.flags
78
- ].join(" ")} ${cyan(installCommand.dependencies.join(" "))}`;
38
+ const packageManager = await detect({
39
+ cwd,
40
+ // Include the `install-metadata` strategy to have the package manager that's
41
+ // used for installation take precedence
42
+ strategies: ["install-metadata", "lockfile", "packageManager-field"]
43
+ });
44
+ const installCommand = resolveCommand(packageManager?.agent ?? "npm", "add", []);
45
+ if (!installCommand) return false;
46
+ const coloredOutput = `${bold(installCommand.command)} ${installCommand.args.join(" ")} ${cyan(packageNames.join(" "))}`;
79
47
  const message = `
80
48
  ${boxen(coloredOutput, {
81
49
  margin: 0.5,
@@ -106,17 +74,13 @@ ${message}`
106
74
  if (Boolean(response)) {
107
75
  const spinner = yoctoSpinner({ text: "Installing dependencies..." }).start();
108
76
  try {
109
- await exec(
110
- installCommand.pm,
111
- [installCommand.command, ...installCommand.flags, ...installCommand.dependencies],
112
- {
113
- nodeOptions: {
114
- cwd,
115
- // reset NODE_ENV to ensure install command run in dev mode
116
- env: { NODE_ENV: void 0 }
117
- }
77
+ await exec(installCommand.command, [...installCommand.args, ...packageNames], {
78
+ nodeOptions: {
79
+ cwd,
80
+ // reset NODE_ENV to ensure install command run in dev mode
81
+ env: { NODE_ENV: void 0 }
118
82
  }
119
- );
83
+ });
120
84
  spinner.success();
121
85
  return true;
122
86
  } catch (err) {
@@ -157,7 +121,7 @@ let _registry;
157
121
  async function getRegistry() {
158
122
  if (_registry) return _registry;
159
123
  const fallback = "https://registry.npmjs.org";
160
- const packageManager = (await preferredPM(process.cwd()))?.name || "npm";
124
+ const packageManager = (await detect())?.name || "npm";
161
125
  try {
162
126
  const { stdout } = await exec(packageManager, ["config", "get", "registry"]);
163
127
  _registry = stdout.trim()?.replace(/\/$/, "") || fallback;
@@ -170,6 +134,5 @@ async function getRegistry() {
170
134
  export {
171
135
  fetchPackageJson,
172
136
  fetchPackageVersions,
173
- getExecCommand,
174
137
  getPackage
175
138
  };
@@ -153,7 +153,7 @@ ${contentConfig.error.message}`);
153
153
  logger.info("Content config changed");
154
154
  shouldClear = true;
155
155
  }
156
- if (previousAstroVersion && previousAstroVersion !== "5.4.1") {
156
+ if (previousAstroVersion && previousAstroVersion !== "5.4.3") {
157
157
  logger.info("Astro version changed");
158
158
  shouldClear = true;
159
159
  }
@@ -161,8 +161,8 @@ ${contentConfig.error.message}`);
161
161
  logger.info("Clearing content store");
162
162
  this.#store.clearAll();
163
163
  }
164
- if ("5.4.1") {
165
- await this.#store.metaStore().set("astro-version", "5.4.1");
164
+ if ("5.4.3") {
165
+ await this.#store.metaStore().set("astro-version", "5.4.3");
166
166
  }
167
167
  if (currentConfigDigest) {
168
168
  await this.#store.metaStore().set("content-config-digest", currentConfigDigest);
@@ -1,3 +1,4 @@
1
+ import { escape } from "html-escaper";
1
2
  import { Traverse } from "neotraverse/modern";
2
3
  import pLimit from "p-limit";
3
4
  import { ZodIssueCode, z } from "zod";
@@ -324,7 +325,7 @@ async function updateImageReferencesInBody(html, fileName) {
324
325
  ...attributes,
325
326
  src: image.src,
326
327
  srcset: image.srcSet.attribute
327
- }).map(([key, value]) => value ? `${key}=${JSON.stringify(String(value))}` : "").join(" ");
328
+ }).map(([key, value]) => value ? `${key}="${escape(value)}"` : "").join(" ");
328
329
  });
329
330
  }
330
331
  function updateImageReferencesInData(data, fileName, imageAssetMap) {
@@ -1,3 +1,5 @@
1
+ import type { ZodType } from 'zod';
2
+ import type { ActionAccept, ActionClient } from '../../actions/runtime/virtual/server.js';
1
3
  import type { RoutingStrategies } from '../../i18n/utils.js';
2
4
  import type { ComponentInstance, SerializedRouteData } from '../../types/astro.js';
3
5
  import type { AstroMiddlewareInstance } from '../../types/public/common.js';
@@ -65,6 +67,7 @@ export type SSRManifest = {
65
67
  key: Promise<CryptoKey>;
66
68
  i18n: SSRManifestI18n | undefined;
67
69
  middleware?: () => Promise<AstroMiddlewareInstance> | AstroMiddlewareInstance;
70
+ actions?: SSRActions;
68
71
  checkOrigin: boolean;
69
72
  sessionConfig?: ResolvedSessionConfig<any>;
70
73
  cacheDir: string | URL;
@@ -74,6 +77,9 @@ export type SSRManifest = {
74
77
  buildClientDir: string | URL;
75
78
  buildServerDir: string | URL;
76
79
  };
80
+ export type SSRActions = {
81
+ server: Record<string, ActionClient<unknown, ActionAccept, ZodType>>;
82
+ };
77
83
  export type SSRManifestI18n = {
78
84
  fallback: Record<string, string> | undefined;
79
85
  fallbackType: 'redirect' | 'rewrite';
@@ -1,7 +1,10 @@
1
+ import type { ZodType } from 'zod';
2
+ import type { ActionAccept, ActionClient } from '../actions/runtime/virtual/server.js';
1
3
  import type { ComponentInstance } from '../types/astro.js';
2
4
  import type { MiddlewareHandler, RewritePayload } from '../types/public/common.js';
3
5
  import type { RuntimeMode } from '../types/public/config.js';
4
6
  import type { RouteData, SSRLoadedRenderer, SSRManifest, SSRResult } from '../types/public/internal.js';
7
+ import type { SSRActions } from './app/types.js';
5
8
  import type { Logger } from './logger/core.js';
6
9
  import { RouteCache } from './render/route-cache.js';
7
10
  /**
@@ -48,8 +51,10 @@ export declare abstract class Pipeline {
48
51
  route: string;
49
52
  component: string;
50
53
  }[];
54
+ readonly actions: SSRActions | undefined;
51
55
  readonly internalMiddleware: MiddlewareHandler[];
52
56
  resolvedMiddleware: MiddlewareHandler | undefined;
57
+ resolvedActions: SSRActions | undefined;
53
58
  constructor(logger: Logger, manifest: SSRManifest,
54
59
  /**
55
60
  * "development" or "production" only
@@ -76,7 +81,7 @@ export declare abstract class Pipeline {
76
81
  matchesComponent(filePath: URL): boolean;
77
82
  route: string;
78
83
  component: string;
79
- }[]);
84
+ }[], actions?: SSRActions | undefined);
80
85
  abstract headElements(routeData: RouteData): Promise<HeadElements> | HeadElements;
81
86
  abstract componentMetadata(routeData: RouteData): Promise<SSRResult['componentMetadata']> | void;
82
87
  /**
@@ -100,6 +105,9 @@ export declare abstract class Pipeline {
100
105
  * it returns a no-op function
101
106
  */
102
107
  getMiddleware(): Promise<MiddlewareHandler>;
108
+ setActions(actions: SSRActions): void;
109
+ getActions(): Promise<SSRActions>;
110
+ getAction(path: string): Promise<ActionClient<unknown, ActionAccept, ZodType>>;
103
111
  }
104
112
  export interface HeadElements extends Pick<SSRResult, 'scripts' | 'styles' | 'links'> {
105
113
  }
@@ -1,11 +1,13 @@
1
1
  import { createI18nMiddleware } from "../i18n/middleware.js";
2
2
  import { createOriginCheckMiddleware } from "./app/middlewares.js";
3
+ import { ActionNotFoundError } from "./errors/errors-data.js";
4
+ import { AstroError } from "./errors/index.js";
3
5
  import { NOOP_MIDDLEWARE_FN } from "./middleware/noop-middleware.js";
4
6
  import { sequence } from "./middleware/sequence.js";
5
7
  import { RouteCache } from "./render/route-cache.js";
6
8
  import { createDefaultRoutes } from "./routing/default.js";
7
9
  class Pipeline {
8
- constructor(logger, manifest, runtimeMode, renderers, resolve, serverLike, streaming, adapterName = manifest.adapterName, clientDirectives = manifest.clientDirectives, inlinedScripts = manifest.inlinedScripts, compressHTML = manifest.compressHTML, i18n = manifest.i18n, middleware = manifest.middleware, routeCache = new RouteCache(logger, runtimeMode), site = manifest.site ? new URL(manifest.site) : void 0, defaultRoutes = createDefaultRoutes(manifest)) {
10
+ constructor(logger, manifest, runtimeMode, renderers, resolve, serverLike, streaming, adapterName = manifest.adapterName, clientDirectives = manifest.clientDirectives, inlinedScripts = manifest.inlinedScripts, compressHTML = manifest.compressHTML, i18n = manifest.i18n, middleware = manifest.middleware, routeCache = new RouteCache(logger, runtimeMode), site = manifest.site ? new URL(manifest.site) : void 0, defaultRoutes = createDefaultRoutes(manifest), actions = manifest.actions) {
9
11
  this.logger = logger;
10
12
  this.manifest = manifest;
11
13
  this.runtimeMode = runtimeMode;
@@ -22,6 +24,7 @@ class Pipeline {
22
24
  this.routeCache = routeCache;
23
25
  this.site = site;
24
26
  this.defaultRoutes = defaultRoutes;
27
+ this.actions = actions;
25
28
  this.internalMiddleware = [];
26
29
  if (i18n?.strategy !== "manual") {
27
30
  this.internalMiddleware.push(
@@ -31,6 +34,7 @@ class Pipeline {
31
34
  }
32
35
  internalMiddleware;
33
36
  resolvedMiddleware = void 0;
37
+ resolvedActions = void 0;
34
38
  /**
35
39
  * Resolves the middleware from the manifest, and returns the `onRequest` function. If `onRequest` isn't there,
36
40
  * it returns a no-op function
@@ -52,6 +56,41 @@ class Pipeline {
52
56
  return this.resolvedMiddleware;
53
57
  }
54
58
  }
59
+ setActions(actions) {
60
+ this.resolvedActions = actions;
61
+ }
62
+ async getActions() {
63
+ if (this.resolvedActions) {
64
+ return this.resolvedActions;
65
+ } else if (this.actions) {
66
+ return this.actions;
67
+ }
68
+ return { server: {} };
69
+ }
70
+ async getAction(path) {
71
+ const pathKeys = path.split(".").map((key) => decodeURIComponent(key));
72
+ let { server } = await this.getActions();
73
+ if (!server || !(typeof server === "object")) {
74
+ throw new TypeError(
75
+ `Expected \`server\` export in actions file to be an object. Received ${typeof server}.`
76
+ );
77
+ }
78
+ for (const key of pathKeys) {
79
+ if (!(key in server)) {
80
+ throw new AstroError({
81
+ ...ActionNotFoundError,
82
+ message: ActionNotFoundError.message(pathKeys.join("."))
83
+ });
84
+ }
85
+ server = server[key];
86
+ }
87
+ if (typeof server !== "function") {
88
+ throw new TypeError(
89
+ `Expected handler for action ${pathKeys.join(".")} to be a function. Received ${typeof server}.`
90
+ );
91
+ }
92
+ return server;
93
+ }
55
94
  }
56
95
  export {
57
96
  Pipeline
@@ -44,11 +44,13 @@ async function generatePages(options, internals) {
44
44
  const renderersEntryUrl = new URL("renderers.mjs", baseDirectory);
45
45
  const renderers = await import(renderersEntryUrl.toString());
46
46
  const middleware = internals.middlewareEntryPoint ? await import(internals.middlewareEntryPoint.toString()).then((mod) => mod.onRequest) : NOOP_MIDDLEWARE_FN;
47
+ const actions = internals.astroActionsEntryPoint ? await import(internals.astroActionsEntryPoint.toString()).then((mod) => mod) : { server: {} };
47
48
  manifest = createBuildManifest(
48
49
  options.settings,
49
50
  internals,
50
51
  renderers.renderers,
51
52
  middleware,
53
+ actions,
52
54
  options.key
53
55
  );
54
56
  }
@@ -270,8 +272,7 @@ function getUrlForPath(pathname, base, origin, format, trailingSlash, routeType)
270
272
  const buildPathRelative = removeTrailingForwardSlash(removeLeadingForwardSlash(pathname)) + ending;
271
273
  buildPathname = joinPaths(base, buildPathRelative);
272
274
  }
273
- const url = new URL(buildPathname, origin);
274
- return url;
275
+ return new URL(buildPathname, origin);
275
276
  }
276
277
  async function generatePath(pathname, pipeline, gopts, route) {
277
278
  const { mod } = gopts;
@@ -358,7 +359,7 @@ function getPrettyRouteName(route) {
358
359
  }
359
360
  return route.component;
360
361
  }
361
- function createBuildManifest(settings, internals, renderers, middleware, key) {
362
+ function createBuildManifest(settings, internals, renderers, middleware, actions, key) {
362
363
  let i18nManifest = void 0;
363
364
  if (settings.config.i18n) {
364
365
  i18nManifest = {
@@ -399,6 +400,7 @@ function createBuildManifest(settings, internals, renderers, middleware, key) {
399
400
  onRequest: middleware
400
401
  };
401
402
  },
403
+ actions,
402
404
  checkOrigin: (settings.config.security?.checkOrigin && settings.buildOutput === "server") ?? false,
403
405
  key
404
406
  };
@@ -69,7 +69,8 @@ export interface BuildInternals {
69
69
  manifestFileName?: string;
70
70
  entryPoints: Map<RouteData, URL>;
71
71
  componentMetadata: SSRResult['componentMetadata'];
72
- middlewareEntryPoint?: URL;
72
+ middlewareEntryPoint: URL | undefined;
73
+ astroActionsEntryPoint: URL | undefined;
73
74
  /**
74
75
  * Chunks in the bundle that are only used in prerendering that we can delete later
75
76
  */
@@ -17,7 +17,9 @@ function createBuildInternals() {
17
17
  staticFiles: /* @__PURE__ */ new Set(),
18
18
  componentMetadata: /* @__PURE__ */ new Map(),
19
19
  entryPoints: /* @__PURE__ */ new Map(),
20
- prerenderOnlyChunks: []
20
+ prerenderOnlyChunks: [],
21
+ astroActionsEntryPoint: void 0,
22
+ middlewareEntryPoint: void 0
21
23
  };
22
24
  }
23
25
  function trackPageData(internals, _component, pageData, componentModuleId, componentURL) {
@@ -1,5 +1,6 @@
1
1
  import { astroConfigBuildPlugin } from "../../../content/vite-plugin-content-assets.js";
2
2
  import { astroHeadBuildPlugin } from "../../../vite-plugin-head/index.js";
3
+ import { pluginActions } from "./plugin-actions.js";
3
4
  import { pluginAnalyzer } from "./plugin-analyzer.js";
4
5
  import { pluginChunks } from "./plugin-chunks.js";
5
6
  import { pluginComponentEntry } from "./plugin-component-entry.js";
@@ -19,6 +20,7 @@ function registerAllPlugins({ internals, options, register }) {
19
20
  register(pluginManifest(options, internals));
20
21
  register(pluginRenderers(options));
21
22
  register(pluginMiddleware(options, internals));
23
+ register(pluginActions(options, internals));
22
24
  register(pluginPages(options, internals));
23
25
  register(pluginCSS(options, internals));
24
26
  register(astroHeadBuildPlugin(internals));
@@ -0,0 +1,4 @@
1
+ import type { BuildInternals } from '../internal.js';
2
+ import type { AstroBuildPlugin } from '../plugin.js';
3
+ import type { StaticBuildOptions } from '../types.js';
4
+ export declare function pluginActions(opts: StaticBuildOptions, internals: BuildInternals): AstroBuildPlugin;
@@ -0,0 +1,16 @@
1
+ import { vitePluginActionsBuild } from "../../../actions/plugins.js";
2
+ function pluginActions(opts, internals) {
3
+ return {
4
+ targets: ["server"],
5
+ hooks: {
6
+ "build:before": () => {
7
+ return {
8
+ vitePlugin: vitePluginActionsBuild(opts, internals)
9
+ };
10
+ }
11
+ }
12
+ };
13
+ }
14
+ export {
15
+ pluginActions
16
+ };
@@ -101,22 +101,6 @@ function rollupPluginAstroBuildCSS(options) {
101
101
  }
102
102
  }
103
103
  };
104
- const cssScopeToPlugin = {
105
- name: "astro:rollup-plugin-css-scope-to",
106
- renderChunk(_, chunk, __, meta) {
107
- for (const id in chunk.modules) {
108
- const modMeta = this.getModuleInfo(id)?.meta;
109
- const cssScopeTo = modMeta?.astroCss?.cssScopeTo;
110
- if (cssScopeTo && !isCssScopeToRendered(cssScopeTo, Object.values(meta.chunks))) {
111
- delete chunk.modules[id];
112
- const moduleIdsIndex = chunk.moduleIds.indexOf(id);
113
- if (moduleIdsIndex > -1) {
114
- chunk.moduleIds.splice(moduleIdsIndex, 1);
115
- }
116
- }
117
- }
118
- }
119
- };
120
104
  const singleCssPlugin = {
121
105
  name: "astro:rollup-plugin-single-css",
122
106
  enforce: "post",
@@ -178,7 +162,7 @@ function rollupPluginAstroBuildCSS(options) {
178
162
  });
179
163
  }
180
164
  };
181
- return [cssBuildPlugin, cssScopeToPlugin, singleCssPlugin, inlineStylesheetsPlugin];
165
+ return [cssBuildPlugin, singleCssPlugin, inlineStylesheetsPlugin];
182
166
  }
183
167
  function* getParentClientOnlys(id, ctx, internals) {
184
168
  for (const info of getParentModuleInfos(id, ctx)) {
@@ -203,16 +187,6 @@ function appendCSSToPage(pageData, meta, pagesToCss, depth, order) {
203
187
  }
204
188
  }
205
189
  }
206
- function isCssScopeToRendered(cssScopeTo, chunks) {
207
- for (const moduleId in cssScopeTo) {
208
- const exports = cssScopeTo[moduleId];
209
- const renderedModule = chunks.find((c) => c.moduleIds.includes(moduleId))?.modules[moduleId];
210
- if (renderedModule?.renderedExports.some((e) => exports.includes(e))) {
211
- return true;
212
- }
213
- }
214
- return false;
215
- }
216
190
  export {
217
191
  pluginCSS
218
192
  };
@@ -1,5 +1,4 @@
1
1
  import type { BuildInternals } from '../internal.js';
2
2
  import type { AstroBuildPlugin } from '../plugin.js';
3
3
  import type { StaticBuildOptions } from '../types.js';
4
- export { MIDDLEWARE_MODULE_ID } from '../../middleware/vite-plugin.js';
5
4
  export declare function pluginMiddleware(opts: StaticBuildOptions, internals: BuildInternals): AstroBuildPlugin;
@@ -1,5 +1,4 @@
1
1
  import { vitePluginMiddlewareBuild } from "../../middleware/vite-plugin.js";
2
- import { MIDDLEWARE_MODULE_ID } from "../../middleware/vite-plugin.js";
3
2
  function pluginMiddleware(opts, internals) {
4
3
  return {
5
4
  targets: ["server"],
@@ -13,6 +12,5 @@ function pluginMiddleware(opts, internals) {
13
12
  };
14
13
  }
15
14
  export {
16
- MIDDLEWARE_MODULE_ID,
17
15
  pluginMiddleware
18
16
  };
@@ -1,8 +1,9 @@
1
+ import { ASTRO_ACTIONS_INTERNAL_MODULE_ID } from "../../../actions/consts.js";
2
+ import { MIDDLEWARE_MODULE_ID } from "../../middleware/vite-plugin.js";
1
3
  import { routeIsRedirect } from "../../redirects/index.js";
2
4
  import { VIRTUAL_ISLAND_MAP_ID } from "../../server-islands/vite-plugin-server-islands.js";
3
5
  import { addRollupInput } from "../add-rollup-input.js";
4
6
  import { SSR_MANIFEST_VIRTUAL_MODULE_ID } from "./plugin-manifest.js";
5
- import { MIDDLEWARE_MODULE_ID } from "./plugin-middleware.js";
6
7
  import { ASTRO_PAGE_MODULE_ID } from "./plugin-pages.js";
7
8
  import { RENDERERS_MODULE_ID } from "./plugin-renderers.js";
8
9
  import { getVirtualModulePageName } from "./util.js";
@@ -138,6 +139,7 @@ function generateSSRCode(adapter, middlewareId) {
138
139
  const edgeMiddleware = adapter?.adapterFeatures?.edgeMiddleware ?? false;
139
140
  const imports = [
140
141
  `import { renderers } from '${RENDERERS_MODULE_ID}';`,
142
+ `import * as actions from '${ASTRO_ACTIONS_INTERNAL_MODULE_ID}';`,
141
143
  `import * as serverEntrypointModule from '${ADAPTER_VIRTUAL_MODULE_ID}';`,
142
144
  `import { manifest as defaultManifest } from '${SSR_MANIFEST_VIRTUAL_MODULE_ID}';`,
143
145
  `import { serverIslandMap } from '${VIRTUAL_ISLAND_MAP_ID}';`
@@ -148,6 +150,7 @@ function generateSSRCode(adapter, middlewareId) {
148
150
  ` pageMap,`,
149
151
  ` serverIslandMap,`,
150
152
  ` renderers,`,
153
+ ` actions,`,
151
154
  ` middleware: ${edgeMiddleware ? "undefined" : `() => import("${middlewareId}")`}`,
152
155
  `});`,
153
156
  `const _args = ${adapter.args ? JSON.stringify(adapter.args, null, 4) : "undefined"};`,
@@ -137,7 +137,15 @@ async function ssrBuild(opts, internals, input, container) {
137
137
  const encoded = encodeName(name);
138
138
  return [prefix, encoded, suffix].join("");
139
139
  },
140
- assetFileNames: `${settings.config.build.assets}/[name].[hash][extname]`,
140
+ assetFileNames(chunkInfo) {
141
+ const { names } = chunkInfo;
142
+ const name = names[0] ?? "";
143
+ if (name.includes(ASTRO_PAGE_EXTENSION_POST_PATTERN)) {
144
+ const [sanitizedName] = name.split(ASTRO_PAGE_EXTENSION_POST_PATTERN);
145
+ return `${settings.config.build.assets}/${sanitizedName}.[hash][extname]`;
146
+ }
147
+ return `${settings.config.build.assets}/[name].[hash][extname]`;
148
+ },
141
149
  ...viteConfig.build?.rollupOptions?.output,
142
150
  entryFileNames(chunkInfo) {
143
151
  if (chunkInfo.facadeModuleId?.startsWith(ASTRO_PAGE_RESOLVED_MODULE_ID)) {
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "5.4.1";
1
+ const ASTRO_VERSION = "5.4.3";
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";
@@ -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.4.1";
25
+ const currentVersion = "5.4.3";
26
26
  const isPrerelease = currentVersion.includes("-");
27
27
  if (!isPrerelease) {
28
28
  try {
@@ -1593,6 +1593,17 @@ export declare const UnknownError: {
1593
1593
  name: string;
1594
1594
  title: string;
1595
1595
  };
1596
+ /**
1597
+ * @docs
1598
+ * @description
1599
+ * Thrown in development mode when the actions file can't be loaded.
1600
+ *
1601
+ */
1602
+ export declare const ActionsCantBeLoaded: {
1603
+ name: string;
1604
+ title: string;
1605
+ message: string;
1606
+ };
1596
1607
  /**
1597
1608
  * @docs
1598
1609
  * @kind heading
@@ -633,6 +633,11 @@ const ActionCalledFromServerError = {
633
633
  hint: "See the `Astro.callAction()` reference for usage examples: https://docs.astro.build/en/reference/api-reference/#callaction"
634
634
  };
635
635
  const UnknownError = { name: "UnknownError", title: "Unknown Error." };
636
+ const ActionsCantBeLoaded = {
637
+ name: "ActionsCantBeLoaded",
638
+ title: "Can't load the Astro actions.",
639
+ message: "An unknown error was thrown while loading the Astro actions file."
640
+ };
636
641
  const SessionWithoutSupportedAdapterOutputError = {
637
642
  name: "SessionWithoutSupportedAdapterOutputError",
638
643
  title: "Sessions cannot be used with an adapter that doesn't support server output.",
@@ -666,6 +671,7 @@ const SessionConfigWithoutFlagError = {
666
671
  export {
667
672
  ActionCalledFromServerError,
668
673
  ActionNotFoundError,
674
+ ActionsCantBeLoaded,
669
675
  ActionsReturnedInvalidDataError,
670
676
  ActionsWithoutServerOutputError,
671
677
  AdapterSupportOutputMismatch,
@@ -14,7 +14,7 @@ import {
14
14
  underline,
15
15
  yellow
16
16
  } from "kleur/colors";
17
- import { getExecCommand } from "../cli/install-package.js";
17
+ import { detect, resolveCommand } from "package-manager-detector";
18
18
  import { getDocsForError, renderErrorMarkdown } from "./errors/dev/utils.js";
19
19
  import {
20
20
  AstroError,
@@ -38,7 +38,7 @@ function serverStart({
38
38
  host,
39
39
  base
40
40
  }) {
41
- const version = "5.4.1";
41
+ const version = "5.4.3";
42
42
  const localPrefix = `${dim("\u2503")} Local `;
43
43
  const networkPrefix = `${dim("\u2503")} Network `;
44
44
  const emptyPrefix = " ".repeat(11);
@@ -74,8 +74,9 @@ function serverShortcuts({ key, label }) {
74
74
  async function newVersionAvailable({ latestVersion }) {
75
75
  const badge = bgYellow(black(` update `));
76
76
  const headline = yellow(`\u25B6 New version of Astro available: ${latestVersion}`);
77
- const execCommand = await getExecCommand();
78
- const details = ` Run ${cyan(`${execCommand} @astrojs/upgrade`)} to update`;
77
+ const packageManager = (await detect())?.agent ?? "npm";
78
+ const execCommand = resolveCommand(packageManager, "execute", ["@astrojs/upgrade"]);
79
+ const details = !execCommand ? "" : ` Run ${cyan(`${execCommand.command} ${execCommand.args.join(" ")}`)} to update`;
79
80
  return ["", `${badge} ${headline}`, details, ""].join("\n");
80
81
  }
81
82
  function telemetryNotice() {
@@ -281,7 +282,7 @@ function printHelp({
281
282
  message.push(
282
283
  linebreak(),
283
284
  ` ${bgGreen(black(` ${commandName} `))} ${green(
284
- `v${"5.4.1"}`
285
+ `v${"5.4.3"}`
285
286
  )} ${headline}`
286
287
  );
287
288
  }
@@ -3,6 +3,7 @@ import type { ComponentInstance } from '../types/astro.js';
3
3
  import type { MiddlewareHandler, Props } from '../types/public/common.js';
4
4
  import type { APIContext, AstroGlobal, AstroGlobalPartial } from '../types/public/context.js';
5
5
  import type { RouteData, SSRResult } from '../types/public/internal.js';
6
+ import type { SSRActions } from './app/types.js';
6
7
  import { AstroCookies } from './cookies/index.js';
7
8
  import { type Pipeline } from './render/index.js';
8
9
  import { AstroSession } from './session.js';
@@ -16,6 +17,7 @@ export declare class RenderContext {
16
17
  readonly pipeline: Pipeline;
17
18
  locals: App.Locals;
18
19
  readonly middleware: MiddlewareHandler;
20
+ readonly actions: SSRActions;
19
21
  pathname: string;
20
22
  request: Request;
21
23
  routeData: RouteData;
@@ -36,7 +38,7 @@ export declare class RenderContext {
36
38
  * A safety net in case of loops
37
39
  */
38
40
  counter: number;
39
- static create({ locals, middleware, pathname, pipeline, request, routeData, clientAddress, status, props, partial, }: Pick<RenderContext, 'pathname' | 'pipeline' | 'request' | 'routeData' | 'clientAddress'> & Partial<Pick<RenderContext, 'locals' | 'middleware' | 'status' | 'props' | 'partial'>>): Promise<RenderContext>;
41
+ static create({ locals, middleware, pathname, pipeline, request, routeData, clientAddress, status, props, partial, actions, }: Pick<RenderContext, 'pathname' | 'pipeline' | 'request' | 'routeData' | 'clientAddress'> & Partial<Pick<RenderContext, 'locals' | 'middleware' | 'status' | 'props' | 'partial' | 'actions'>>): Promise<RenderContext>;
40
42
  /**
41
43
  * The main function of the RenderContext.
42
44
  *
@@ -49,9 +51,9 @@ export declare class RenderContext {
49
51
  * - fallback
50
52
  */
51
53
  render(componentInstance: ComponentInstance | undefined, slots?: Record<string, any>): Promise<Response>;
52
- createAPIContext(props: APIContext['props']): APIContext;
54
+ createAPIContext(props: APIContext['props'], context: ActionAPIContext): APIContext;
53
55
  createActionAPIContext(): ActionAPIContext;
54
- createResult(mod: ComponentInstance): Promise<SSRResult>;
56
+ createResult(mod: ComponentInstance, ctx: ActionAPIContext): Promise<SSRResult>;
55
57
  /**
56
58
  * The Astro global is sourced in 3 different phases:
57
59
  * - **Static**: `.generator` and `.glob` is printed by the compiler, instantiated once per process per astro file
@@ -60,8 +62,8 @@ export declare class RenderContext {
60
62
  *
61
63
  * The page level partial is used as the prototype of the user-visible `Astro` global object, which is instantiated once per use of a component.
62
64
  */
63
- createAstro(result: SSRResult, astroStaticPartial: AstroGlobalPartial, props: Record<string, any>, slotValues: Record<string, any> | null): AstroGlobal;
64
- createAstroPagePartial(result: SSRResult, astroStaticPartial: AstroGlobalPartial): Omit<AstroGlobal, 'props' | 'self' | 'slots'>;
65
+ createAstro(result: SSRResult, astroStaticPartial: AstroGlobalPartial, props: Record<string, any>, slotValues: Record<string, any> | null, apiContext: ActionAPIContext): AstroGlobal;
66
+ createAstroPagePartial(result: SSRResult, astroStaticPartial: AstroGlobalPartial, apiContext: ActionAPIContext): Omit<AstroGlobal, 'props' | 'self' | 'slots'>;
65
67
  getClientAddress(): string;
66
68
  computeCurrentLocale(): string | undefined;
67
69
  computePreferredLocale(): string | undefined;