astro 4.6.4 → 4.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dist/@types/astro.d.ts +48 -6
  2. package/dist/cli/add/index.js +1 -41
  3. package/dist/cli/install-package.d.ts +9 -0
  4. package/dist/cli/install-package.js +64 -1
  5. package/dist/config/index.js +1 -1
  6. package/dist/content/index.d.ts +0 -1
  7. package/dist/content/index.js +0 -2
  8. package/dist/content/utils.js +1 -3
  9. package/dist/core/build/generate.js +1 -1
  10. package/dist/core/build/index.js +1 -1
  11. package/dist/core/build/plugins/plugin-manifest.js +1 -1
  12. package/dist/core/build/plugins/plugin-ssr.js +1 -1
  13. package/dist/core/build/static-build.js +5 -1
  14. package/dist/core/compile/compile.js +1 -1
  15. package/dist/core/config/settings.js +3 -1
  16. package/dist/core/constants.d.ts +1 -1
  17. package/dist/core/constants.js +1 -1
  18. package/dist/core/create-vite.js +1 -1
  19. package/dist/core/dev/container.js +1 -1
  20. package/dist/core/dev/dev.js +34 -2
  21. package/dist/core/dev/restart.js +5 -1
  22. package/dist/core/dev/update-check.d.ts +4 -0
  23. package/dist/core/dev/update-check.js +36 -0
  24. package/dist/core/errors/errors-data.d.ts +1 -1
  25. package/dist/core/errors/errors-data.js +2 -2
  26. package/dist/core/errors/index.d.ts +1 -0
  27. package/dist/core/errors/index.js +2 -0
  28. package/dist/core/errors/overlay.js +2 -2
  29. package/dist/core/logger/core.d.ts +1 -1
  30. package/dist/core/messages.d.ts +3 -0
  31. package/dist/core/messages.js +11 -2
  32. package/dist/core/preview/index.js +1 -1
  33. package/dist/core/routing/priority.d.ts +1 -1
  34. package/dist/core/sync/index.js +1 -1
  35. package/dist/integrations/{index.d.ts → hooks.d.ts} +28 -0
  36. package/dist/integrations/{index.js → hooks.js} +41 -2
  37. package/dist/preferences/defaults.d.ts +9 -0
  38. package/dist/preferences/defaults.js +9 -0
  39. package/dist/preferences/index.d.ts +12 -4
  40. package/dist/preferences/index.js +11 -4
  41. package/dist/prerender/utils.d.ts +1 -1
  42. package/dist/runtime/client/dev-toolbar/apps/astro.d.ts +1 -1
  43. package/dist/runtime/client/dev-toolbar/apps/astro.js +3 -0
  44. package/dist/runtime/client/dev-toolbar/apps/audit/index.d.ts +1 -1
  45. package/dist/runtime/client/dev-toolbar/apps/settings.d.ts +1 -1
  46. package/dist/runtime/client/dev-toolbar/apps/xray.d.ts +1 -1
  47. package/dist/runtime/client/dev-toolbar/entrypoint.js +3 -2
  48. package/dist/runtime/client/dev-toolbar/helpers.d.ts +61 -0
  49. package/dist/runtime/client/dev-toolbar/helpers.js +87 -0
  50. package/dist/runtime/client/dev-toolbar/toolbar.d.ts +3 -2
  51. package/dist/runtime/client/dev-toolbar/toolbar.js +2 -1
  52. package/dist/runtime/server/astro-global.js +1 -1
  53. package/dist/runtime/server/render/astro/instance.js +10 -10
  54. package/dist/runtime/server/render/util.js +3 -1
  55. package/dist/toolbar/index.d.ts +2 -0
  56. package/dist/toolbar/index.js +6 -0
  57. package/dist/{vite-plugin-dev-toolbar → toolbar}/vite-plugin-dev-toolbar.js +33 -12
  58. package/dist/transitions/events.d.ts +5 -4
  59. package/dist/transitions/events.js +13 -7
  60. package/dist/transitions/router.js +93 -34
  61. package/dist/vite-plugin-astro-server/pipeline.js +1 -0
  62. package/dist/vite-plugin-astro-server/vite.js +4 -5
  63. package/dist/vite-plugin-integrations-container/index.js +1 -1
  64. package/package.json +14 -13
  65. package/tsconfigs/strictest.json +1 -3
  66. /package/dist/{content/error-map.d.ts → core/errors/zod-error-map.d.ts} +0 -0
  67. /package/dist/{content/error-map.js → core/errors/zod-error-map.js} +0 -0
  68. /package/dist/integrations/{astroFeaturesValidation.d.ts → features-validation.d.ts} +0 -0
  69. /package/dist/integrations/{astroFeaturesValidation.js → features-validation.js} +0 -0
  70. /package/dist/{vite-plugin-dev-toolbar → toolbar}/vite-plugin-dev-toolbar.d.ts +0 -0
