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
package/client.d.ts CHANGED
@@ -193,14 +193,14 @@ declare module 'astro:config/server' {
193
193
  // biome-ignore format: bug
194
194
  type ServerConfigSerialized = import('./dist/types/public/manifest.js').ServerDeserializedManifest;
195
195
  const manifest: ServerConfigSerialized;
196
- export default manifest;
196
+ export = manifest;
197
197
  }
198
198
 
199
199
  declare module 'astro:config/client' {
200
200
  // biome-ignore format: bug
201
201
  type ClientConfigSerialized = import('./dist/types/public/manifest.js').ClientDeserializedManifest;
202
202
  const manifest: ClientConfigSerialized;
203
- export default manifest;
203
+ export = manifest;
204
204
  }
205
205
 
206
206
  declare module 'astro:components' {
@@ -21,8 +21,9 @@ const value = Astro.props[key];
21
21
  font-size: 14px;
22
22
  padding: 1rem 1.5rem;
23
23
  background: white;
24
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
25
- 'Open Sans', 'Helvetica Neue', sans-serif;
24
+ font-family:
25
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans',
26
+ 'Helvetica Neue', sans-serif;
26
27
  }
27
28
 
28
29
  .astro-debug-header,
@@ -1,8 +1,8 @@
1
1
  export declare const VIRTUAL_MODULE_ID = "astro:actions";
2
2
  export declare const RESOLVED_VIRTUAL_MODULE_ID: string;
3
3
  export declare const ACTIONS_TYPES_FILE = "actions.d.ts";
4
- export declare const VIRTUAL_INTERNAL_MODULE_ID = "astro:internal-actions";
5
- export declare const RESOLVED_VIRTUAL_INTERNAL_MODULE_ID = "\0astro:internal-actions";
4
+ export declare const ASTRO_ACTIONS_INTERNAL_MODULE_ID = "astro-internal:actions";
5
+ export declare const RESOLVED_ASTRO_ACTIONS_INTERNAL_MODULE_ID: string;
6
6
  export declare const NOOP_ACTIONS = "\0noop-actions";
