astro 4.0.0-beta.0 → 4.0.0-beta.2

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 (62) hide show
  1. package/components/ViewTransitions.astro +28 -27
  2. package/dist/@types/astro.d.ts +37 -22
  3. package/dist/cli/index.js +9 -1
  4. package/dist/cli/info/index.d.ts +5 -0
  5. package/dist/cli/info/index.js +16 -7
  6. package/dist/cli/preferences/index.d.ts +8 -0
  7. package/dist/cli/preferences/index.js +223 -0
  8. package/dist/cli/throw-and-exit.js +1 -1
  9. package/dist/core/app/index.d.ts +9 -3
  10. package/dist/core/app/index.js +28 -2
  11. package/dist/core/app/node.d.ts +9 -3
  12. package/dist/core/app/node.js +4 -4
  13. package/dist/core/compile/compile.js +1 -1
  14. package/dist/core/config/schema.d.ts +52 -14
  15. package/dist/core/config/schema.js +8 -2
  16. package/dist/core/config/settings.js +3 -0
  17. package/dist/core/constants.js +1 -1
  18. package/dist/core/dev/dev.js +1 -1
  19. package/dist/core/dev/restart.js +7 -3
  20. package/dist/core/errors/errors-data.js +3 -3
  21. package/dist/core/logger/core.d.ts +1 -1
  22. package/dist/core/logger/node.js +2 -2
  23. package/dist/core/messages.d.ts +8 -1
  24. package/dist/core/messages.js +81 -37
  25. package/dist/preferences/defaults.d.ts +7 -0
  26. package/dist/preferences/defaults.js +9 -0
  27. package/dist/preferences/index.d.ts +20 -0
  28. package/dist/preferences/index.js +73 -0
  29. package/dist/preferences/store.d.ts +15 -0
  30. package/dist/preferences/store.js +64 -0
  31. package/dist/prefetch/index.js +1 -1
  32. package/dist/runtime/client/dev-overlay/entrypoint.js +14 -10
  33. package/dist/runtime/client/dev-overlay/overlay.js +28 -6
  34. package/dist/runtime/client/dev-overlay/plugins/astro.d.ts +14 -1
  35. package/dist/runtime/client/dev-overlay/plugins/astro.js +335 -15
  36. package/dist/runtime/client/dev-overlay/plugins/settings.js +26 -2
  37. package/dist/runtime/client/dev-overlay/plugins/utils/highlight.d.ts +1 -0
  38. package/dist/runtime/client/dev-overlay/plugins/utils/highlight.js +13 -0
  39. package/dist/runtime/client/dev-overlay/plugins/utils/icons.d.ts +3 -0
  40. package/dist/runtime/client/dev-overlay/plugins/utils/icons.js +37 -0
  41. package/dist/runtime/client/dev-overlay/plugins/utils/window.d.ts +1 -2
  42. package/dist/runtime/client/dev-overlay/plugins/utils/window.js +25 -29
  43. package/dist/runtime/client/dev-overlay/plugins/xray.js +8 -1
  44. package/dist/runtime/client/dev-overlay/ui-library/badge.d.ts +9 -0
  45. package/dist/runtime/client/dev-overlay/ui-library/badge.js +67 -0
  46. package/dist/runtime/client/dev-overlay/ui-library/button.d.ts +9 -0
  47. package/dist/runtime/client/dev-overlay/ui-library/button.js +83 -0
  48. package/dist/runtime/client/dev-overlay/ui-library/card.d.ts +1 -3
  49. package/dist/runtime/client/dev-overlay/ui-library/card.js +17 -25
  50. package/dist/runtime/client/dev-overlay/ui-library/highlight.js +1 -0
  51. package/dist/runtime/client/dev-overlay/ui-library/icon.d.ts +10 -0
  52. package/dist/runtime/client/dev-overlay/ui-library/icon.js +46 -0
  53. package/dist/runtime/client/dev-overlay/ui-library/icons.d.ts +21 -6
  54. package/dist/runtime/client/dev-overlay/ui-library/icons.js +22 -7
  55. package/dist/runtime/client/dev-overlay/ui-library/index.d.ts +8 -0
  56. package/dist/runtime/client/dev-overlay/ui-library/index.js +18 -0
  57. package/dist/runtime/client/dev-overlay/ui-library/toggle.js +8 -0
  58. package/dist/runtime/client/dev-overlay/ui-library/window.d.ts +0 -4
  59. package/dist/runtime/client/dev-overlay/ui-library/window.js +7 -33
  60. package/dist/vite-plugin-astro-server/request.js +5 -2
  61. package/dist/vite-plugin-astro-server/route.js +11 -5
  62. package/package.json +5 -1