@@ -14,6 +14,7 @@ import {
14
14
  underline,
15
15
  yellow
16
16
  } from "kleur/colors";
17
+ import { getExecCommand } from "../cli/install-package.js";
17
18
  import { getDocsForError, renderErrorMarkdown } from "./errors/dev/utils.js";
18
19
  import {
19
20
  AstroError,
@@ -36,7 +37,7 @@ function serverStart({
36
37
  host,
37
38
  base
38
39
  }) {
39
- const version = "4.6.4";
40
+ const version = "4.7.1";
40
41
  const localPrefix = `${dim("\u2503")} Local `;
41
42
  const networkPrefix = `${dim("\u2503")} Network `;
42
43
  const emptyPrefix = " ".repeat(11);
@@ -69,6 +70,13 @@ function serverStart({
69
70
  function serverShortcuts({ key, label }) {
70
71
  return [dim(" Press"), key, dim("to"), label].join(" ");
71
72
  }
73
+ function newVersionAvailable({ latestVersion }) {
74
+ const badge = bgYellow(black(` update `));
75
+ const headline = yellow(`\u25B6 New version of Astro available: ${latestVersion}`);
76
+ const execCommand = getExecCommand();
77
+ const details = ` Run ${cyan(`${execCommand} @astrojs/upgrade`)} to update`;
78
+ return ["", `${badge} ${headline}`, details, ""].join("\n");
79
+ }
72
80
  function telemetryNotice() {
73
81
  const headline = blue(`\u25B6 Astro collects anonymous usage data.`);
74
82
  const why = " This information helps us improve Astro.";
@@ -261,7 +269,7 @@ function printHelp({
261
269
  message.push(
262
270
  linebreak(),
263
271
  ` ${bgGreen(black(` ${commandName} `))} ${green(
264
- `v${"4.6.4"}`
272
+ `v${"4.7.1"}`
265
273
  )} ${headline}`
266
274
  );
267
275
  }
@@ -291,6 +299,7 @@ export {
291
299
  formatErrorMessage,
292
300
  fsStrictWarning,
293
301
  getNetworkLogging,
302
+ newVersionAvailable,
294
303
  preferenceDefault,
295
304
  preferenceDefaultIntro,
296
305
  preferenceDisabled,
@@ -4,7 +4,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
4
4
  import { AstroIntegrationLogger } from "../../core/logger/core.js";
5
5
  import { telemetry } from "../../events/index.js";
6
6
  import { eventCliSession } from "../../events/session.js";
7
- import { runHookConfigDone, runHookConfigSetup } from "../../integrations/index.js";
7
+ import { runHookConfigDone, runHookConfigSetup } from "../../integrations/hooks.js";
8
8
  import { resolveConfig } from "../config/config.js";
9
9
  import { createNodeLogger } from "../config/logging.js";
10
10
  import { createSettings } from "../config/settings.js";
@@ -16,7 +16,7 @@ import type { RouteData } from '../../@types/astro.js';
16
16
  * - Prerendered routes are sorted before non-prerendered routes.
17
17
  * - Endpoints are sorted before pages.
18
18
  * For example, a file `/foo.ts` is sorted before `/bar.astro`.
19
- * - If both routes are equal regarding all previosu conditions, they are sorted alphabetically.
19
+ * - If both routes are equal regarding all previous conditions, they are sorted alphabetically.
20
20
  * For example, `/bar` is sorted before `/foo`.
21
21
  * The definition of "alphabetically" is dependent on the default locale of the running system.
22
22
  */
@@ -8,7 +8,7 @@ import { createContentTypesGenerator } from "../../content/index.js";
8
8
  import { globalContentConfigObserver } from "../../content/utils.js";
9
9
  import { telemetry } from "../../events/index.js";
10
10
  import { eventCliSession } from "../../events/session.js";
11
- import { runHookConfigSetup } from "../../integrations/index.js";
11
+ import { runHookConfigSetup } from "../../integrations/hooks.js";
12
12
  import { setUpEnvTs } from "../../vite-plugin-inject-env-ts/index.js";
13
13
  import { getTimeStat } from "../build/util.js";
14
14
  import { resolveConfig } from "../config/config.js";
@@ -5,6 +5,34 @@ import type { AstroAdapter, AstroConfig, AstroSettings, RouteData } from '../@ty
5
5
  import type { SerializedSSRManifest } from '../core/app/types.js';
6
6
  import type { PageBuildData } from '../core/build/types.js';
7
7
  import type { Logger } from '../core/logger/core.js';
8
+ export declare function getToolbarServerCommunicationHelpers(server: ViteDevServer): {
9
+ /**
10
+ * Send a message to the dev toolbar that an app can listen for. The payload can be any serializable data.
11
+ * @param event - The event name
12
+ * @param payload - The payload to send
13
+ */
14
+ send: <T>(event: string, payload: T) => void;
15
+ /**
16
+ * Receive a message from a dev toolbar app.
17
+ * @param event
18
+ * @param callback
19
+ */
20
+ on: <T_1>(event: string, callback: (data: T_1) => void) => void;
21
+ /**
22
+ * Fired when an app is initialized.
23
+ * @param appId - The id of the app that was initialized
24
+ * @param callback - The callback to run when the app is initialized
25
+ */
26
+ onAppInitialized: (appId: string, callback: (data: Record<string, never>) => void) => void;
27
+ /**
28
+ * Fired when an app is toggled on or off.
29
+ * @param appId - The id of the app that was toggled
30
+ * @param callback - The callback to run when the app is toggled
31
+ */
32
+ onAppToggled: (appId: string, callback: (data: {
33
+ state: boolean;
34
+ }) => void) => void;
35
+ };
8
36
  export declare function runHookConfigSetup({ settings, command, logger, isRestart, }: {
9
37
  settings: AstroSettings;
10
38
  command: 'dev' | 'build' | 'preview';
@@ -4,7 +4,7 @@ import { bold } from "kleur/colors";
4
4
  import { buildClientDirectiveEntrypoint } from "../core/client-directive/index.js";
5
5
  import { mergeConfig } from "../core/config/index.js";
6
6
  import { isServerLikeOutput } from "../prerender/utils.js";
7
- import { validateSupportedFeatures } from "./astroFeaturesValidation.js";
7
+ import { validateSupportedFeatures } from "./features-validation.js";
8
8
  async function withTakingALongTimeMsg({
9
9
  name,
10
10
  hookName,
@@ -33,6 +33,43 @@ function getLogger(integration, logger) {
33
33
  Loggers.set(integration, integrationLogger);
34
34
  return integrationLogger;
35
35
  }
36
+ const serverEventPrefix = "astro-dev-toolbar";
37
+ function getToolbarServerCommunicationHelpers(server) {
38
+ return {
39
+ /**
40
+ * Send a message to the dev toolbar that an app can listen for. The payload can be any serializable data.
41
+ * @param event - The event name
42
+ * @param payload - The payload to send
43
+ */
44
+ send: (event, payload) => {
45
+ server.hot.send(event, payload);
46
+ },
47
+ /**
48
+ * Receive a message from a dev toolbar app.
49
+ * @param event
50
+ * @param callback
51
+ */
52
+ on: (event, callback) => {
53
+ server.hot.on(event, callback);
54
+ },
55
+ /**
56
+ * Fired when an app is initialized.
57
+ * @param appId - The id of the app that was initialized
58
+ * @param callback - The callback to run when the app is initialized
59
+ */
60
+ onAppInitialized: (appId, callback) => {
61
+ server.hot.on(`${serverEventPrefix}:${appId}:initialized`, callback);
62
+ },
63
+ /**
64
+ * Fired when an app is toggled on or off.
65
+ * @param appId - The id of the app that was toggled
66
+ * @param callback - The callback to run when the app is toggled
67
+ */
68
+ onAppToggled: (appId, callback) => {
69
+ server.hot.on(`${serverEventPrefix}:${appId}:toggled`, callback);
70
+ }
71
+ };
72
+ }
36
73
  async function runHookConfigSetup({
37
74
  settings,
38
75
  command,
@@ -219,7 +256,8 @@ async function runHookServerSetup({
219
256
  hookName: "astro:server:setup",
220
257
  hookResult: integration.hooks["astro:server:setup"]({
221
258
  server,
222
- logger: getLogger(integration, logger)
259
+ logger: getLogger(integration, logger),
260
+ toolbar: getToolbarServerCommunicationHelpers(server)
223
261
  }),
224
262
  logger
225
263
  });
@@ -384,6 +422,7 @@ function isFunctionPerRouteEnabled(adapter) {
384
422
  }
385
423
  }
386
424
  export {
425
+ getToolbarServerCommunicationHelpers,
387
426
  isFunctionPerRouteEnabled,
388
427
  runHookBuildDone,
389
428
  runHookBuildGenerated,
@@ -3,5 +3,14 @@ export declare const DEFAULT_PREFERENCES: {
3
3
  /** Specifies whether the user has the Dev Overlay enabled */
4
4
  enabled: boolean;
5
5
  };
6
+ checkUpdates: {
7
+ /** Specifies whether the user has the update check enabled */
8
+ enabled: boolean;
9
+ };
10
+ _variables: {
11
+ /** Time since last update check */
12
+ lastUpdateCheck: number;
13
+ };
6
14
  };
7
15
  export type Preferences = typeof DEFAULT_PREFERENCES;
16
+ export type PublicPreferences = Omit<Preferences, '_variables'>;
@@ -2,6 +2,15 @@ const DEFAULT_PREFERENCES = {
2
2
  devToolbar: {
3
3
  /** Specifies whether the user has the Dev Overlay enabled */
4
4
  enabled: true
5
+ },
6
+ checkUpdates: {
7
+ /** Specifies whether the user has the update check enabled */
8
+ enabled: true
9
+ },
10
+ // Temporary variables that shouldn't be exposed to the users in the CLI, but are still useful to store in preferences
11
+ _variables: {
12
+ /** Time since last update check */
13
+ lastUpdateCheck: 0
5
14
  }
6
15
  };
7
16
  export {
@@ -1,5 +1,5 @@
1
1
  import type { AstroConfig } from '../@types/astro.js';
2
- import { type Preferences } from './defaults.js';
2
+ import { type Preferences, type PublicPreferences } from './defaults.js';
3
3
  type DotKeys<T> = T extends object ? {
4
4
  [K in keyof T]: `${Exclude<K, symbol>}${DotKeys<T[K]> extends never ? '' : `.${DotKeys<T[K]>}`}`;
5
5
  }[keyof T] : never;
@@ -7,20 +7,28 @@ export type GetDotKey<T extends Record<string | number, any>, K extends string>
7
7
  export type PreferenceLocation = 'global' | 'project';
8
8
  export interface PreferenceOptions {
9
9
  location?: PreferenceLocation;
10
+ /**
11
+ * If `true`, the server will be reloaded after setting the preference.
12
+ * If `false`, the server will not be reloaded after setting the preference.
13
+ *
14
+ * Defaults to `true`.
15
+ */
16
+ reloadServer?: boolean;
10
17
  }
11
18
  type DeepPartial<T> = T extends object ? {
12
19
  [P in keyof T]?: DeepPartial<T[P]>;
13
20
  } : T;
14
21
  export type PreferenceKey = DotKeys<Preferences>;
15
- export interface PreferenceList extends Record<PreferenceLocation, DeepPartial<Preferences>> {
22
+ export interface PreferenceList extends Record<PreferenceLocation, DeepPartial<PublicPreferences>> {
16
23
  fromAstroConfig: DeepPartial<Preferences>;
17
- defaults: Preferences;
24
+ defaults: PublicPreferences;
18
25
  }
19
26
  export interface AstroPreferences {
20
27
  get<Key extends PreferenceKey>(key: Key, opts?: PreferenceOptions): Promise<GetDotKey<Preferences, Key>>;
21
28
  set<Key extends PreferenceKey>(key: Key, value: GetDotKey<Preferences, Key>, opts?: PreferenceOptions): Promise<void>;
22
- getAll(): Promise<Preferences>;
29
+ getAll(): Promise<PublicPreferences>;
23
30
  list(opts?: PreferenceOptions): Promise<PreferenceList>;
31
+ ignoreNextPreferenceReload: boolean;
24
32
  }
25
33
  export declare function isValidKey(key: string): key is PreferenceKey;
26
34
  export declare function coerce(key: string, value: unknown): any;
@@ -37,30 +37,37 @@ function createPreferences(config) {
37
37
  return project.get(key) ?? global.get(key) ?? dget(DEFAULT_PREFERENCES, key);
38
38
  return stores[location].get(key);
39
39
  },
40
- async set(key, value, { location = "project" } = {}) {
40
+ async set(key, value, { location = "project", reloadServer = true } = {}) {
41
41
  stores[location].set(key, value);
42
+ if (!reloadServer) {
43
+ this.ignoreNextPreferenceReload = true;
44
+ }
42
45
  },
43
46
  async getAll() {
44
- return Object.assign(
47
+ const allPrefs = Object.assign(
45
48
  {},
46
49
  DEFAULT_PREFERENCES,
47
50
  stores["global"].getAll(),
48
51
  stores["project"].getAll()
49
52
  );
53
+ const { _variables, ...prefs } = allPrefs;
54
+ return prefs;
50
55
  },
51
56
  async list() {
57
+ const { _variables, ...defaultPrefs } = DEFAULT_PREFERENCES;
52
58
  return {
53
59
  global: stores["global"].getAll(),
54
60
  project: stores["project"].getAll(),
55
61
  fromAstroConfig: mapFrom(DEFAULT_PREFERENCES, config),
56
- defaults: DEFAULT_PREFERENCES
62
+ defaults: defaultPrefs
57
63
  };
58
64
  function mapFrom(defaults, astroConfig) {
59
65
  return Object.fromEntries(
60
66
  Object.entries(defaults).map(([key, _]) => [key, astroConfig[key]])
61
67
  );
62
68
  }
63
- }
69
+ },
70
+ ignoreNextPreferenceReload: false
64
71
  };
65
72
  }
66
73
  function getGlobalPreferenceDir() {
@@ -2,6 +2,6 @@ import type { AstroConfig } from '../@types/astro.js';
2
2
  export declare function isServerLikeOutput(config: AstroConfig): boolean;
3
3
  export declare function getPrerenderDefault(config: AstroConfig): boolean;
4
4
  /**
5
- * Returns the correct output directory of hte SSR build based on the configuration
5
+ * Returns the correct output directory of the SSR build based on the configuration
6
6
  */
7
7
  export declare function getOutputDirectory(config: AstroConfig): URL;
@@ -15,6 +15,6 @@ declare const _default: {
15
15
  id: string;
16
16
  name: string;
17
17
  icon: "astro:logo";
18
- init(canvas: ShadowRoot, eventTarget: EventTarget): Promise<void>;
18
+ init(canvas: ShadowRoot, eventTarget: import("../helpers.js").ToolbarAppEventTarget): Promise<void>;
19
19
  };
20
20
  export default _default;
@@ -59,6 +59,7 @@ var astro_default = {
59
59
  link: "https://astro.build/chat"
60
60
  }
61
61
  ];
62
+ const hasNewerVersion = window.__astro_dev_toolbar__.latestAstroVersion;
62
63
  const windowComponent = createWindowElement(
63
64
  `<style>
64
65
  #buttons-container {
@@ -301,6 +302,8 @@ var astro_default = {
301
302
  <section>
302
303
  ${astroLogo}
303
304
  <astro-dev-toolbar-badge badge-style="gray" size="large">${window.__astro_dev_toolbar__.version}</astro-dev-toolbar-badge>
305
+ ${hasNewerVersion ? `<astro-dev-toolbar-badge badge-style="green" size="large">${window.__astro_dev_toolbar__.latestAstroVersion} available!</astro-dev-toolbar-badge>
306
+ ` : ""}
304
307
  </section>
305
308
  <astro-dev-toolbar-button id="copy-debug-button">Copy debug info <astro-dev-toolbar-icon icon="copy" /></astro-dev-toolbar-button>
306
309
  </header>
@@ -10,6 +10,6 @@ declare const _default: {
10
10
  id: string;
11
11
  name: string;
12
12
  icon: "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 1 20 16\"><path fill=\"#fff\" d=\"M.6 2A1.1 1.1 0 0 1 1.7.9h16.6a1.1 1.1 0 1 1 0 2.2H1.6A1.1 1.1 0 0 1 .8 2Zm1.1 7.1h6a1.1 1.1 0 0 0 0-2.2h-6a1.1 1.1 0 0 0 0 2.2ZM9.3 13H1.8a1.1 1.1 0 1 0 0 2.2h7.5a1.1 1.1 0 1 0 0-2.2Zm11.3 1.9a1.1 1.1 0 0 1-1.5 0l-1.7-1.7a4.1 4.1 0 1 1 1.6-1.6l1.6 1.7a1.1 1.1 0 0 1 0 1.6Zm-5.3-3.4a1.9 1.9 0 1 0 0-3.8 1.9 1.9 0 0 0 0 3.8Z\"/></svg>";
13
- init(canvas: ShadowRoot, eventTarget: EventTarget): Promise<void>;
13
+ init(canvas: ShadowRoot, eventTarget: import("../../helpers.js").ToolbarAppEventTarget): Promise<void>;
14
14
  };
15
15
  export default _default;
@@ -2,6 +2,6 @@ declare const _default: {
2
2
  id: string;
3
3
  name: string;
4
4
  icon: "gear";
5
- init(canvas: ShadowRoot, eventTarget: EventTarget): void;
5
+ init(canvas: ShadowRoot, eventTarget: import("../helpers.js").ToolbarAppEventTarget): void;
6
6
  };
7
7
  export default _default;
@@ -2,6 +2,6 @@ declare const _default: {
2
2
  id: string;
3
3
  name: string;
4
4
  icon: "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\"><path fill=\"#fff\" d=\"M7.9 1.5v-.4a1.1 1.1 0 0 1 2.2 0v.4a1.1 1.1 0 1 1-2.2 0Zm-6.4 8.6a1.1 1.1 0 1 0 0-2.2h-.4a1.1 1.1 0 0 0 0 2.2h.4ZM12 3.7a1.1 1.1 0 0 0 1.4-.7l.4-1.1a1.1 1.1 0 0 0-2.1-.8l-.4 1.2a1.1 1.1 0 0 0 .7 1.4Zm-9.7 7.6-1.2.4a1.1 1.1 0 1 0 .8 2.1l1-.4a1.1 1.1 0 1 0-.6-2ZM20.8 17a1.9 1.9 0 0 1 0 2.6l-1.2 1.2a1.9 1.9 0 0 1-2.6 0l-4.3-4.2-1.6 3.6a1.9 1.9 0 0 1-1.7 1.2A1.9 1.9 0 0 1 7.5 20L2.7 5a1.9 1.9 0 0 1 2.4-2.4l15 5a1.9 1.9 0 0 1 .2 3.4l-3.7 1.6 4.2 4.3ZM19 18.3 14.6 14a1.9 1.9 0 0 1 .6-3l3.2-1.5L5.1 5.1l4.3 13.3 1.5-3.2a1.9 1.9 0 0 1 3-.6l4.4 4.4.7-.7Z\"/></svg>";
5
- init(canvas: ShadowRoot, eventTarget: EventTarget): void;
5
+ init(canvas: ShadowRoot, eventTarget: import("../helpers.js").ToolbarAppEventTarget): void;
6
6
  };
7
7
  export default _default;
@@ -1,4 +1,5 @@
1
- import { loadDevToolbarApps } from "astro:dev-toolbar";
1
+ import { loadDevToolbarApps } from "astro:toolbar:internal";
2
+ import { ToolbarAppEventTarget } from "./helpers.js";
2
3
  import { settings } from "./settings.js";
3
4
  let overlay;
4
5
  document.addEventListener("DOMContentLoaded", async () => {
@@ -60,7 +61,7 @@ document.addEventListener("DOMContentLoaded", async () => {
60
61
  info: '<svg viewBox="0 0 10 10" style="--fill:var(--fill-default);--fill-default:#3645D9;--fill-hover:#BDC3FF;"><rect width="9" height="9" x=".5" y=".5" fill="var(--fill)" stroke="#13151A" stroke-width="2" rx="1.5"/></svg>'
61
62
  };
62
63
  const prepareApp = (appDefinition, builtIn) => {
63
- const eventTarget = new EventTarget();
64
+ const eventTarget = new ToolbarAppEventTarget();
64
65
  const app = {
65
66
  ...appDefinition,
66
67
  builtIn,
@@ -0,0 +1,61 @@
1
+ type NotificationPayload = {
2
+ state: true;
3
+ level?: 'error' | 'warning' | 'info';
4
+ } | {
5
+ state: false;
6
+ };
7
+ type AppStatePayload = {
8
+ state: boolean;
9
+ };
10
+ type AppToggledEvent = (opts: {
11
+ state: boolean;
12
+ }) => void;
13
+ type ToolbarPlacementUpdatedEvent = (opts: {
14
+ placement: 'bottom-left' | 'bottom-center' | 'bottom-right';
15
+ }) => void;
16
+ export declare class ToolbarAppEventTarget extends EventTarget {
17
+ constructor();
18
+ /**
19
+ * Toggle the notification state of the toolbar
20
+ * @param options - The notification options
21
+ * @param options.state - The state of the notification
22
+ * @param options.level - The level of the notification, optional when state is false
23
+ */
24
+ toggleNotification(options: NotificationPayload): void;
25
+ /**
26
+ * Toggle the app state on or off
27
+ * @param options - The app state options
28
+ * @param options.state - The new state of the app
29
+ */
30
+ toggleState(options: AppStatePayload): void;
31
+ /**
32
+ * Fired when the app is toggled on or off
33
+ * @param callback - The callback to run when the event is fired, takes an object with the new state
34
+ */
35
+ onToggled(callback: AppToggledEvent): void;
36
+ /**
37
+ * Fired when the toolbar placement is updated by the user
38
+ * @param callback - The callback to run when the event is fired, takes an object with the new placement
39
+ */
40
+ onToolbarPlacementUpdated(callback: ToolbarPlacementUpdatedEvent): void;
41
+ }
42
+ export declare const serverHelpers: {
43
+ /**
44
+ * Send a message to the server, the payload can be any serializable data.
45
+ *
46
+ * The server can listen for this message in the `astro:server:config` hook of an Astro integration, using the `toolbar.on` method.
47
+ *
48
+ * @param event - The event name
49
+ * @param payload - The payload to send
50
+ */
51
+ send: <T>(event: string, payload: T) => void;
52
+ /**
53
+ * Receive a message from the server.
54
+ * @param event - The event name
55
+ * @param callback - The callback to run when the event is received.
56
+ * The payload's content will be passed to the callback as an argument
57
+ */
58
+ on: <T_1>(event: string, callback: (data: T_1) => void) => void;
59
+ };
60
+ export type ToolbarServerHelpers = typeof serverHelpers;
61
+ export {};
@@ -0,0 +1,87 @@
1
+ class ToolbarAppEventTarget extends EventTarget {
2
+ constructor() {
3
+ super();
4
+ }
5
+ /**
6
+ * Toggle the notification state of the toolbar
7
+ * @param options - The notification options
8
+ * @param options.state - The state of the notification
9
+ * @param options.level - The level of the notification, optional when state is false
10
+ */
11
+ toggleNotification(options) {
12
+ this.dispatchEvent(
13
+ new CustomEvent("toggle-notification", {
14
+ detail: {
15
+ state: options.state,
16
+ level: options.state === true ? options.level : void 0
17
+ }
18
+ })
19
+ );
20
+ }
21
+ /**
22
+ * Toggle the app state on or off
23
+ * @param options - The app state options
24
+ * @param options.state - The new state of the app
25
+ */
26
+ toggleState(options) {
27
+ this.dispatchEvent(
28
+ new CustomEvent("toggle-app", {
29
+ detail: {
30
+ state: options.state
31
+ }
32
+ })
33
+ );
34
+ }
35
+ /**
36
+ * Fired when the app is toggled on or off
37
+ * @param callback - The callback to run when the event is fired, takes an object with the new state
38
+ */
39
+ onToggled(callback) {
40
+ this.addEventListener("app-toggled", (evt) => {
41
+ if (!(evt instanceof CustomEvent))
42
+ return;
43
+ callback(evt.detail);
44
+ });
45
+ }
46
+ /**
47
+ * Fired when the toolbar placement is updated by the user
48
+ * @param callback - The callback to run when the event is fired, takes an object with the new placement
49
+ */
50
+ onToolbarPlacementUpdated(callback) {
51
+ this.addEventListener("placement-updated", (evt) => {
52
+ if (!(evt instanceof CustomEvent))
53
+ return;
54
+ callback(evt.detail);
55
+ });
56
+ }
57
+ }
58
+ const serverHelpers = {
59
+ /**
60
+ * Send a message to the server, the payload can be any serializable data.
61
+ *
62
+ * The server can listen for this message in the `astro:server:config` hook of an Astro integration, using the `toolbar.on` method.
63
+ *
64
+ * @param event - The event name
65
+ * @param payload - The payload to send
66
+ */
67
+ send: (event, payload) => {
68
+ if (import.meta.hot) {
69
+ import.meta.hot.send(event, payload);
70
+ }
71
+ },
72
+ /**
73
+ * Receive a message from the server.
74
+ * @param event - The event name
75
+ * @param callback - The callback to run when the event is received.
76
+ * The payload's content will be passed to the callback as an argument
77
+ */
78
+ on: (event, callback) => {
79
+ if (import.meta.hot) {
80
+ import.meta.hot.on(event, callback);
81
+ }
82
+ }
83
+ };
84
+ export {
85
+ ToolbarAppEventTarget,
86
+ serverHelpers
87
+ };
@@ -1,4 +1,5 @@
1
- import type { DevToolbarApp as DevToolbarAppDefinition } from '../../../@types/astro.js';
1
+ import type { ResolvedDevToolbarApp as DevToolbarAppDefinition } from '../../../@types/astro.js';
2
+ import { type ToolbarAppEventTarget } from './helpers.js';
2
3
  import { type Icon } from './ui-library/icons.js';
3
4
  import { type Placement } from './ui-library/window.js';
4
5
  export type DevToolbarApp = DevToolbarAppDefinition & {
@@ -9,7 +10,7 @@ export type DevToolbarApp = DevToolbarAppDefinition & {
9
10
  state: boolean;
10
11
  level?: 'error' | 'warning' | 'info';
11
12
  };
12
- eventTarget: EventTarget;
13
+ eventTarget: ToolbarAppEventTarget;
13
14
  };
14
15
  export declare class AstroDevToolbar extends HTMLElement {
15
16
  shadowRoot: ShadowRoot;
@@ -1,3 +1,4 @@
1
+ import { serverHelpers } from "./helpers.js";
1
2
  import { settings } from "./settings.js";
2
3
  import { getIconElement, isDefinedIcon } from "./ui-library/icons.js";
3
4
  import {} from "./ui-library/window.js";
@@ -340,7 +341,7 @@ class AstroDevToolbar extends HTMLElement {
340
341
  app.status = "loading";
341
342
  try {
342
343
  settings.logger.verboseLog(`Initializing app ${app.id}`);
343
- await app.init?.(shadowRoot, app.eventTarget);
344
+ await app.init?.(shadowRoot, app.eventTarget, serverHelpers);
344
345
  app.status = "ready";
345
346
  if (import.meta.hot) {
346
347
  import.meta.hot.send(`${WS_EVENT_NAME}:${app.id}:initialized`);
@@ -21,7 +21,7 @@ function createAstroGlobFn() {
21
21
  }
22
22
  function createAstro(site) {
23
23
  return {
24
- // TODO: this is no longer neccessary for `Astro.site`
24
+ // TODO: this is no longer necessary for `Astro.site`
25
25
  // but it somehow allows working around caching issues in content collections for some tests
26
26
  site: site ? new URL(site) : void 0,
27
27
  generator: `Astro v${ASTRO_VERSION}`,
@@ -31,20 +31,20 @@ class AstroComponentInstance {
31
31
  if (this.returnValue !== void 0)
32
32
  return this.returnValue;
33
33
  this.returnValue = this.factory(result, this.props, this.slotValues);
34
+ if (isPromise(this.returnValue)) {
35
+ this.returnValue.then((resolved) => {
36
+ this.returnValue = resolved;
37
+ }).catch(() => {
38
+ });
39
+ }
34
40
  return this.returnValue;
35
41
  }
36
42
  async render(destination) {
37
- if (this.returnValue === void 0) {
38
- await this.init(this.result);
39
- }
40
- let value = this.returnValue;
41
- if (isPromise(value)) {
42
- value = await value;
43
- }
44
- if (isHeadAndContent(value)) {
45
- await value.content.render(destination);
43
+ const returnValue = await this.init(this.result);
44
+ if (isHeadAndContent(returnValue)) {
45
+ await returnValue.content.render(destination);
46
46
  } else {
47
- await renderChild(destination, value);
47
+ await renderChild(destination, returnValue);
48
48
  }
49
49
  }
50
50
  }
@@ -4,13 +4,15 @@ const voidElementNames = /^(area|base|br|col|command|embed|hr|img|input|keygen|l
4
4
  const htmlBooleanAttributes = /^(?:allowfullscreen|async|autofocus|autoplay|controls|default|defer|disabled|disablepictureinpicture|disableremoteplayback|formnovalidate|hidden|loop|nomodule|novalidate|open|playsinline|readonly|required|reversed|scoped|seamless|itemscope)$/i;
5
5
  const htmlEnumAttributes = /^(?:contenteditable|draggable|spellcheck|value)$/i;
6
6
  const svgEnumAttributes = /^(?:autoReverse|externalResourcesRequired|focusable|preserveAlpha)$/i;
7
+ const AMPERSAND_REGEX = /&/g;
8
+ const DOUBLE_QUOTE_REGEX = /"/g;
7
9
  const STATIC_DIRECTIVES = /* @__PURE__ */ new Set(["set:html", "set:text"]);
8
10
  const toIdent = (k) => k.trim().replace(/(?!^)\b\w|\s+|\W+/g, (match, index) => {
9
11
  if (/\W/.test(match))
10
12
  return "";
11
13
  return index === 0 ? match : match.toUpperCase();
12
14
  });
13
- const toAttributeString = (value, shouldEscape = true) => shouldEscape ? String(value).replace(/&/g, "&#38;").replace(/"/g, "&#34;") : value;
15
+ const toAttributeString = (value, shouldEscape = true) => shouldEscape ? String(value).replace(AMPERSAND_REGEX, "&#38;").replace(DOUBLE_QUOTE_REGEX, "&#34;") : value;
14
16
  const kebab = (k) => k.toLowerCase() === k ? k : k.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
15
17
  const toStyleString = (obj) => Object.entries(obj).filter(([_, v]) => typeof v === "string" && v.trim() || typeof v === "number").map(([k, v]) => {
16
18
  if (k[0] !== "-" && k[1] !== "-")
@@ -0,0 +1,2 @@
1
+ import type { DevToolbarApp } from '../@types/astro.js';
2
+ export declare function defineToolbarApp(app: DevToolbarApp): DevToolbarApp;
@@ -0,0 +1,6 @@
1
+ function defineToolbarApp(app) {
2
+ return app;
3
+ }
4
+ export {
5
+ defineToolbarApp
6
+ };