7
7
  export declare const ACTION_QUERY_PARAMS: {
8
8
  actionName: string;
@@ -1,8 +1,8 @@
1
1
  const VIRTUAL_MODULE_ID = "astro:actions";
2
2
  const RESOLVED_VIRTUAL_MODULE_ID = "\0" + VIRTUAL_MODULE_ID;
3
3
  const ACTIONS_TYPES_FILE = "actions.d.ts";
4
- const VIRTUAL_INTERNAL_MODULE_ID = "astro:internal-actions";
5
- const RESOLVED_VIRTUAL_INTERNAL_MODULE_ID = "\0astro:internal-actions";
4
+ const ASTRO_ACTIONS_INTERNAL_MODULE_ID = "astro-internal:actions";
5
+ const RESOLVED_ASTRO_ACTIONS_INTERNAL_MODULE_ID = "\0" + ASTRO_ACTIONS_INTERNAL_MODULE_ID;
6
6
  const NOOP_ACTIONS = "\0noop-actions";
7
7
  const ACTION_QUERY_PARAMS = {
8
8
  actionName: "_action",
@@ -13,9 +13,9 @@ export {
13
13
  ACTIONS_TYPES_FILE,
14
14
  ACTION_QUERY_PARAMS,
15
15
  ACTION_RPC_ROUTE_PATTERN,
16
+ ASTRO_ACTIONS_INTERNAL_MODULE_ID,
16
17
  NOOP_ACTIONS,
17
- RESOLVED_VIRTUAL_INTERNAL_MODULE_ID,
18
+ RESOLVED_ASTRO_ACTIONS_INTERNAL_MODULE_ID,
18
19
  RESOLVED_VIRTUAL_MODULE_ID,
19
- VIRTUAL_INTERNAL_MODULE_ID,
20
20
  VIRTUAL_MODULE_ID
21
21
  };
@@ -8,17 +8,13 @@ function astroIntegrationActionsRouteHandler({
8
8
  return {
9
9
  name: VIRTUAL_MODULE_ID,
10
10
  hooks: {
11
- async "astro:config:setup"(params) {
11
+ async "astro:config:setup"() {
12
12
  settings.injectedRoutes.push({
13
13
  pattern: ACTION_RPC_ROUTE_PATTERN,
14
14
  entrypoint: "astro/actions/runtime/route.js",
15
15
  prerender: false,
16
16
  origin: "internal"
17
17
  });
18
- params.addMiddleware({
19
- entrypoint: "astro/actions/runtime/middleware.js",
20
- order: "post"
21
- });
22
18
  },
23
19
  "astro:config:done": async (params) => {
24
20
  if (params.buildOutput === "static") {
@@ -0,0 +1,8 @@
1
+ import type { SSRActions } from '../core/app/types.js';
2
+ import type { ModuleLoader } from '../core/module-loader/index.js';
3
+ /**
4
+ * It accepts a module loader and the astro settings, and it attempts to load the middlewares defined in the configuration.
5
+ *
6
+ * If not middlewares were not set, the function returns an empty array.
7
+ */
8
+ export declare function loadActions(moduleLoader: ModuleLoader): Promise<SSRActions>;
@@ -0,0 +1,13 @@
1
+ import { ActionsCantBeLoaded } from "../core/errors/errors-data.js";
2
+ import { AstroError } from "../core/errors/index.js";
3
+ import { ASTRO_ACTIONS_INTERNAL_MODULE_ID } from "./consts.js";
4
+ async function loadActions(moduleLoader) {
5
+ try {
6
+ return await moduleLoader.import(ASTRO_ACTIONS_INTERNAL_MODULE_ID);
7
+ } catch (error) {
8
+ throw new AstroError(ActionsCantBeLoaded, { cause: error });
9
+ }
10
+ }
11
+ export {
12
+ loadActions
13
+ };
@@ -1,5 +1,7 @@
1
1
  import type fsMod from 'node:fs';
2
2
  import type { Plugin as VitePlugin } from 'vite';
3
+ import type { BuildInternals } from '../core/build/internal.js';
4
+ import type { StaticBuildOptions } from '../core/build/types.js';
3
5
  import type { AstroSettings } from '../types/astro.js';
4
6
  /**
5
7
  * This plugin is responsible to load the known file `actions/index.js` / `actions.js`
@@ -9,6 +11,12 @@ import type { AstroSettings } from '../types/astro.js';
9
11
  export declare function vitePluginUserActions({ settings }: {
10
12
  settings: AstroSettings;
11
13
  }): VitePlugin;
14
+ /**
15
+ * This plugin is used to retrieve the final entry point of the bundled actions.ts file
16
+ * @param opts
17
+ * @param internals
18
+ */
19
+ export declare function vitePluginActionsBuild(opts: StaticBuildOptions, internals: BuildInternals): VitePlugin;
12
20
  export declare function vitePluginActions({ fs, settings, }: {
13
21
  fs: typeof fsMod;
14
22
  settings: AstroSettings;
@@ -1,9 +1,11 @@
1
+ import { addRollupInput } from "../core/build/add-rollup-input.js";
1
2
  import { shouldAppendForwardSlash } from "../core/build/util.js";
3
+ import { getOutputDirectory } from "../prerender/utils.js";
2
4
  import {
5
+ ASTRO_ACTIONS_INTERNAL_MODULE_ID,
3
6
  NOOP_ACTIONS,
4
- RESOLVED_VIRTUAL_INTERNAL_MODULE_ID,
7
+ RESOLVED_ASTRO_ACTIONS_INTERNAL_MODULE_ID,
5
8
  RESOLVED_VIRTUAL_MODULE_ID,
6
- VIRTUAL_INTERNAL_MODULE_ID,
7
9
  VIRTUAL_MODULE_ID
8
10
  } from "./consts.js";
9
11
  import { isActionsFilePresent } from "./utils.js";
@@ -15,7 +17,7 @@ function vitePluginUserActions({ settings }) {
15
17
  if (id === NOOP_ACTIONS) {
16
18
  return NOOP_ACTIONS;
17
19
  }
18
- if (id === VIRTUAL_INTERNAL_MODULE_ID) {
20
+ if (id === ASTRO_ACTIONS_INTERNAL_MODULE_ID) {
19
21
  const resolvedModule = await this.resolve(
20
22
  `${decodeURI(new URL("actions", settings.config.srcDir).pathname)}`
21
23
  );
@@ -23,18 +25,34 @@ function vitePluginUserActions({ settings }) {
23
25
  return NOOP_ACTIONS;
24
26
  }
25
27
  resolvedActionsId = resolvedModule.id;
26
- return RESOLVED_VIRTUAL_INTERNAL_MODULE_ID;
28
+ return RESOLVED_ASTRO_ACTIONS_INTERNAL_MODULE_ID;
27
29
  }
28
30
  },
29
31
  load(id) {
30
32
  if (id === NOOP_ACTIONS) {
31
33
  return "export const server = {}";
32
- } else if (id === RESOLVED_VIRTUAL_INTERNAL_MODULE_ID) {
34
+ } else if (id === RESOLVED_ASTRO_ACTIONS_INTERNAL_MODULE_ID) {
33
35
  return `export { server } from '${resolvedActionsId}';`;
34
36
  }
35
37
  }
36
38
  };
37
39
  }
40
+ function vitePluginActionsBuild(opts, internals) {
41
+ return {
42
+ name: "@astro/plugin-actions-build",
43
+ options(options) {
44
+ return addRollupInput(options, [ASTRO_ACTIONS_INTERNAL_MODULE_ID]);
45
+ },
46
+ writeBundle(_, bundle) {
47
+ for (const [chunkName, chunk] of Object.entries(bundle)) {
48
+ if (chunk.type !== "asset" && chunk.facadeModuleId === RESOLVED_ASTRO_ACTIONS_INTERNAL_MODULE_ID) {
49
+ const outputDirectory = getOutputDirectory(opts.settings);
50
+ internals.astroActionsEntryPoint = new URL(chunkName, outputDirectory);
51
+ }
52
+ }
53
+ }
54
+ };
55
+ }
38
56
  function vitePluginActions({
39
57
  fs,
40
58
  settings
@@ -83,5 +101,6 @@ export * from 'astro/actions/runtime/virtual/client.js';`;
83
101
  }
84
102
  export {
85
103
  vitePluginActions,
104
+ vitePluginActionsBuild,
86
105
  vitePluginUserActions
87
106
  };
@@ -19,7 +19,7 @@ export declare function defineAction<TOutput, TAccept extends ActionAccept | und
19
19
  }): ActionClient<TOutput, TAccept, TInputSchema> & string;
20
20
  /** Transform form data to an object based on a Zod schema. */
21
21
  export declare function formDataToObject<T extends z.AnyZodObject>(formData: FormData, schema: T): Record<string, unknown>;
22
- export type ActionMiddlewareContext = {
22
+ export type AstroActionContext = {
23
23
  /** Information about an incoming action request. */
24
24
  action?: {
25
25
  /** Whether an action was called using an RPC function or by using an HTML form action. */
@@ -47,4 +47,4 @@ export type ActionMiddlewareContext = {
47
47
  /**
48
48
  * Access information about Action requests from middleware.
49
49
  */
50
- export declare function getActionContext(context: APIContext): ActionMiddlewareContext;
50
+ export declare function getActionContext(context: APIContext): AstroActionContext;
@@ -11,7 +11,6 @@ import {
11
11
  hasContentType,
12
12
  isActionAPIContext
13
13
  } from "../utils.js";
14
- import { getAction } from "./get-action.js";
15
14
  import {
16
15
  ACTION_QUERY_PARAMS,
17
16
  ActionError,
@@ -151,7 +150,7 @@ function getActionContext(context) {
151
150
  pipeline.manifest.trailingSlash,
152
151
  pipeline.manifest.buildFormat
153
152
  ) ? removeTrailingForwardSlash(callerInfo.name) : callerInfo.name;
154
- const baseAction = await getAction(callerInfoName);
153
+ const baseAction = await pipeline.getAction(callerInfoName);
155
154
  let input;
156
155
  try {
157
156
  input = await parseRequestBody(context.request);
@@ -1,4 +1,5 @@
1
1
  import type { z } from 'zod';
2
+ import { AstroError } from '../../../core/errors/errors.js';
2
3
  import { appendForwardSlash as _appendForwardSlash } from '../../../core/path.js';
3
4
  import type { ErrorInferenceObject, MaybePromise, ActionAPIContext as _ActionAPIContext } from '../utils.js';
4
5
  export type ActionAPIContext = _ActionAPIContext;
@@ -56,3 +57,4 @@ export type SerializedActionResult = {
56
57
  };
57
58
  export declare function serializeActionResult(res: SafeResult<any, any>): SerializedActionResult;
58
59
  export declare function deserializeActionResult(res: SerializedActionResult): SafeResult<any, any>;
60
+ export declare function astroCalledServerError(): AstroError;
@@ -1,6 +1,9 @@
1
1
  import { parse as devalueParse, stringify as devalueStringify } from "devalue";
2
2
  import { REDIRECT_STATUS_CODES } from "../../../core/constants.js";
3
- import { ActionsReturnedInvalidDataError } from "../../../core/errors/errors-data.js";
3
+ import {
4
+ ActionCalledFromServerError,
5
+ ActionsReturnedInvalidDataError
6
+ } from "../../../core/errors/errors-data.js";
4
7
  import { AstroError } from "../../../core/errors/errors.js";
5
8
  import { appendForwardSlash as _appendForwardSlash } from "../../../core/path.js";
6
9
  import { ACTION_QUERY_PARAMS as _ACTION_QUERY_PARAMS } from "../../consts.js";
@@ -224,12 +227,16 @@ const actionResultErrorStack = /* @__PURE__ */ function actionResultErrorStackFn
224
227
  }
225
228
  };
226
229
  }();
230
+ function astroCalledServerError() {
231
+ return new AstroError(ActionCalledFromServerError);
232
+ }
227
233
  export {
228
234
  ACTION_ERROR_CODES,
229
235
  ACTION_QUERY_PARAMS,
230
236
  ActionError,
231
237
  ActionInputError,
232
238
  appendForwardSlash,
239
+ astroCalledServerError,
233
240
  callSafely,
234
241
  deserializeActionResult,
235
242
  getActionQueryString,
@@ -1,4 +1,22 @@
1
1
  import type { ImageMetadata, UnresolvedImageTransform } from '../types.js';
2
+ /**
3
+ * Determines if the given source is an ECMAScript Module (ESM) imported image.
4
+ *
5
+ * @param {ImageMetadata | string} src - The source to check. It can be an `ImageMetadata` object or a string.
6
+ * @return {boolean} Returns `true` if the source is an `ImageMetadata` object, otherwise `false`.
7
+ */
2
8
  export declare function isESMImportedImage(src: ImageMetadata | string): src is ImageMetadata;
9
+ /**
10
+ * Determines if the provided source is a remote image URL in the form of a string.
11
+ *
12
+ * @param {ImageMetadata | string} src - The source to check, which can either be an `ImageMetadata` object or a string.
13
+ * @return {boolean} Returns `true` if the source is a string, otherwise `false`.
14
+ */
3
15
  export declare function isRemoteImage(src: ImageMetadata | string): src is string;
16
+ /**
17
+ * Resolves the source of an image transformation by handling asynchronous or synchronous inputs.
18
+ *
19
+ * @param {UnresolvedImageTransform['src']} src - The source of the image transformation.
20
+ * @return {Promise<string | ImageMetadata>} A promise that resolves to the image source. It returns either the default export of the resolved source or the resolved source itself if the default export doesn't exist.
21
+ */
4
22
  export declare function resolveSrc(src: UnresolvedImageTransform['src']): Promise<string | ImageMetadata>;
@@ -5,7 +5,11 @@ function isRemoteImage(src) {
5
5
  return typeof src === "string";
6
6
  }
7
7
  async function resolveSrc(src) {
8
- return typeof src === "object" && "then" in src ? (await src).default ?? await src : src;
8
+ if (typeof src === "object" && "then" in src) {
9
+ const resource = await src;
10
+ return resource.default ?? resource;
11
+ }
12
+ return src;
9
13
  }
10
14
  export {
11
15
  isESMImportedImage,
@@ -1,8 +1,13 @@
1
+ /**
2
+ * NOTE: this is a public module exposed to the user, so all functions exposed
3
+ * here must be documented via JsDoc and in the docs website.
4
+ *
5
+ * If some functions don't need to be exposed, just import the file that contains the functions.
6
+ */
1
7
  export { emitESMImage } from './node/emitAsset.js';
2
8
  export { isESMImportedImage, isRemoteImage } from './imageKind.js';
3
9
  export { imageMetadata } from './metadata.js';
4
10
  export { getOrigQueryParams } from './queryParams.js';
5
11
  export { hashTransform, propsToFilename } from './transformToPath.js';
6
12
  export { inferRemoteSize } from './remoteProbe.js';
7
- export { makeSvgComponent } from './svg.js';
8
13
  export { isRemoteAllowed, matchHostname, matchPathname, matchPattern, matchPort, matchProtocol, type RemotePattern, } from './remotePattern.js';
@@ -4,7 +4,6 @@ import { imageMetadata } from "./metadata.js";
4
4
  import { getOrigQueryParams } from "./queryParams.js";
5
5
  import { hashTransform, propsToFilename } from "./transformToPath.js";
6
6
  import { inferRemoteSize } from "./remoteProbe.js";
7
- import { makeSvgComponent } from "./svg.js";
8
7
  import {
9
8
  isRemoteAllowed,
10
9
  matchHostname,
@@ -22,7 +21,6 @@ export {
22
21
  isESMImportedImage,
23
22
  isRemoteAllowed,
24
23
  isRemoteImage,
25
- makeSvgComponent,
26
24
  matchHostname,
27
25
  matchPathname,
28
26
  matchPattern,
@@ -1,2 +1,10 @@
1
1
  import type { ImageMetadata } from '../types.js';
2
+ /**
3
+ * Extracts image metadata such as dimensions, format, and orientation from the provided image data.
4
+ *
5
+ * @param {Uint8Array} data - The binary data of the image.
6
+ * @param {string} [src] - The source path or URL of the image, used for error messages. Optional.
7
+ * @return {Promise<Omit<ImageMetadata, 'src' | 'fsPath'>>} A promise that resolves with the extracted metadata, excluding `src` and `fsPath`.
8
+ * @throws {AstroError} Throws an error if the image metadata cannot be extracted.
9
+ */
2
10
  export declare function imageMetadata(data: Uint8Array, src?: string): Promise<Omit<ImageMetadata, 'src' | 'fsPath'>>;
@@ -1,28 +1,29 @@
1
1
  import { AstroError, AstroErrorData } from "../../core/errors/index.js";
2
2
  import { lookup as probe } from "../utils/vendor/image-size/lookup.js";
3
3
  async function imageMetadata(data, src) {
4
+ let result;
4
5
  try {
5
- const result = probe(data);
6
- if (!result.height || !result.width || !result.type) {
7
- throw new AstroError({
8
- ...AstroErrorData.NoImageMetadata,
9
- message: AstroErrorData.NoImageMetadata.message(src)
10
- });
11
- }
12
- const { width, height, type, orientation } = result;
13
- const isPortrait = (orientation || 0) >= 5;
14
- return {
15
- width: isPortrait ? height : width,
16
- height: isPortrait ? width : height,
17
- format: type,
18
- orientation
19
- };
6
+ result = probe(data);
20
7
  } catch {
21
8
  throw new AstroError({
22
9
  ...AstroErrorData.NoImageMetadata,
23
10
  message: AstroErrorData.NoImageMetadata.message(src)
24
11
  });
25
12
  }
13
+ if (!result.height || !result.width || !result.type) {
14
+ throw new AstroError({
15
+ ...AstroErrorData.NoImageMetadata,
16
+ message: AstroErrorData.NoImageMetadata.message(src)
17
+ });
18
+ }
19
+ const { width, height, type, orientation } = result;
20
+ const isPortrait = (orientation || 0) >= 5;
21
+ return {
22
+ width: isPortrait ? height : width,
23
+ height: isPortrait ? width : height,
24
+ format: type,
25
+ orientation
26
+ };
26
27
  }
27
28
  export {
28
29
  imageMetadata
@@ -4,6 +4,15 @@ type FileEmitter = vite.Rollup.EmitFile;
4
4
  type ImageMetadataWithContents = ImageMetadata & {
5
5
  contents?: Buffer;
6
6
  };
7
+ /**
8
+ * Processes an image file and emits its metadata and optionally its contents. This function supports both build and development modes.
9
+ *
10
+ * @param {string | undefined} id - The identifier or path of the image file to process. If undefined, the function returns immediately.
11
+ * @param {boolean} _watchMode - **Deprecated**: Indicates if the method is operating in watch mode. This parameter will be removed or updated in the future.
12
+ * @param {boolean} experimentalSvgEnabled - A flag to enable experimental handling of SVG files. Embeds SVG file data if set to true.
13
+ * @param {FileEmitter | undefined} [fileEmitter] - Function for emitting files during the build process. May throw in certain scenarios.
14
+ * @return {Promise<ImageMetadataWithContents | undefined>} Resolves to metadata with optional image contents or `undefined` if processing fails.
15
+ */
7
16
  export declare function emitESMImage(id: string | undefined,
8
17
  /** @deprecated */
9
18
  _watchMode: boolean, experimentalSvgEnabled: boolean, fileEmitter?: FileEmitter): Promise<ImageMetadataWithContents | undefined>;
@@ -24,7 +24,7 @@ async function emitESMImage(id, _watchMode, experimentalSvgEnabled, fileEmitter)
24
24
  writable: false,
25
25
  value: id
26
26
  });
27
- if (fileMetadata.format === "svg" && experimentalSvgEnabled === true) {
27
+ if (fileMetadata.format === "svg" && experimentalSvgEnabled) {
28
28
  emittedImage.contents = fileData;
29
29
  }
30
30
  let isBuild = typeof fileEmitter === "function";
@@ -1,2 +1,11 @@
1
1
  import type { ImageMetadata } from '../types.js';
2
+ /**
3
+ * Extracts the original image query parameters (width, height, format) from the given `URLSearchParams` object
4
+ * and returns them as an object. If any of the required parameters are missing or invalid, the function returns undefined.
5
+ *
6
+ * The `width` and `height` are parsed to integer values.
7
+ *
8
+ * @param {URLSearchParams} params - The `URLSearchParams` object containing the query parameters.
9
+ * @return {Pick<ImageMetadata, 'width' | 'height' | 'format'> | undefined} An object with the original image parameters (width, height, format) or undefined if any parameter is missing.
10
+ */
2
11
  export declare function getOrigQueryParams(params: URLSearchParams): Pick<ImageMetadata, 'width' | 'height' | 'format'> | undefined;
@@ -1,2 +1,9 @@
1
1
  import type { ImageMetadata } from '../types.js';
2
+ /**
3
+ * Infers the dimensions of a remote image by streaming its data and analyzing it progressively until sufficient metadata is available.
4
+ *
5
+ * @param {string} url - The URL of the remote image from which to infer size metadata.
6
+ * @return {Promise<Omit<ImageMetadata, 'src' | 'fsPath'>>} Returns a promise that resolves to an object containing the image dimensions metadata excluding `src` and `fsPath`.
7
+ * @throws {AstroError} Thrown when the fetching fails or metadata cannot be extracted.
8
+ */
2
9
  export declare function inferRemoteSize(url: string): Promise<Omit<ImageMetadata, 'src' | 'fsPath'>>;
@@ -1,3 +1,33 @@
1
1
  import type { ImageTransform } from '../types.js';
2
+ /**
3
+ * Converts a file path and transformation properties of the transformation image service, into a formatted filename.
4
+ *
5
+ * The formatted filename follows this structure:
6
+ *
7
+ * `<prefixDirname>/<baseFilename>_<hash><outputExtension>`
8
+ *
9
+ * - `prefixDirname`: If the image is an ESM imported image, this is the directory name of the original file path; otherwise, it will be an empty string.
10
+ * - `baseFilename`: The base name of the file or a hashed short name if the file is a `data:` URI.
11
+ * - `hash`: A unique hash string generated to distinguish the transformed file.
12
+ * - `outputExtension`: The desired output file extension derived from the `transform.format` or the original file extension.
13
+ *
14
+ * ## Example
15
+ * - Input: `filePath = '/images/photo.jpg'`, `transform = { format: 'png', src: '/images/photo.jpg' }`, `hash = 'abcd1234'`.
16
+ * - Output: `/images/photo_abcd1234.png`
17
+ *
18
+ * @param {string} filePath - The original file path or data URI of the source image.
19
+ * @param {ImageTransform} transform - An object representing the transformation properties, including format and source.
20
+ * @param {string} hash - A unique hash used to differentiate the transformed file.
21
+ * @return {string} The generated filename based on the provided input, transformations, and hash.
22
+ */
2
23
  export declare function propsToFilename(filePath: string, transform: ImageTransform, hash: string): string;
24
+ /**
25
+ * Transforms the provided `transform` object into a hash string based on selected properties
26
+ * and the specified `imageService`.
27
+ *
28
+ * @param {ImageTransform} transform - The transform object containing various image transformation properties.
29
+ * @param {string} imageService - The name of the image service related to the transform.
30
+ * @param {string[]} propertiesToHash - An array of property names from the `transform` object that should be used to generate the hash.
31
+ * @return {string} A hashed string created from the specified properties of the `transform` object and the image service.
32
+ */
3
33
  export declare function hashTransform(transform: ImageTransform, imageService: string, propertiesToHash: string[]): string;
@@ -6,7 +6,7 @@ import { diffWords } from "diff";
6
6
  import { bold, cyan, dim, green, magenta, red, yellow } from "kleur/colors";
7
7
  import { builders, generateCode, loadFile } from "magicast";
8
8
  import { getDefaultExportOptions } from "magicast/helpers";
9
- import preferredPM from "preferred-pm";
9
+ import { detect, resolveCommand } from "package-manager-detector";
10
10
  import prompts from "prompts";
11
11
  import maxSatisfying from "semver/ranges/max-satisfying.js";
12
12
  import yoctoSpinner from "yocto-spinner";
@@ -190,7 +190,7 @@ async function add(names, { flags }) {
190
190
  logger.debug("add", `Using existing db configuration`);
191
191
  }
192
192
  }
193
- if (integrations.find((integration) => integration.id === "lit") && (await preferredPM(fileURLToPath(root)))?.name === "pnpm") {
193
+ if (integrations.find((integration) => integration.id === "lit") && (await detect({ cwd: fileURLToPath(root) }))?.name === "pnpm") {
194
194
  await setupIntegrationConfig({
195
195
  root,
196
196
  logger,
@@ -494,28 +494,6 @@ ${message}`
494
494
  return 2 /* cancelled */;
495
495
  }
496
496
  }
497
- async function getInstallIntegrationsCommand({
498
- integrations,
499
- logger,
500
- cwd = process.cwd()
501
- }) {
502
- const pm = await preferredPM(cwd);
503
- logger.debug("add", `package manager: ${JSON.stringify(pm)}`);
504
- if (!pm) return null;
505
- const dependencies = await convertIntegrationsToInstallSpecifiers(integrations);
506
- switch (pm.name) {
507
- case "npm":
508
- return { pm: "npm", command: "install", flags: [], dependencies };
509
- case "yarn":
510
- return { pm: "yarn", command: "add", flags: [], dependencies };
511
- case "pnpm":
512
- return { pm: "pnpm", command: "add", flags: [], dependencies };
513
- case "bun":
514
- return { pm: "bun", command: "add", flags: [], dependencies };
515
- default:
516
- return null;
517
- }
518
- }
519
497
  async function convertIntegrationsToInstallSpecifiers(integrations) {
520
498
  const ranges = {};
521
499
  for (let { dependencies } of integrations) {
@@ -550,7 +528,14 @@ async function tryToInstallIntegrations({
550
528
  flags,
551
529
  logger
552
530
  }) {
553
- const installCommand = await getInstallIntegrationsCommand({ integrations, cwd, logger });
531
+ const packageManager = await detect({
532
+ cwd,
533
+ // Include the `install-metadata` strategy to have the package manager that's
534
+ // used for installation take precedence
535
+ strategies: ["install-metadata", "lockfile", "packageManager-field"]
536
+ });
537
+ logger.debug("add", `package manager: "${packageManager?.name}"`);
538
+ if (!packageManager) return 0 /* none */;
554
539
  const inheritedFlags = Object.entries(flags).map(([flag]) => {
555
540
  if (flag == "_") return;
556
541
  if (INHERITED_FLAGS.has(flag)) {
@@ -558,60 +543,46 @@ async function tryToInstallIntegrations({
558
543
  return `--${flag}`;
559
544
  }
560
545
  }).filter(Boolean).flat();
561
- if (installCommand === null) {
562
- return 0 /* none */;
563
- } else {
564
- const coloredOutput = `${bold(installCommand.pm)} ${installCommand.command}${[
565
- "",
566
- ...installCommand.flags,
567
- ...inheritedFlags
568
- ].join(" ")} ${cyan(installCommand.dependencies.join(" "))}`;
569
- const message = `
546
+ const installCommand = resolveCommand(packageManager?.agent ?? "npm", "add", inheritedFlags);
547
+ if (!installCommand) return 0 /* none */;
548
+ const installSpecifiers = await convertIntegrationsToInstallSpecifiers(integrations);
549
+ const coloredOutput = `${bold(installCommand.command)} ${installCommand.args.join(" ")} ${cyan(installSpecifiers.join(" "))}`;
550
+ const message = `
570
551
  ${boxen(coloredOutput, {
571
- margin: 0.5,
572
- padding: 0.5,
573
- borderStyle: "round"
574
- })}
552
+ margin: 0.5,
553
+ padding: 0.5,
554
+ borderStyle: "round"
555
+ })}
575
556
  `;
576
- logger.info(
577
- "SKIP_FORMAT",
578
- `
557
+ logger.info(
558
+ "SKIP_FORMAT",
559
+ `
579
560
  ${magenta("Astro will run the following command:")}
580
561
  ${dim(
581
- "If you skip this step, you can always run it yourself later"
582
- )}
562
+ "If you skip this step, you can always run it yourself later"
563
+ )}
583
564
  ${message}`
584
- );
585
- if (await askToContinue({ flags })) {
586
- const spinner = yoctoSpinner({ text: "Installing dependencies..." }).start();
587
- try {
588
- await exec(
589
- installCommand.pm,
590
- [
591
- installCommand.command,
592
- ...installCommand.flags,
593
- ...inheritedFlags,
594
- ...installCommand.dependencies
595
- ],
596
- {
597
- nodeOptions: {
598
- cwd,
599
- // reset NODE_ENV to ensure install command run in dev mode
600
- env: { NODE_ENV: void 0 }
601
- }
602
- }
603
- );
604
- spinner.success();
605
- return 1 /* updated */;
606
- } catch (err) {
607
- spinner.error();
608
- logger.debug("add", "Error installing dependencies", err);
609
- console.error("\n", err.stdout || err.message, "\n");
610
- return 3 /* failure */;
611
- }
612
- } else {
613
- return 2 /* cancelled */;
565
+ );
566
+ if (await askToContinue({ flags })) {
567
+ const spinner = yoctoSpinner({ text: "Installing dependencies..." }).start();
568
+ try {
569
+ await exec(installCommand.command, [...installCommand.args, ...installSpecifiers], {
570
+ nodeOptions: {
571
+ cwd,
572
+ // reset NODE_ENV to ensure install command run in dev mode
573
+ env: { NODE_ENV: void 0 }
574
+ }
575
+ });
576
+ spinner.success();
577
+ return 1 /* updated */;
578
+ } catch (err) {
579
+ spinner.error();
580
+ logger.debug("add", "Error installing dependencies", err);
581
+ console.error("\n", err.stdout || err.message, "\n");
582
+ return 3 /* failure */;
614
583
  }
584
+ } else {
585
+ return 2 /* cancelled */;
615
586
  }
616
587
  }
617
588
  async function validateIntegrations(integrations) {