@@ -3,10 +3,14 @@ type Fallback = 'none' | 'animate' | 'swap';
3
3
 
4
4
  export interface Props {
5
5
  fallback?: Fallback;
6
+ /** @deprecated handleForms is enabled by default in Astro 4.0
7
+ *
8
+ * Set `data-astro-reload` on your form to opt-out of the default behavior.
9
+ */
6
10
  handleForms?: boolean;
7
11
  }
8
12
 
9
- const { fallback = 'animate', handleForms } = Astro.props;
13
+ const { fallback = 'animate' } = Astro.props;
10
14
  ---
11
15
 
12
16
  <style is:global>
@@ -25,7 +29,6 @@ const { fallback = 'animate', handleForms } = Astro.props;
25
29
  </style>
26
30
  <meta name="astro-view-transitions-enabled" content="true" />
27
31
  <meta name="astro-view-transitions-fallback" content={fallback} />
28
- {handleForms ? <meta name="astro-view-transitions-forms" content="true" /> : ''}
29
32
  <script>
30
33
  import type { Options } from 'astro:transitions/client';
31
34
  import { supportsViewTransitions, navigate } from 'astro:transitions/client';
@@ -89,33 +92,31 @@ const { fallback = 'animate', handleForms } = Astro.props;
89
92
  });
90
93
  });
91
94
 
92
- if (document.querySelector('[name="astro-view-transitions-forms"]')) {
93
- document.addEventListener('submit', (ev) => {
94
- let el = ev.target as HTMLElement;
95
- if (el.tagName !== 'FORM' || isReloadEl(el)) {
96
- return;
97
- }
95
+ document.addEventListener('submit', (ev) => {
96
+ let el = ev.target as HTMLElement;
97
+ if (el.tagName !== 'FORM' || isReloadEl(el)) {
98
+ return;
99
+ }
98
100
 
99
- const form = el as HTMLFormElement;
100
- const submitter = ev.submitter;
101
- const formData = new FormData(form);
102
- // Use the form action, if defined, otherwise fallback to current path.
103
- let action = submitter?.getAttribute('formaction') ?? form.action ?? location.pathname;
104
- const method = submitter?.getAttribute('formmethod') ?? form.method;
101
+ const form = el as HTMLFormElement;
102
+ const submitter = ev.submitter;
103
+ const formData = new FormData(form);
104
+ // Use the form action, if defined, otherwise fallback to current path.
105
+ let action = submitter?.getAttribute('formaction') ?? form.action ?? location.pathname;
106
+ const method = submitter?.getAttribute('formmethod') ?? form.method;
105
107
 
106
- const options: Options = { sourceElement: submitter ?? form };
107
- if (method === 'get') {
108
- const params = new URLSearchParams(formData as any);
109
- const url = new URL(action);
110
- url.search = params.toString();
111
- action = url.toString();
112
- } else {
113
- options.formData = formData;
114
- }
115
- ev.preventDefault();
116
- navigate(action, options);
117
- });
118
- }
108
+ const options: Options = { sourceElement: submitter ?? form };
109
+ if (method === 'get') {
110
+ const params = new URLSearchParams(formData as any);
111
+ const url = new URL(action);
112
+ url.search = params.toString();
113
+ action = url.toString();
114
+ } else {
115
+ options.formData = formData;
116
+ }
117
+ ev.preventDefault();
118
+ navigate(action, options);
119
+ });
119
120
 
120
121
  // @ts-expect-error injected by vite-plugin-transitions for treeshaking
