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
@@ -1,7 +1,7 @@
1
1
  import { telemetry } from "../events/index.js";
2
2
  import { eventAppToggled } from "../events/toolbar.js";
3
- const VIRTUAL_MODULE_ID = "astro:dev-toolbar";
4
- const resolvedVirtualModuleId = "\0" + VIRTUAL_MODULE_ID;
3
+ const PRIVATE_VIRTUAL_MODULE_ID = "astro:toolbar:internal";
4
+ const resolvedPrivateVirtualModuleId = "\0" + PRIVATE_VIRTUAL_MODULE_ID;
5
5
  function astroDevToolbar({ settings, logger }) {
6
6
  let telemetryTimeout;
7
7
  return {
@@ -15,8 +15,8 @@ function astroDevToolbar({ settings, logger }) {
15
15
  };
16
16
  },
17
17
  resolveId(id) {
18
- if (id === VIRTUAL_MODULE_ID) {
19
- return resolvedVirtualModuleId;
18
+ if (id === PRIVATE_VIRTUAL_MODULE_ID) {
19
+ return resolvedPrivateVirtualModuleId;
20
20
  }
21
21
  },
22
22
  configureServer(server) {
@@ -49,22 +49,43 @@ ${args.error}`
49
49
  });
50
50
  },
51
51
  async load(id) {
52
- if (id === resolvedVirtualModuleId) {
52
+ if (id === resolvedPrivateVirtualModuleId) {
53
53
  return `
54
54
  export const loadDevToolbarApps = async () => {
55
55
  return (await Promise.all([${settings.devToolbarApps.map(
56
- (plugin) => `safeLoadPlugin(async () => (await import(${JSON.stringify(
56
+ (plugin) => `safeLoadPlugin(${JSON.stringify(
57
57
  plugin
58
- )})).default, ${JSON.stringify(plugin)})`
59
- ).join(",")}])).filter(app => app);
58
+ )}, async () => (await import(${JSON.stringify(
59
+ typeof plugin === "string" ? plugin : plugin.entrypoint
60
+ )})).default, ${JSON.stringify(
61
+ typeof plugin === "string" ? plugin : plugin.entrypoint
62
+ )})`
63
+ ).join(",")}]));
60
64
  };
61
65
 
62
- async function safeLoadPlugin(importEntrypoint, entrypoint) {
66
+ async function safeLoadPlugin(appDefinition, importEntrypoint, entrypoint) {
63
67
  try {
64
- const app = await importEntrypoint();
68
+ let app;
69
+ if (typeof appDefinition === 'string') {
70
+ app = await importEntrypoint();
65
71
 
66
- if (typeof app !== 'object' || !app.id || !app.name) {
67
- throw new Error("Apps must default export an object with an id, and a name.");
72
+ if (typeof app !== 'object' || !app.id || !app.name) {
73
+ throw new Error("Apps must default export an object with an id, and a name.");
74
+ }
75
+ } else {
76
+ app = appDefinition;
77
+
78
+ if (typeof app !== 'object' || !app.id || !app.name || !app.entrypoint) {
79
+ throw new Error("Apps must be an object with an id, a name and an entrypoint.");
80
+ }
81
+
82
+ const loadedApp = await importEntrypoint();
83
+
84
+ if (typeof loadedApp !== 'object') {
85
+ throw new Error("App entrypoint must default export an object.");
86
+ }
87
+
88
+ app = { ...app, ...loadedApp };
68
89
  }
69
90
 
70
91
  return app;
@@ -16,13 +16,14 @@ declare class BeforeEvent extends Event {
16
16
  readonly sourceElement: Element | undefined;
17
17
  readonly info: any;
18
18
  newDocument: Document;
19
- constructor(type: string, eventInitDict: EventInit | undefined, from: URL, to: URL, direction: Direction | string, navigationType: NavigationTypeString, sourceElement: Element | undefined, info: any, newDocument: Document);
19
+ signal: AbortSignal;
20
+ constructor(type: string, eventInitDict: EventInit | undefined, from: URL, to: URL, direction: Direction | string, navigationType: NavigationTypeString, sourceElement: Element | undefined, info: any, newDocument: Document, signal: AbortSignal);
20
21
  }
21
22
  export declare const isTransitionBeforePreparationEvent: (value: any) => value is TransitionBeforePreparationEvent;
22
23
  export declare class TransitionBeforePreparationEvent extends BeforeEvent {
23
24
  formData: FormData | undefined;
24
25
  loader: () => Promise<void>;
25
- constructor(from: URL, to: URL, direction: Direction | string, navigationType: NavigationTypeString, sourceElement: Element | undefined, info: any, newDocument: Document, formData: FormData | undefined, loader: (event: TransitionBeforePreparationEvent) => Promise<void>);
26
+ constructor(from: URL, to: URL, direction: Direction | string, navigationType: NavigationTypeString, sourceElement: Element | undefined, info: any, newDocument: Document, signal: AbortSignal, formData: FormData | undefined, loader: (event: TransitionBeforePreparationEvent) => Promise<void>);
26
27
  }
27
28
  export declare const isTransitionBeforeSwapEvent: (value: any) => value is TransitionBeforeSwapEvent;
28
29
  export declare class TransitionBeforeSwapEvent extends BeforeEvent {
@@ -31,6 +32,6 @@ export declare class TransitionBeforeSwapEvent extends BeforeEvent {
31
32
  swap: () => void;
32
33
  constructor(afterPreparation: BeforeEvent, viewTransition: ViewTransition, swap: (event: TransitionBeforeSwapEvent) => void);
33
34
  }
34
- export declare function doPreparation(from: URL, to: URL, direction: Direction | string, navigationType: NavigationTypeString, sourceElement: Element | undefined, info: any, formData: FormData | undefined, defaultLoader: (event: TransitionBeforePreparationEvent) => Promise<void>): Promise<TransitionBeforePreparationEvent>;
35
- export declare function doSwap(afterPreparation: BeforeEvent, viewTransition: ViewTransition, defaultSwap: (event: TransitionBeforeSwapEvent) => void): Promise<TransitionBeforeSwapEvent>;
35
+ export declare function doPreparation(from: URL, to: URL, direction: Direction | string, navigationType: NavigationTypeString, sourceElement: Element | undefined, info: any, signal: AbortSignal, formData: FormData | undefined, defaultLoader: (event: TransitionBeforePreparationEvent) => Promise<void>): Promise<TransitionBeforePreparationEvent>;
36
+ export declare function doSwap(afterPreparation: BeforeEvent, viewTransition: ViewTransition, defaultSwap: (event: TransitionBeforeSwapEvent) => void): TransitionBeforeSwapEvent;
36
37
  export {};
@@ -14,7 +14,8 @@ class BeforeEvent extends Event {
14
14
  sourceElement;
15
15
  info;
16
16
  newDocument;
17
- constructor(type, eventInitDict, from, to, direction, navigationType, sourceElement, info, newDocument) {
17
+ signal;
18
+ constructor(type, eventInitDict, from, to, direction, navigationType, sourceElement, info, newDocument, signal) {
18
19
  super(type, eventInitDict);
19
20
  this.from = from;
20
21
  this.to = to;
@@ -23,6 +24,7 @@ class BeforeEvent extends Event {
23
24
  this.sourceElement = sourceElement;
24
25
  this.info = info;
25
26
  this.newDocument = newDocument;
27
+ this.signal = signal;
26
28
  Object.defineProperties(this, {
27
29
  from: { enumerable: true },
28
30
  to: { enumerable: true, writable: true },
@@ -30,7 +32,8 @@ class BeforeEvent extends Event {
30
32
  navigationType: { enumerable: true },
31
33
  sourceElement: { enumerable: true },
32
34
  info: { enumerable: true },
33
- newDocument: { enumerable: true, writable: true }
35
+ newDocument: { enumerable: true, writable: true },
36
+ signal: { enumerable: true }
34
37
  });
35
38
  }
36
39
  }
@@ -38,7 +41,7 @@ const isTransitionBeforePreparationEvent = (value) => value.type === TRANSITION_
38
41
  class TransitionBeforePreparationEvent extends BeforeEvent {
39
42
  formData;
40
43
  loader;
41
- constructor(from, to, direction, navigationType, sourceElement, info, newDocument, formData, loader) {
44
+ constructor(from, to, direction, navigationType, sourceElement, info, newDocument, signal, formData, loader) {
42
45
  super(
43
46
  TRANSITION_BEFORE_PREPARATION,
44
47
  { cancelable: true },
@@ -48,7 +51,8 @@ class TransitionBeforePreparationEvent extends BeforeEvent {
48
51
  navigationType,
49
52
  sourceElement,
50
53
  info,
51
- newDocument
54
+ newDocument,
55
+ signal
52
56
  );
53
57
  this.formData = formData;
54
58
  this.loader = loader.bind(this, this);
@@ -73,7 +77,8 @@ class TransitionBeforeSwapEvent extends BeforeEvent {
73
77
  afterPreparation.navigationType,
74
78
  afterPreparation.sourceElement,
75
79
  afterPreparation.info,
76
- afterPreparation.newDocument
80
+ afterPreparation.newDocument,
81
+ afterPreparation.signal
77
82
  );
78
83
  this.direction = afterPreparation.direction;
79
84
  this.viewTransition = viewTransition;
@@ -85,7 +90,7 @@ class TransitionBeforeSwapEvent extends BeforeEvent {
85
90
  });
86
91
  }
87
92
  }
88
- async function doPreparation(from, to, direction, navigationType, sourceElement, info, formData, defaultLoader) {
93
+ async function doPreparation(from, to, direction, navigationType, sourceElement, info, signal, formData, defaultLoader) {
89
94
  const event = new TransitionBeforePreparationEvent(
90
95
  from,
91
96
  to,
@@ -94,6 +99,7 @@ async function doPreparation(from, to, direction, navigationType, sourceElement,
94
99
  sourceElement,
95
100
  info,
96
101
  window.document,
102
+ signal,
97
103
  formData,
98
104
  defaultLoader
99
105
  );
@@ -108,7 +114,7 @@ async function doPreparation(from, to, direction, navigationType, sourceElement,
108
114
  }
109
115
  return event;
110
116
  }
111
- async function doSwap(afterPreparation, viewTransition, defaultSwap) {
117
+ function doSwap(afterPreparation, viewTransition, defaultSwap) {
112
118
  const event = new TransitionBeforeSwapEvent(afterPreparation, viewTransition, defaultSwap);
113
119
  document.dispatchEvent(event);
114
120
  event.swap();
@@ -11,10 +11,9 @@ const updateScrollPosition = (positions) => {
11
11
  const supportsViewTransitions = inBrowser && !!document.startViewTransition;
12
12
  const transitionEnabledOnThisPage = () => inBrowser && !!document.querySelector('[name="astro-view-transitions-enabled"]');
13
13
  const samePage = (thisLocation, otherLocation) => thisLocation.pathname === otherLocation.pathname && thisLocation.search === otherLocation.search;
14
+ let mostRecentNavigation;
15
+ let mostRecentTransition;
14
16
  let originalLocation;
15
- let viewTransition;
16
- let skipTransition = false;
17
- let viewTransitionFinished;
18
17
  const triggerEvent = (name) => document.dispatchEvent(new Event(name));
19
18
  const onPageLoad = () => triggerEvent("astro:page-load");
20
19
  const announce = () => {
@@ -173,7 +172,7 @@ function preloadStyleLinks(newDocument) {
173
172
  }
174
173
  return links;
175
174
  }
176
- async function updateDOM(preparationEvent, options, historyState, fallback) {
175
+ async function updateDOM(preparationEvent, options, currentTransition, historyState, fallback) {
177
176
  const persistedHeadElement = (el, newDoc) => {
178
177
  const id = el.getAttribute(PERSIST_ATTR);
179
178
  const newEl = id && newDoc.head.querySelector(`[${PERSIST_ATTR}="${id}"]`);
@@ -274,26 +273,37 @@ async function updateDOM(preparationEvent, options, historyState, fallback) {
274
273
  const newAnimations = nextAnimations.filter(
275
274
  (a) => !currentAnimations.includes(a) && !isInfinite(a)
276
275
  );
277
- return Promise.all(newAnimations.map((a) => a.finished));
276
+ return Promise.allSettled(newAnimations.map((a) => a.finished));
278
277
  }
279
- if (!skipTransition) {
280
- document.documentElement.setAttribute(DIRECTION_ATTR, preparationEvent.direction);
281
- if (fallback === "animate") {
278
+ if (fallback === "animate" && !currentTransition.transitionSkipped && !preparationEvent.signal.aborted) {
279
+ try {
282
280
  await animate("old");
281
+ } catch (err) {
283
282
  }
284
- } else {
285
- throw new DOMException("Transition was skipped");
286
283
  }
287
284
  const pageTitleForBrowserHistory = document.title;
288
- const swapEvent = await doSwap(preparationEvent, viewTransition, defaultSwap);
285
+ const swapEvent = doSwap(preparationEvent, currentTransition.viewTransition, defaultSwap);
289
286
  moveToLocation(swapEvent.to, swapEvent.from, options, pageTitleForBrowserHistory, historyState);
290
287
  triggerEvent(TRANSITION_AFTER_SWAP);
291
- if (fallback === "animate" && !skipTransition) {
292
- animate("new").then(() => viewTransitionFinished());
288
+ if (fallback === "animate") {
289
+ if (!currentTransition.transitionSkipped && !swapEvent.signal.aborted) {
290
+ animate("new").finally(() => currentTransition.viewTransitionFinished());
291
+ } else {
292
+ currentTransition.viewTransitionFinished();
293
+ }
293
294
  }
294
295
  }
296
+ function abortAndRecreateMostRecentNavigation() {
297
+ mostRecentNavigation?.controller.abort();
298
+ return mostRecentNavigation = {
299
+ controller: new AbortController()
300
+ };
301
+ }
295
302
  async function transition(direction, from, to, options, historyState) {
303
+ const currentNavigation = abortAndRecreateMostRecentNavigation();
296
304
  if (!transitionEnabledOnThisPage() || location.origin !== to.origin) {
305
+ if (currentNavigation === mostRecentNavigation)
306
+ mostRecentNavigation = void 0;
297
307
  location.href = to.href;
298
308
  return;
299
309
  }
@@ -304,6 +314,8 @@ async function transition(direction, from, to, options, historyState) {
304
314
  if (samePage(from, to)) {
305
315
  if (direction !== "back" && to.hash || direction === "back" && from.hash) {
306
316
  moveToLocation(to, from, options, document.title, historyState);
317
+ if (currentNavigation === mostRecentNavigation)
318
+ mostRecentNavigation = void 0;
307
319
  return;
308
320
  }
309
321
  }
@@ -314,16 +326,21 @@ async function transition(direction, from, to, options, historyState) {
314
326
  navigationType,
315
327
  options.sourceElement,
316
328
  options.info,
329
+ currentNavigation.controller.signal,
317
330
  options.formData,
318
331
  defaultLoader
319
332
  );
320
- if (prepEvent.defaultPrevented) {
321
- location.href = to.href;
333
+ if (prepEvent.defaultPrevented || prepEvent.signal.aborted) {
334
+ if (currentNavigation === mostRecentNavigation)
335
+ mostRecentNavigation = void 0;
336
+ if (!prepEvent.signal.aborted) {
337
+ location.href = to.href;
338
+ }
322
339
  return;
323
340
  }
324
341
  async function defaultLoader(preparationEvent) {
325
342
  const href = preparationEvent.to.href;
326
- const init = {};
343
+ const init = { signal: preparationEvent.signal };
327
344
  if (preparationEvent.formData) {
328
345
  init.method = "POST";
329
346
  const form = preparationEvent.sourceElement instanceof HTMLFormElement ? preparationEvent.sourceElement : preparationEvent.sourceElement instanceof HTMLElement && "form" in preparationEvent.sourceElement ? preparationEvent.sourceElement.form : preparationEvent.sourceElement?.closest("form");
@@ -345,42 +362,80 @@ async function transition(direction, from, to, options, historyState) {
345
362
  return;
346
363
  }
347
364
  const links = preloadStyleLinks(preparationEvent.newDocument);
348
- links.length && await Promise.all(links);
349
- if (import.meta.env.DEV)
350
- await prepareForClientOnlyComponents(preparationEvent.newDocument, preparationEvent.to);
365
+ links.length && !preparationEvent.signal.aborted && await Promise.all(links);
366
+ if (import.meta.env.DEV && !preparationEvent.signal.aborted)
367
+ await prepareForClientOnlyComponents(
368
+ preparationEvent.newDocument,
369
+ preparationEvent.to,
370
+ preparationEvent.signal
371
+ );
351
372
  }
352
- skipTransition = false;
373
+ async function abortAndRecreateMostRecentTransition() {
374
+ if (mostRecentTransition) {
375
+ if (mostRecentTransition.viewTransition) {
376
+ try {
377
+ mostRecentTransition.viewTransition.skipTransition();
378
+ } catch {
379
+ }
380
+ try {
381
+ await mostRecentTransition.viewTransition.updateCallbackDone;
382
+ } catch {
383
+ }
384
+ }
385
+ }
386
+ return mostRecentTransition = { transitionSkipped: false };
387
+ }
388
+ const currentTransition = await abortAndRecreateMostRecentTransition();
389
+ if (prepEvent.signal.aborted) {
390
+ if (currentNavigation === mostRecentNavigation)
391
+ mostRecentNavigation = void 0;
392
+ return;
393
+ }
394
+ document.documentElement.setAttribute(DIRECTION_ATTR, prepEvent.direction);
353
395
  if (supportsViewTransitions) {
354
- viewTransition = document.startViewTransition(
355
- async () => await updateDOM(prepEvent, options, historyState)
396
+ currentTransition.viewTransition = document.startViewTransition(
397
+ async () => await updateDOM(prepEvent, options, currentTransition, historyState)
356
398
  );
357
399
  } else {
358
400
  const updateDone = (async () => {
359
- await new Promise((r) => setTimeout(r));
360
- await updateDOM(prepEvent, options, historyState, getFallback());
401
+ await Promise.resolve();
402
+ await updateDOM(prepEvent, options, currentTransition, historyState, getFallback());
361
403
  })();
362
- viewTransition = {
404
+ currentTransition.viewTransition = {
363
405
  updateCallbackDone: updateDone,
364
406
  // this is about correct
365
407
  ready: updateDone,
366
408
  // good enough
367
- finished: new Promise((r) => viewTransitionFinished = r),
409
+ // Finished promise could have been done better: finished rejects iff updateDone does.
410
+ // Our simulation always resolves, never rejects.
411
+ finished: new Promise((r) => currentTransition.viewTransitionFinished = r),
368
412
  // see end of updateDOM
369
413
  skipTransition: () => {
370
- skipTransition = true;
414
+ currentTransition.transitionSkipped = true;
415
+ document.documentElement.removeAttribute(OLD_NEW_ATTR);
371
416
  }
372
417
  };
373
418
  }
374
- viewTransition.ready.then(async () => {
419
+ currentTransition.viewTransition.updateCallbackDone.finally(async () => {
375
420
  await runScripts();
376
421
  onPageLoad();
377
422
  announce();
378
423
  });
379
- viewTransition.finished.then(() => {
424
+ currentTransition.viewTransition.finished.finally(() => {
425
+ currentTransition.viewTransition = void 0;
426
+ if (currentTransition === mostRecentTransition)
427
+ mostRecentTransition = void 0;
428
+ if (currentNavigation === mostRecentNavigation)
429
+ mostRecentNavigation = void 0;
380
430
  document.documentElement.removeAttribute(DIRECTION_ATTR);
381
431
  document.documentElement.removeAttribute(OLD_NEW_ATTR);
382
432
  });
383
- await viewTransition.ready;
433
+ try {
434
+ await currentTransition.viewTransition.updateCallbackDone;
435
+ } catch (e) {
436
+ const err = e;
437
+ console.log("[astro]", err.name, err.message, err.stack);
438
+ }
384
439
  }
385
440
  let navigateOnServerWarned = false;
386
441
  async function navigate(href, options) {
@@ -456,7 +511,7 @@ if (inBrowser) {
456
511
  script.dataset.astroExec = "";
457
512
  }
458
513
  }
459
- async function prepareForClientOnlyComponents(newDocument, toLocation) {
514
+ async function prepareForClientOnlyComponents(newDocument, toLocation, signal) {
460
515
  if (newDocument.body.querySelector(`astro-island[client='only']`)) {
461
516
  const nextPage = document.createElement("iframe");
462
517
  nextPage.src = toLocation.href;
@@ -481,11 +536,15 @@ async function prepareForClientOnlyComponents(newDocument, toLocation) {
481
536
  });
482
537
  }
483
538
  async function hydrationDone(loadingPage) {
484
- await new Promise(
485
- (r) => loadingPage.contentWindow?.addEventListener("load", r, { once: true })
486
- );
539
+ if (!signal.aborted) {
540
+ await new Promise(
541
+ (r) => loadingPage.contentWindow?.addEventListener("load", r, { once: true })
542
+ );
543
+ }
487
544
  return new Promise(async (r) => {
488
545
  for (let count = 0; count <= 20; ++count) {
546
+ if (signal.aborted)
547
+ break;
489
548
  if (!loadingPage.contentDocument.body.querySelector("astro-island[ssr]"))
490
549
  break;
491
550
  await new Promise((r2) => setTimeout(r2, 50));
@@ -56,6 +56,7 @@ class DevPipeline extends Pipeline {
56
56
  const additionalMetadata = {
57
57
  root: url.fileURLToPath(settings.config.root),
58
58
  version: ASTRO_VERSION,
59
+ latestAstroVersion: settings.latestAstroVersion,
59
60
  debugInfo: await getInfoOutput({ userConfig: settings.config, print: false })
60
61
  };
61
62
  const children = `window.__astro_dev_toolbar__ = ${JSON.stringify(additionalMetadata)}`;
@@ -15,7 +15,7 @@ async function* crawlGraph(loader, _id, isRootFile, scanned = /* @__PURE__ */ ne
15
15
  loader.getModulesByFile(id) ?? /* @__PURE__ */ new Set()
16
16
  ) : (
17
17
  // For non-root files, we're safe to pull from "getModuleById" based on testing.
18
- // TODO: Find better invalidation strat to use "getModuleById" in all cases!
18
+ // TODO: Find better invalidation strategy to use "getModuleById" in all cases!
19
19
  /* @__PURE__ */ new Set([loader.getModuleById(id)])
20
20
  );
21
21
  for (const entry of moduleEntriesForId) {
@@ -24,14 +24,13 @@ async function* crawlGraph(loader, _id, isRootFile, scanned = /* @__PURE__ */ ne
24
24
  }
25
25
  if (id === entry.id) {
26
26
  scanned.add(id);
27
- const entryIsStyle = isCSSRequest(id);
27
+ if (isCSSRequest(id)) {
28
+ continue;
29
+ }
28
30
  for (const importedModule of entry.importedModules) {
29
31
  if (!importedModule.id)
30
32
  continue;
31
33
  const importedModulePathname = importedModule.id.replace(STRIP_QUERY_PARAMS_REGEX, "");
32
- if (entryIsStyle && !isCSSRequest(importedModulePathname)) {
33
- continue;
34
- }
35
34
  const isFileTypeNeedingSSR = fileExtensionsToSSR.has(npath.extname(importedModulePathname));
36
35
  const isPropagationStoppingPoint = ASTRO_PROPAGATED_ASSET_REGEX.test(importedModule.id);
37
36
  if (isFileTypeNeedingSSR && // Should not SSR a module with ?astroPropagatedAssets
@@ -1,5 +1,5 @@
1
1
  import { normalizePath } from "vite";
2
- import { runHookServerSetup } from "../integrations/index.js";
2
+ import { runHookServerSetup } from "../integrations/hooks.js";
3
3
  function astroIntegrationsContainerPlugin({
4
4
  settings,
5
5
  logger
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "4.6.4",
3
+ "version": "4.7.1",
4
4
  "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
5
5
  "type": "module",
6
6
  "author": "withastro",
@@ -53,6 +53,7 @@
53
53
  "./client/*": "./dist/runtime/client/*",
54
54
  "./components": "./components/index.ts",
55
55
  "./components/*": "./components/*",
56
+ "./toolbar": "./dist/toolbar/index.js",
56
57
  "./assets": "./dist/assets/index.js",
57
58
  "./assets/utils": "./dist/assets/utils/index.js",
58
59
  "./assets/endpoint/*": "./dist/assets/endpoint/*.js",
@@ -103,12 +104,12 @@
103
104
  ],
104
105
  "dependencies": {
105
106
  "@astrojs/compiler": "^2.7.1",
106
- "@babel/core": "^7.24.4",
107
- "@babel/generator": "^7.24.4",
108
- "@babel/parser": "^7.24.4",
107
+ "@babel/core": "^7.24.5",
108
+ "@babel/generator": "^7.24.5",
109
+ "@babel/parser": "^7.24.5",
109
110
  "@babel/plugin-transform-react-jsx": "^7.23.4",
110
- "@babel/traverse": "^7.24.1",
111
- "@babel/types": "^7.24.0",
111
+ "@babel/traverse": "^7.24.5",
112
+ "@babel/types": "^7.24.5",
112
113
  "@types/babel__core": "^7.20.5",
113
114
  "@types/cookie": "^0.6.0",
114
115
  "acorn": "^8.11.3",
@@ -117,7 +118,7 @@
117
118
  "boxen": "^7.1.1",
118
119
  "chokidar": "^3.6.0",
119
120
  "ci-info": "^4.0.0",
120
- "clsx": "^2.1.0",
121
+ "clsx": "^2.1.1",
121
122
  "common-ancestor-path": "^1.0.1",
122
123
  "cookie": "^0.6.0",
123
124
  "cssesc": "^3.0.0",
@@ -127,7 +128,7 @@
127
128
  "diff": "^5.2.0",
128
129
  "dlv": "^1.1.3",
129
130
  "dset": "^3.1.3",
130
- "es-module-lexer": "^1.5.0",
131
+ "es-module-lexer": "^1.5.2",
131
132
  "esbuild": "^0.20.2",
132
133
  "estree-walker": "^3.0.3",
133
134
  "execa": "^8.0.1",
@@ -160,14 +161,14 @@
160
161
  "vitefu": "^0.2.5",
161
162
  "which-pm": "^2.1.1",
162
163
  "yargs-parser": "^21.1.1",
163
- "zod": "^3.23.0",
164
- "zod-to-json-schema": "^3.22.5",
164
+ "zod": "^3.23.5",
165
+ "zod-to-json-schema": "^3.23.0",
165
166
  "@astrojs/internal-helpers": "0.4.0",
166
167
  "@astrojs/markdown-remark": "5.1.0",
167
168
  "@astrojs/telemetry": "3.1.0"
168
169
  },
169
170
  "optionalDependencies": {
170
- "sharp": "^0.32.6"
171
+ "sharp": "^0.33.3"
171
172
  },
172
173
  "devDependencies": {
173
174
  "@astrojs/check": "^0.5.10",
@@ -195,14 +196,14 @@
195
196
  "@types/yargs-parser": "^21.0.3",
196
197
  "cheerio": "1.0.0-rc.12",
197
198
  "eol": "^0.9.1",
198
- "memfs": "^4.8.2",
199
+ "memfs": "^4.9.1",
199
200
  "node-mocks-http": "^1.14.1",
200
201
  "parse-srcset": "^1.0.2",
201
202
  "rehype-autolink-headings": "^7.1.0",
202
203
  "rehype-slug": "^6.0.0",
203
204
  "rehype-toc": "^3.0.2",
204
205
  "remark-code-titles": "^0.1.2",
205
- "rollup": "^4.16.1",
206
+ "rollup": "^4.17.1",
206
207
  "sass": "^1.75.0",
207
208
  "srcset-parse": "^1.1.0",
208
209
  "unified": "^11.0.4",
@@ -19,8 +19,6 @@
19
19
  // Report an error for unreachable code instead of just a warning.
20
20
  "allowUnreachableCode": false,
21
21
  // Report an error for unused labels instead of just a warning.
22
- "allowUnusedLabels": false,
23
- // Disallow JavaScript files from being imported
24
- "allowJs": false
22
+ "allowUnusedLabels": false
25
23
  }
26
24
  }