121
122
  if (!__PREFETCH_DISABLED__) {
@@ -15,14 +15,12 @@ import type { TSConfig } from '../core/config/tsconfig.js';
15
15
  import type { AstroCookies } from '../core/cookies/index.js';
16
16
  import type { AstroIntegrationLogger, Logger, LoggerLevel } from '../core/logger/core.js';
17
17
  import type { AstroDevOverlay, DevOverlayCanvas } from '../runtime/client/dev-overlay/overlay.js';
18
- import type { DevOverlayHighlight } from '../runtime/client/dev-overlay/ui-library/highlight.js';
19
18
  import type { Icon } from '../runtime/client/dev-overlay/ui-library/icons.js';
20
- import type { DevOverlayToggle } from '../runtime/client/dev-overlay/ui-library/toggle.js';
21
- import type { DevOverlayTooltip } from '../runtime/client/dev-overlay/ui-library/tooltip.js';
22
- import type { DevOverlayWindow } from '../runtime/client/dev-overlay/ui-library/window.js';
19
+ import type { DevOverlayBadge, DevOverlayButton, DevOverlayCard, DevOverlayHighlight, DevOverlayIcon, DevOverlayToggle, DevOverlayTooltip, DevOverlayWindow } from '../runtime/client/dev-overlay/ui-library/index.js';
23
20
  import type { AstroComponentFactory, AstroComponentInstance } from '../runtime/server/index.js';
24
21
  import type { OmitIndexSignature, Simplify } from '../type-utils.js';
25
22
  import type { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './../core/constants.js';
23
+ import type { AstroPreferences } from '../preferences/index.js';
26
24
  export { type AstroIntegrationLogger };
27
25
  export type { MarkdownHeading, MarkdownMetadata, MarkdownRenderingResult, RehypePlugins, RemarkPlugins, ShikiConfig, } from '@astrojs/markdown-remark';
28
26
  export type { ExternalImageService, ImageService, LocalImageService, } from '../assets/services/service.js';
@@ -1055,6 +1053,33 @@ export interface AstroUserConfig {
1055
1053
  */
1056
1054
  remotePatterns?: Partial<RemotePattern>[];
1057
1055
  };
1056
+ /**
1057
+ * @docs
1058
+ * @kind heading
1059
+ * @name Dev Overlay Options
1060
+ */
1061
+ devOverlay?: {
1062
+ /**
1063
+ * @docs
1064
+ * @name devOverlay.enabled
1065
+ * @type {boolean}
1066
+ * @default `true`
1067
+ * @description
1068
+ * Whether to enable the dev overlay. This overlay allows you to inspect your page islands, see helpful audits on performance and accessibility, and more.
1069
+ *
1070
+ * This option is scoped to the entire project, to only disable the overlay for yourself, run `npm run astro preferences disable devOverlay`. To disable the overlay for all your Astro projects, run `npm run astro preferences disable devOverlay --global`.
1071
+ */
1072
+ enabled: boolean;
1073
+ /**
1074
+ * @docs
1075
+ * @name devOverlay.defaultState
1076
+ * @type {'minimized' | 'expanded'}
1077
+ * @default `minimized`
1078
+ * @description
1079
+ * Whether the dev overlay should be expanded or minimized by default.
1080
+ */
1081
+ defaultState: 'minimized' | 'expanded';
1082
+ };
1058
1083
  /**
1059
1084
  * @docs
1060
1085
  * @kind heading
@@ -1271,24 +1296,6 @@ export interface AstroUserConfig {
1271
1296
  * ```
1272
1297
  */
1273
1298
  optimizeHoistedScript?: boolean;
1274
- /**
1275
- * @docs
1276
- * @name experimental.devOverlay
1277
- * @type {boolean}
1278
- * @default `false`
1279
- * @version 3.4.0
1280
- * @description
1281
- * Enable a dev overlay in development mode. This overlay allows you to inspect your page islands, see helpful audits on performance and accessibility, and more.
1282
- *
1283
- * ```js
1284
- * {
1285
- * experimental: {
1286
- * devOverlay: true,
1287
- * },
1288
- * }
1289
- * ```
1290
- */
1291
- devOverlay?: boolean;
1292
1299
  /**
1293
1300
  * @docs
1294
1301
  * @name experimental.i18n
@@ -1531,6 +1538,7 @@ export interface AstroAdapterFeatures {
1531
1538
  export interface AstroSettings {
1532
1539
  config: AstroConfig;
1533
1540
  adapter: AstroAdapter | undefined;
1541
+ preferences: AstroPreferences;
1534
1542
  injectedRoutes: InjectedRoute[];
1535
1543
  resolvedInjectedRoutes: ResolvedInjectedRoute[];
1536
1544
  pageExtensions: string[];
@@ -2235,7 +2243,10 @@ export interface DevOverlayPlugin {
2235
2243
  }
2236
2244
  export type DevOverlayMetadata = Window & typeof globalThis & {
2237
2245
  __astro_dev_overlay__: {
2246
+ defaultState: AstroConfig['devOverlay']['defaultState'];
2238
2247
  root: string;
2248
+ version: string;
2249
+ debugInfo: string;
2239
2250
  };
2240
2251
  };
2241
2252
  declare global {
@@ -2246,5 +2257,9 @@ declare global {
2246
2257
  'astro-dev-overlay-tooltip': DevOverlayTooltip;
2247
2258
  'astro-dev-overlay-highlight': DevOverlayHighlight;
2248
2259
  'astro-dev-overlay-toggle': DevOverlayToggle;
2260
+ 'astro-dev-overlay-badge': DevOverlayBadge;
2261
+ 'astro-dev-overlay-button': DevOverlayButton;
2262
+ 'astro-dev-overlay-icon': DevOverlayIcon;
2263
+ 'astro-dev-overlay-card': DevOverlayCard;
2249
2264
  }
2250
2265
  }
package/dist/cli/index.js CHANGED
@@ -17,6 +17,7 @@ async function printAstroHelp() {
17
17
  ["info", "List info about your current Astro setup."],
18
18
  ["preview", "Preview your build locally."],
19
19
  ["sync", "Generate content collection types."],
20
+ ["preferences", "Configure user preferences."],
20
21
  ["telemetry", "Configure telemetry settings."]
21
22
  ],
22
23
  "Global Flags": [
@@ -44,6 +45,7 @@ function resolveCommand(flags) {
44
45
  "add",
45
46
  "sync",
46
47
  "telemetry",
48
+ "preferences",
47
49
  "dev",
48
50
  "build",
49
51
  "preview",
@@ -85,6 +87,12 @@ async function runCommand(cmd, flags) {
85
87
  const exitCode = await sync({ flags });
86
88
  return process.exit(exitCode);
87
89
  }
90
+ case "preferences": {
91
+ const { preferences } = await import("./preferences/index.js");
92
+ const [subcommand, key, value] = flags._.slice(3).map((v) => v.toString());
93
+ const exitCode = await preferences(subcommand, key, value, { flags });
94
+ return process.exit(exitCode);
95
+ }
88
96
  }
89
97
  if (flags.verbose) {
90
98
  const { enableVerboseLogging } = await import("../core/logger/node.js");
@@ -138,7 +146,7 @@ async function runCommand(cmd, flags) {
138
146
  throw new Error(`Error running ${cmd} -- no command found.`);
139
147
  }
140
148
  async function cli(args) {
141
- const flags = yargs(args);
149
+ const flags = yargs(args, { boolean: ["global"], alias: { g: "global" } });
142
150
  const cmd = resolveCommand(flags);
143
151
  try {
144
152
  await runCommand(cmd, flags);
@@ -1,6 +1,11 @@
1
1
  import type yargs from 'yargs-parser';
2
+ import type { AstroConfig, AstroUserConfig } from '../../@types/astro.js';
2
3
  interface InfoOptions {
3
4
  flags: yargs.Arguments;
4
5
  }
6
+ export declare function getInfoOutput({ userConfig, print, }: {
7
+ userConfig: AstroUserConfig | AstroConfig;
8
+ print: boolean;
9
+ }): Promise<string>;
5
10
  export declare function printInfo({ flags }: InfoOptions): Promise<void>;
6
11
  export {};
@@ -5,16 +5,17 @@ import prompts from "prompts";
5
5
  import { resolveConfig } from "../../core/config/index.js";
6
6
  import { ASTRO_VERSION } from "../../core/constants.js";
7
7
  import { flagsToAstroInlineConfig } from "../flags.js";
8
- async function printInfo({ flags }) {
8
+ async function getInfoOutput({
9
+ userConfig,
10
+ print
11
+ }) {
9
12
  const rows = [
10
13
  ["Astro", `v${ASTRO_VERSION}`],
11
14
  ["Node", process.version],
12
15
  ["System", getSystem()],
13
16
  ["Package Manager", getPackageManager()]
14
17
  ];
15
- const inlineConfig = flagsToAstroInlineConfig(flags);
16
18
  try {
17
- const { userConfig } = await resolveConfig(inlineConfig, "info");
18
19
  rows.push(["Output", userConfig.output ?? "static"]);
19
20
  rows.push(["Adapter", userConfig.adapter?.name ?? "none"]);
20
21
  const integrations = (userConfig?.integrations ?? []).filter(Boolean).flat().map((i) => i?.name).filter(Boolean);
@@ -23,9 +24,14 @@ async function printInfo({ flags }) {
23
24
  }
24
25
  let output = "";
25
26
  for (const [label, value] of rows) {
26
- output += printRow(label, value);
27
+ output += printRow(label, value, print);
27
28
  }
28
- await copyToClipboard(output.trim());
29
+ return output.trim();
30
+ }
31
+ async function printInfo({ flags }) {
32
+ const { userConfig } = await resolveConfig(flagsToAstroInlineConfig(flags), "info");
33
+ const output = await getInfoOutput({ userConfig, print: true });
34
+ await copyToClipboard(output);
29
35
  }
30
36
  async function copyToClipboard(text) {
31
37
  const system = platform();
@@ -84,7 +90,7 @@ function getPackageManager() {
84
90
  return name === "npminstall" ? "cnpm" : name;
85
91
  }
86
92
  const MAX_PADDING = 25;
87
- function printRow(label, value) {
93
+ function printRow(label, value, print) {
88
94
  const padding = MAX_PADDING - label.length;
89
95
  const [first, ...rest] = Array.isArray(value) ? value : [value];
90
96
  let plaintext = `${label}${" ".repeat(padding)}${first}`;
@@ -98,9 +104,12 @@ ${" ".repeat(MAX_PADDING)}${colors.green(entry)}`;
98
104
  }
99
105
  }
100
106
  plaintext += "\n";
101
- console.log(richtext);
107
+ if (print) {
108
+ console.log(richtext);
109
+ }
102
110
  return plaintext;
103
111
  }
104
112
  export {
113
+ getInfoOutput,
105
114
  printInfo
106
115
  };
@@ -0,0 +1,8 @@
1
+ import type yargs from 'yargs-parser';
2
+ interface PreferencesOptions {
3
+ flags: yargs.Arguments;
4
+ }
5
+ declare const PREFERENCES_SUBCOMMANDS: readonly ["get", "set", "enable", "disable", "delete", "reset", "list"];
6
+ export type Subcommand = (typeof PREFERENCES_SUBCOMMANDS)[number];
7
+ export declare function preferences(subcommand: string, key: string, value: string | undefined, { flags }: PreferencesOptions): Promise<number>;
8
+ export {};
@@ -0,0 +1,223 @@
1
+ import { bold } from "kleur/colors";
2
+ import { fileURLToPath } from "node:url";
3
+ import * as msg from "../../core/messages.js";
4
+ import { createLoggerFromFlags, flagsToAstroInlineConfig } from "../flags.js";
5
+ import { resolveConfig } from "../../core/config/config.js";
6
+ import { createSettings } from "../../core/config/settings.js";
7
+ import { coerce, isValidKey } from "../../preferences/index.js";
8
+ import { DEFAULT_PREFERENCES } from "../../preferences/defaults.js";
9
+ import dlv from "dlv";
10
+ import { flattie } from "flattie";
11
+ import { formatWithOptions } from "node:util";
12
+ import { collectErrorMetadata } from "../../core/errors/dev/utils.js";
13
+ const PREFERENCES_SUBCOMMANDS = [
14
+ "get",
15
+ "set",
16
+ "enable",
17
+ "disable",
18
+ "delete",
19
+ "reset",
20
+ "list"
21
+ ];
22
+ function isValidSubcommand(subcommand) {
23
+ return PREFERENCES_SUBCOMMANDS.includes(subcommand);
24
+ }
25
+ async function preferences(subcommand, key, value, { flags }) {
26
+ if (!isValidSubcommand(subcommand) || flags?.help || flags?.h) {
27
+ msg.printHelp({
28
+ commandName: "astro preferences",
29
+ usage: "[command]",
30
+ tables: {
31
+ Commands: [
32
+ ["list", "Pretty print all current preferences"],
33
+ ["list --json", "Log all current preferences as a JSON object"],
34
+ ["get [key]", "Log current preference value"],
35
+ ["set [key] [value]", "Update preference value"],
36
+ ["reset [key]", "Reset preference value to default"],
37
+ ["enable [key]", "Set a boolean preference to true"],
38
+ ["disable [key]", "Set a boolean preference to false"]
39
+ ],
40
+ Flags: [
41
+ [
42
+ "--global",
43
+ "Scope command to global preferences (all Astro projects) rather than the current project"
44
+ ]
45
+ ]
46
+ }
47
+ });
48
+ return 0;
49
+ }
50
+ const inlineConfig = flagsToAstroInlineConfig(flags);
51
+ const logger = createLoggerFromFlags(flags);
52
+ const { astroConfig } = await resolveConfig(inlineConfig ?? {}, "dev");
53
+ const settings = await createSettings(astroConfig, fileURLToPath(astroConfig.root));
54
+ const opts = {
55
+ location: flags.global ? "global" : void 0,
56
+ json: flags.json
57
+ };
58
+ if (subcommand === "list") {
59
+ return listPreferences(settings, opts);
60
+ }
61
+ if (subcommand === "enable" || subcommand === "disable") {
62
+ key = `${key}.enabled`;
63
+ }
64
+ if (!isValidKey(key)) {
65
+ logger.error("preferences", `Unknown preference "${key}"
66
+ `);
67
+ return 1;
68
+ }
69
+ if (subcommand === "set" && value === void 0) {
70
+ const type = typeof dlv(DEFAULT_PREFERENCES, key);
71
+ console.error(
72
+ msg.formatErrorMessage(
73
+ collectErrorMetadata(new Error(`Please provide a ${type} value for "${key}"`)),
74
+ true
75
+ )
76
+ );
77
+ return 1;
78
+ }
79
+ switch (subcommand) {
80
+ case "get":
81
+ return getPreference(settings, key, opts);
82
+ case "set":
83
+ return setPreference(settings, key, value, opts);
84
+ case "reset":
85
+ case "delete":
86
+ return resetPreference(settings, key, opts);
87
+ case "enable":
88
+ return enablePreference(settings, key, opts);
89
+ case "disable":
90
+ return disablePreference(settings, key, opts);
91
+ }
92
+ }
93
+ async function getPreference(settings, key, { location = "project" }) {
94
+ try {
95
+ let value = await settings.preferences.get(key, { location });
96
+ if (value && typeof value === "object" && !Array.isArray(value)) {
97
+ if (Object.keys(value).length === 0) {
98
+ value = dlv(DEFAULT_PREFERENCES, key);
99
+ console.log(msg.preferenceDefaultIntro(key));
100
+ }
101
+ prettyPrint({ [key]: value });
102
+ return 0;
103
+ }
104
+ if (value === void 0) {
105
+ const defaultValue = await settings.preferences.get(key);
106
+ console.log(msg.preferenceDefault(key, defaultValue));
107
+ return 0;
108
+ }
109
+ console.log(msg.preferenceGet(key, value));
110
+ return 0;
111
+ } catch {
112
+ }
113
+ return 1;
114
+ }
115
+ async function setPreference(settings, key, value, { location }) {
116
+ try {
117
+ const defaultType = typeof dlv(DEFAULT_PREFERENCES, key);
118
+ if (typeof coerce(key, value) !== defaultType) {
119
+ throw new Error(`${key} expects a "${defaultType}" value!`);
120
+ }
121
+ await settings.preferences.set(key, coerce(key, value), { location });
122
+ console.log(msg.preferenceSet(key, value));
123
+ return 0;
124
+ } catch (e) {
125
+ if (e instanceof Error) {
126
+ console.error(msg.formatErrorMessage(collectErrorMetadata(e), true));
127
+ return 1;
128
+ }
129
+ throw e;
130
+ }
131
+ }
132
+ async function enablePreference(settings, key, { location }) {
133
+ try {
134
+ await settings.preferences.set(key, true, { location });
135
+ console.log(msg.preferenceEnabled(key.replace(".enabled", "")));
136
+ return 0;
137
+ } catch {
138
+ }
139
+ return 1;
140
+ }
141
+ async function disablePreference(settings, key, { location }) {
142
+ try {
143
+ await settings.preferences.set(key, false, { location });
144
+ console.log(msg.preferenceDisabled(key.replace(".enabled", "")));
145
+ return 0;
146
+ } catch {
147
+ }
148
+ return 1;
149
+ }
150
+ async function resetPreference(settings, key, { location }) {
151
+ try {
152
+ await settings.preferences.set(key, void 0, { location });
153
+ console.log(msg.preferenceReset(key));
154
+ return 0;
155
+ } catch {
156
+ }
157
+ return 1;
158
+ }
159
+ async function listPreferences(settings, { location, json }) {
160
+ const store = await settings.preferences.getAll({ location });
161
+ if (json) {
162
+ console.log(JSON.stringify(store, null, 2));
163
+ return 0;
164
+ }
165
+ prettyPrint(store);
166
+ return 0;
167
+ }
168
+ function prettyPrint(value) {
169
+ const flattened = flattie(value);
170
+ const table = formatTable(flattened, ["Preference", "Value"]);
171
+ console.log(table);
172
+ }
173
+ const chars = {
174
+ h: "\u2500",
175
+ hThick: "\u2501",
176
+ hThickCross: "\u253F",
177
+ v: "\u2502",
178
+ vRight: "\u251C",
179
+ vRightThick: "\u251D",
180
+ vLeft: "\u2524",
181
+ vLeftThick: "\u2525",
182
+ hTop: "\u2534",
183
+ hBottom: "\u252C",
184
+ topLeft: "\u256D",
185
+ topRight: "\u256E",
186
+ bottomLeft: "\u2570",
187
+ bottomRight: "\u256F"
188
+ };
189
+ function formatTable(object, columnLabels) {
190
+ const [colA, colB] = columnLabels;
191
+ const colALength = [colA, ...Object.keys(object)].reduce(longest, 0) + 3;
192
+ const colBLength = [colB, ...Object.values(object)].reduce(longest, 0) + 3;
193
+ function formatRow(i2, a, b, style = (v) => v.toString()) {
194
+ return `${chars.v} ${style(a)} ${space(colALength - a.length - 2)} ${chars.v} ${style(
195
+ b
196
+ )} ${space(colBLength - b.toString().length - 3)} ${chars.v}`;
197
+ }
198
+ const top = `${chars.topLeft}${chars.h.repeat(colALength + 1)}${chars.hBottom}${chars.h.repeat(
199
+ colBLength
200
+ )}${chars.topRight}`;
201
+ const bottom = `${chars.bottomLeft}${chars.h.repeat(colALength + 1)}${chars.hTop}${chars.h.repeat(
202
+ colBLength
203
+ )}${chars.bottomRight}`;
204
+ const divider = `${chars.vRightThick}${chars.hThick.repeat(colALength + 1)}${chars.hThickCross}${chars.hThick.repeat(colBLength)}${chars.vLeftThick}`;
205
+ const rows = [top, formatRow(-1, colA, colB, bold), divider];
206
+ let i = 0;
207
+ for (const [key, value] of Object.entries(object)) {
208
+ rows.push(formatRow(i, key, value, (v) => formatWithOptions({ colors: true }, v)));
209
+ i++;
210
+ }
211
+ rows.push(bottom);
212
+ return rows.join("\n");
213
+ }
214
+ function space(len) {
215
+ return " ".repeat(len);
216
+ }
217
+ const longest = (a, b) => {
218
+ const { length: len } = b.toString();
219
+ return a > len ? a : len;
220
+ };
221
+ export {
222
+ preferences
223
+ };
@@ -15,7 +15,7 @@ async function throwAndExit(cmd, err) {
15
15
  }
16
16
  const errorWithMetadata = collectErrorMetadata(createSafeError(err));
17
17
  telemetryPromise = telemetry.record(eventError({ cmd, err: errorWithMetadata, isFatal: true }));
18
- errorMessage = formatErrorMessage(errorWithMetadata);
18
+ errorMessage = formatErrorMessage(errorWithMetadata, true);
19
19
  setTimeout(exitWithErrorMessage, 400);
20
20
  await telemetryPromise.catch((err2) => debug("telemetry", `record() error: ${err2.message}`)).then(exitWithErrorMessage);
21
21
  }
@@ -1,8 +1,9 @@
1
1
  import type { ManifestData, RouteData, SSRManifest } from '../../@types/astro.js';
2
2
  import { AstroIntegrationLogger } from '../logger/core.js';
3
3
  export { deserializeManifest } from './common.js';
4
- export interface MatchOptions {
5
- matchNotFound?: boolean | undefined;
4
+ export interface RenderOptions {
5
+ routeData?: RouteData;
6
+ locals?: object;
6
7
  }
7
8
  export interface RenderErrorOptions {
8
9
  routeData?: RouteData;
@@ -19,7 +20,12 @@ export declare class App {
19
20
  getAdapterLogger(): AstroIntegrationLogger;
20
21
  set setManifestData(newManifestData: ManifestData);
21
22
  removeBase(pathname: string): string;
22
- match(request: Request, _opts?: MatchOptions): RouteData | undefined;
23
+ match(request: Request): RouteData | undefined;
24
+ render(request: Request, options?: RenderOptions): Promise<Response>;
25
+ /**
26
+ * @deprecated Instead of passing `RouteData` and locals individually, pass an object with `routeData` and `locals` properties.
27
+ * See https://github.com/withastro/astro/pull/9199 for more information.
28
+ */
23
29
  render(request: Request, routeData?: RouteData, locals?: object): Promise<Response>;
24
30
  setCookieHeaders(response: Response): Generator<string, string[], unknown>;
25
31
  }
@@ -36,6 +36,7 @@ class App {
36
36
  #baseWithoutTrailingSlash;
37
37
  #pipeline;
38
38
  #adapterLogger;
39
+ #renderOptionsDeprecationWarningShown = false;
39
40
  constructor(manifest, streaming = true) {
40
41
  this.#manifest = manifest;
41
42
  this.#manifestData = {
@@ -101,7 +102,7 @@ class App {
101
102
  const pathname = prependForwardSlash(this.removeBase(url.pathname));
102
103
  return pathname;
103
104
  }
104
- match(request, _opts = {}) {
105
+ match(request) {
105
106
  const url = new URL(request.url);
106
107
  if (this.#manifest.assets.has(url.pathname))
107
108
  return void 0;
@@ -111,7 +112,23 @@ class App {
111
112
  return void 0;
112
113
  return routeData;
113
114
  }
114
- async render(request, routeData, locals) {
115
+ async render(request, routeDataOrOptions, maybeLocals) {
116
+ let routeData;
117
+ let locals;
118
+ if (routeDataOrOptions && ("routeData" in routeDataOrOptions || "locals" in routeDataOrOptions)) {
119
+ if ("routeData" in routeDataOrOptions) {
120
+ routeData = routeDataOrOptions.routeData;
121
+ }
122
+ if ("locals" in routeDataOrOptions) {
123
+ locals = routeDataOrOptions.locals;
124
+ }
125
+ } else {
126
+ routeData = routeDataOrOptions;
127
+ locals = maybeLocals;
128
+ if (routeDataOrOptions || locals) {
129
+ this.#logRenderOptionsDeprecationWarning();
130
+ }
131
+ }
115
132
  if (request.url !== collapseDuplicateSlashes(request.url)) {
116
133
  request = new Request(collapseDuplicateSlashes(request.url), request);
117
134
  }
@@ -174,6 +191,15 @@ class App {
174
191
  }
175
192
  return response;
176
193
  }
194
+ #logRenderOptionsDeprecationWarning() {
195
+ if (this.#renderOptionsDeprecationWarningShown)
196
+ return;
197
+ this.#logger.warn(
198
+ "deprecated",
199
+ `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.`
200
+ );
201
+ this.#renderOptionsDeprecationWarningShown = true;
202
+ }
177
203
  setCookieHeaders(response) {
178
204
  return getSetCookiesFromResponse(response);
179
205
  }
@@ -1,8 +1,9 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  import type { RouteData } from '../../@types/astro.js';
3
3
  import type { SSRManifest } from './types.js';
4
+ import type { RenderOptions } from './index.js';
4
5
  import { IncomingMessage } from 'node:http';
5
- import { App, type MatchOptions } from './index.js';
6
+ import { App } from './index.js';
6
7
  export { apply as applyPolyfills } from '../polyfill.js';
7
8
  declare class NodeIncomingMessage extends IncomingMessage {
8
9
  /**
@@ -12,8 +13,13 @@ declare class NodeIncomingMessage extends IncomingMessage {
12
13
  body?: unknown;
13
14
  }
14
15
  export declare class NodeApp extends App {
15
- match(req: NodeIncomingMessage | Request, opts?: MatchOptions): RouteData | undefined;
16
- render(req: NodeIncomingMessage | Request, routeData?: RouteData, locals?: object): Promise<Response>;
16
+ match(req: NodeIncomingMessage | Request): RouteData | undefined;
17
+ render(request: NodeIncomingMessage | Request, options?: RenderOptions): Promise<Response>;
18
+ /**
19
+ * @deprecated Instead of passing `RouteData` and locals individually, pass an object with `routeData` and `locals` properties.
20
+ * See https://github.com/withastro/astro/pull/9199 for more information.
21
+ */
22
+ render(request: NodeIncomingMessage | Request, routeData?: RouteData, locals?: object): Promise<Response>;
17
23
  }
18
24
  export declare function loadManifest(rootFolder: URL): Promise<SSRManifest>;
19
25
  export declare function loadApp(rootFolder: URL): Promise<NodeApp>;
@@ -77,19 +77,19 @@ class NodeIncomingMessage extends IncomingMessage {
77
77
  body;
78
78
  }
79
79
  class NodeApp extends App {
80
- match(req, opts = {}) {
80
+ match(req) {
81
81
  if (!(req instanceof Request)) {
82
82
  req = createRequestFromNodeRequest(req, {
83
83
  emptyBody: true
84
84
  });
85
85
  }
86
- return super.match(req, opts);
86
+ return super.match(req);
87
87
  }
88
- render(req, routeData, locals) {
88
+ render(req, routeDataOrOptions, maybeLocals) {
89
89
  if (!(req instanceof Request)) {
90
90
  req = createRequestFromNodeRequest(req);
91
91
  }
92
- return super.render(req, routeData, locals);
92
+ return super.render(req, routeDataOrOptions, maybeLocals);
93
93
  }
94
94
  }
95
95
  async function loadManifest(rootFolder) {