astro 4.6.2 → 4.6.4

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 (56) hide show
  1. package/astro-jsx.d.ts +0 -2
  2. package/components/Image.astro +1 -1
  3. package/components/Picture.astro +1 -1
  4. package/components/ViewTransitions.astro +9 -2
  5. package/dist/@types/astro.d.ts +38 -37
  6. package/dist/assets/endpoint/generic.js +3 -3
  7. package/dist/assets/endpoint/node.js +3 -3
  8. package/dist/assets/utils/emitAsset.d.ts +6 -1
  9. package/dist/assets/utils/emitAsset.js +15 -9
  10. package/dist/assets/vite-plugin-assets.js +9 -2
  11. package/dist/cli/add/index.js +3 -3
  12. package/dist/cli/install-package.js +3 -1
  13. package/dist/config/index.js +2 -2
  14. package/dist/content/runtime-assets.d.ts +1 -1
  15. package/dist/content/runtime-assets.js +2 -2
  16. package/dist/content/runtime.d.ts +1 -1
  17. package/dist/content/utils.d.ts +1 -1
  18. package/dist/content/utils.js +2 -2
  19. package/dist/content/vite-plugin-content-imports.js +10 -2
  20. package/dist/core/app/createOutgoingHttpHeaders.d.ts +1 -0
  21. package/dist/core/build/consts.d.ts +1 -0
  22. package/dist/core/build/consts.js +4 -0
  23. package/dist/core/build/index.js +2 -1
  24. package/dist/core/build/internal.d.ts +1 -0
  25. package/dist/core/build/internal.js +2 -1
  26. package/dist/core/build/plugin.d.ts +1 -1
  27. package/dist/core/build/plugins/plugin-content.js +135 -30
  28. package/dist/core/build/plugins/util.d.ts +1 -1
  29. package/dist/core/build/static-build.d.ts +1 -1
  30. package/dist/core/build/static-build.js +3 -2
  31. package/dist/core/config/config.d.ts +1 -0
  32. package/dist/core/config/config.js +10 -8
  33. package/dist/core/config/index.d.ts +1 -1
  34. package/dist/core/config/index.js +8 -1
  35. package/dist/core/config/schema.d.ts +333 -290
  36. package/dist/core/constants.js +1 -1
  37. package/dist/core/dev/dev.js +1 -1
  38. package/dist/core/messages.js +2 -2
  39. package/dist/core/render-context.d.ts +10 -1
  40. package/dist/core/render-context.js +38 -8
  41. package/dist/integrations/index.d.ts +2 -1
  42. package/dist/integrations/index.js +9 -2
  43. package/dist/runtime/client/dev-toolbar/apps/settings.js +3 -1
  44. package/dist/runtime/client/dev-toolbar/entrypoint.js +1 -1
  45. package/dist/runtime/client/dev-toolbar/toolbar.js +3 -1
  46. package/dist/runtime/server/astro-island.js +132 -137
  47. package/dist/runtime/server/astro-island.prebuilt-dev.d.ts +1 -1
  48. package/dist/runtime/server/astro-island.prebuilt-dev.js +1 -1
  49. package/dist/runtime/server/astro-island.prebuilt.d.ts +1 -1
  50. package/dist/runtime/server/astro-island.prebuilt.js +1 -1
  51. package/dist/transitions/router.js +4 -3
  52. package/dist/vite-plugin-astro/index.js +11 -4
  53. package/dist/vite-plugin-markdown/images.d.ts +0 -1
  54. package/dist/vite-plugin-markdown/images.js +1 -4
  55. package/dist/vite-plugin-markdown/index.js +8 -2
  56. package/package.json +46 -49
@@ -10,40 +10,53 @@ import {
10
10
  generateLookupMap
11
11
  } from "../../../content/vite-plugin-content-virtual-mod.js";
12
12
  import { isServerLikeOutput } from "../../../prerender/utils.js";
13
- import { joinPaths, removeFileExtension, removeLeadingForwardSlash } from "../../path.js";
13
+ import { configPaths } from "../../config/index.js";
14
+ import { emptyDir } from "../../fs/index.js";
15
+ import {
16
+ appendForwardSlash,
17
+ joinPaths,
18
+ removeFileExtension,
19
+ removeLeadingForwardSlash
20
+ } from "../../path.js";
14
21
  import { addRollupInput } from "../add-rollup-input.js";
22
+ import { CHUNKS_PATH } from "../consts.js";
15
23
  import {} from "../internal.js";
16
24
  import { copyFiles } from "../static-build.js";
17
25
  import { encodeName } from "../util.js";
18
26
  import { extendManualChunks } from "./util.js";
19
27
  const CONTENT_CACHE_DIR = "./content/";
20
28
  const CONTENT_MANIFEST_FILE = "./manifest.json";
21
- const CONTENT_MANIFEST_VERSION = 0;
29
+ const CONTENT_MANIFEST_VERSION = 1;
22
30
  const virtualEmptyModuleId = `virtual:empty-content`;
23
31
  const resolvedVirtualEmptyModuleId = `\0${virtualEmptyModuleId}`;
32
+ const NO_MANIFEST_VERSION = -1;
24
33
  function createContentManifest() {
25
- return { version: -1, entries: [], serverEntries: [], clientEntries: [] };
34
+ return {
35
+ version: NO_MANIFEST_VERSION,
36
+ entries: [],
37
+ serverEntries: [],
38
+ clientEntries: [],
39
+ lockfiles: "",
40
+ configs: ""
41
+ };
26
42
  }
27
- function vitePluginContent(opts, lookupMap, internals) {
43
+ function vitePluginContent(opts, lookupMap, internals, cachedBuildOutput) {
28
44
  const { config } = opts.settings;
29
45
  const { cacheDir } = config;
30
46
  const distRoot = config.outDir;
31
47
  const distContentRoot = new URL("./content/", distRoot);
32
- const cachedChunks = new URL("./chunks/", opts.settings.config.cacheDir);
33
- const distChunks = new URL("./chunks/", opts.settings.config.outDir);
34
48
  const contentCacheDir = new URL(CONTENT_CACHE_DIR, cacheDir);
35
49
  const contentManifestFile = new URL(CONTENT_MANIFEST_FILE, contentCacheDir);
36
- const cache = contentCacheDir;
37
- const cacheTmp = new URL("./.tmp/", cache);
50
+ const cacheTmp = new URL("./.tmp/", contentCacheDir);
38
51
  let oldManifest = createContentManifest();
39
52
  let newManifest = createContentManifest();
40
53
  let entries;
41
54
  let injectedEmptyFile = false;
55
+ let currentManifestState = "valid";
42
56
  if (fsMod.existsSync(contentManifestFile)) {
43
57
  try {
44
58
  const data = fsMod.readFileSync(contentManifestFile, { encoding: "utf8" });
45
59
  oldManifest = JSON.parse(data);
46
- internals.cachedClientEntries = oldManifest.clientEntries;
47
60
  } catch {
48
61
  }
49
62
  }
@@ -53,6 +66,30 @@ function vitePluginContent(opts, lookupMap, internals) {
53
66
  let newOptions = Object.assign({}, options);
54
67
  newManifest = await generateContentManifest(opts, lookupMap);
55
68
  entries = getEntriesFromManifests(oldManifest, newManifest);
69
+ currentManifestState = manifestState(oldManifest, newManifest);
70
+ if (currentManifestState === "valid") {
71
+ internals.cachedClientEntries = oldManifest.clientEntries;
72
+ } else {
73
+ let logReason = "";
74
+ switch (currentManifestState) {
75
+ case "config-mismatch":
76
+ logReason = "Astro config has changed";
77
+ break;
78
+ case "lockfile-mismatch":
79
+ logReason = "Lockfiles have changed";
80
+ break;
81
+ case "no-entries":
82
+ logReason = "No content collections entries cached";
83
+ break;
84
+ case "version-mismatch":
85
+ logReason = "The cache manifest version has changed";
86
+ break;
87
+ case "no-manifest":
88
+ logReason = "No content manifest was found in the cache";
89
+ break;
90
+ }
91
+ opts.logger.info("build", `Cache invalid, rebuilding from source. Reason: ${logReason}.`);
92
+ }
56
93
  for (const { type, entry } of entries.buildFromSource) {
57
94
  const fileURL = encodeURI(joinPaths(opts.settings.config.root.toString(), entry));
58
95
  const input = fileURLToPath(fileURL);
@@ -62,8 +99,12 @@ function vitePluginContent(opts, lookupMap, internals) {
62
99
  }
63
100
  newOptions = addRollupInput(newOptions, inputs);
64
101
  }
65
- if (fsMod.existsSync(cachedChunks)) {
66
- await copyFiles(cachedChunks, distChunks, true);
102
+ if (currentManifestState === "valid") {
103
+ for (const { cached, dist } of cachedBuildOutput) {
104
+ if (fsMod.existsSync(cached)) {
105
+ await copyFiles(cached, dist, true);
106
+ }
107
+ }
67
108
  }
68
109
  if (entries.buildFromSource.length === 0) {
69
110
  newOptions = addRollupInput(newOptions, [virtualEmptyModuleId]);
@@ -152,15 +193,17 @@ export default {}`
152
193
  ]);
153
194
  newManifest.serverEntries = Array.from(serverComponents);
154
195
  newManifest.clientEntries = Array.from(clientComponents);
196
+ const cacheExists = fsMod.existsSync(contentCacheDir);
197
+ if (cacheExists && currentManifestState !== "valid") {
198
+ emptyDir(contentCacheDir);
199
+ }
155
200
  await fsMod.promises.mkdir(contentCacheDir, { recursive: true });
156
201
  await fsMod.promises.writeFile(contentManifestFile, JSON.stringify(newManifest), {
157
202
  encoding: "utf8"
158
203
  });
159
- const cacheExists = fsMod.existsSync(cache);
160
- fsMod.mkdirSync(cache, { recursive: true });
161
204
  await fsMod.promises.mkdir(cacheTmp, { recursive: true });
162
205
  await copyFiles(distContentRoot, cacheTmp, true);
163
- if (cacheExists) {
206
+ if (cacheExists && currentManifestState === "valid") {
164
207
  await copyFiles(contentCacheDir, distContentRoot, false);
165
208
  }
166
209
  await copyFiles(cacheTmp, contentCacheDir);
@@ -186,11 +229,11 @@ function findEntryFromSrcRelativePath(lookupMap, srcRelativePath) {
186
229
  }
187
230
  }
188
231
  function getEntriesFromManifests(oldManifest, newManifest) {
189
- const { version: oldVersion, entries: oldEntries } = oldManifest;
190
- const { version: newVersion, entries: newEntries } = newManifest;
232
+ const { entries: oldEntries } = oldManifest;
233
+ const { entries: newEntries } = newManifest;
191
234
  let entries = { restoreFromCache: [], buildFromSource: [] };
192
235
  const newEntryMap = new Map(newEntries);
193
- if (oldVersion !== newVersion || oldEntries.length === 0) {
236
+ if (manifestState(oldManifest, newManifest) !== "valid") {
194
237
  entries.buildFromSource = Array.from(newEntryMap.keys());
195
238
  return entries;
196
239
  }
@@ -206,13 +249,27 @@ function getEntriesFromManifests(oldManifest, newManifest) {
206
249
  }
207
250
  return entries;
208
251
  }
252
+ function manifestState(oldManifest, newManifest) {
253
+ if (oldManifest.version === NO_MANIFEST_VERSION) {
254
+ return "no-manifest";
255
+ }
256
+ if (oldManifest.version !== newManifest.version) {
257
+ return "version-mismatch";
258
+ }
259
+ if (oldManifest.entries.length === 0) {
260
+ return "no-entries";
261
+ }
262
+ if (oldManifest.lockfiles !== newManifest.lockfiles || newManifest.lockfiles === "") {
263
+ return "lockfile-mismatch";
264
+ }
265
+ if (oldManifest.configs !== newManifest.configs) {
266
+ return "config-mismatch";
267
+ }
268
+ return "valid";
269
+ }
209
270
  async function generateContentManifest(opts, lookupMap) {
210
- let manifest = {
211
- version: CONTENT_MANIFEST_VERSION,
212
- entries: [],
213
- serverEntries: [],
214
- clientEntries: []
215
- };
271
+ let manifest = createContentManifest();
272
+ manifest.version = CONTENT_MANIFEST_VERSION;
216
273
  const limit = pLimit(10);
217
274
  const promises = [];
218
275
  for (const [collection, { type, entries }] of Object.entries(lookupMap)) {
@@ -227,19 +284,65 @@ async function generateContentManifest(opts, lookupMap) {
227
284
  );
228
285
  }
229
286
  }
287
+ const [lockfiles, configs] = await Promise.all([
288
+ lockfilesHash(opts.settings.config.root),
289
+ configHash(opts.settings.config.root)
290
+ ]);
291
+ manifest.lockfiles = lockfiles;
292
+ manifest.configs = configs;
230
293
  await Promise.all(promises);
231
294
  return manifest;
232
295
  }
233
- function checksum(data) {
234
- return createHash("sha1").update(data).digest("base64");
296
+ async function pushBufferInto(fileURL, buffers) {
297
+ try {
298
+ const handle = await fsMod.promises.open(fileURL, "r");
299
+ const data = await handle.readFile();
300
+ buffers.push(data);
301
+ await handle.close();
302
+ } catch {
303
+ }
304
+ }
305
+ async function lockfilesHash(root) {
306
+ const lockfiles = ["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb"];
307
+ const datas = [];
308
+ const promises = [];
309
+ for (const lockfileName of lockfiles) {
310
+ const fileURL = new URL(`./${lockfileName}`, root);
311
+ promises.push(pushBufferInto(fileURL, datas));
312
+ }
313
+ await Promise.all(promises);
314
+ return checksum(...datas);
315
+ }
316
+ async function configHash(root) {
317
+ const configFileNames = configPaths;
318
+ for (const configPath of configFileNames) {
319
+ try {
320
+ const fileURL = new URL(`./${configPath}`, root);
321
+ const data = await fsMod.promises.readFile(fileURL);
322
+ const hash = checksum(data);
323
+ return hash;
324
+ } catch {
325
+ }
326
+ }
327
+ return checksum(`export default {}`);
328
+ }
329
+ function checksum(...datas) {
330
+ const hash = createHash("sha1");
331
+ datas.forEach((data) => hash.update(data));
332
+ return hash.digest("base64");
235
333
  }
236
334
  function collectionTypeToFlag(type) {
237
335
  const name = type[0].toUpperCase() + type.slice(1);
238
336
  return `astro${name}CollectionEntry`;
239
337
  }
240
338
  function pluginContent(opts, internals) {
241
- const cachedChunks = new URL("./chunks/", opts.settings.config.cacheDir);
242
- const distChunks = new URL("./chunks/", opts.settings.config.outDir);
339
+ const { cacheDir, outDir } = opts.settings.config;
340
+ const chunksFolder = "./" + CHUNKS_PATH;
341
+ const assetsFolder = "./" + appendForwardSlash(opts.settings.config.build.assets);
342
+ const cachedBuildOutput = [
343
+ { cached: new URL(chunksFolder, cacheDir), dist: new URL(chunksFolder, outDir) },
344
+ { cached: new URL(assetsFolder, cacheDir), dist: new URL(assetsFolder, outDir) }
345
+ ];
243
346
  return {
244
347
  targets: ["server"],
245
348
  hooks: {
@@ -252,7 +355,7 @@ function pluginContent(opts, internals) {
252
355
  }
253
356
  const lookupMap = await generateLookupMap({ settings: opts.settings, fs: fsMod });
254
357
  return {
255
- vitePlugin: vitePluginContent(opts, lookupMap, internals)
358
+ vitePlugin: vitePluginContent(opts, lookupMap, internals, cachedBuildOutput)
256
359
  };
257
360
  },
258
361
  async "build:post"() {
@@ -262,8 +365,10 @@ function pluginContent(opts, internals) {
262
365
  if (isServerLikeOutput(opts.settings.config)) {
263
366
  return;
264
367
  }
265
- if (fsMod.existsSync(distChunks)) {
266
- await copyFiles(distChunks, cachedChunks, true);
368
+ for (const { cached, dist } of cachedBuildOutput) {
369
+ if (fsMod.existsSync(dist)) {
370
+ await copyFiles(dist, cached, true);
371
+ }
267
372
  }
268
373
  }
269
374
  }
@@ -1,4 +1,4 @@
1
- import type { BuildOptions, Plugin as VitePlugin, Rollup } from 'vite';
1
+ import type { BuildOptions, Rollup, Plugin as VitePlugin } from 'vite';
2
2
  type OutputOptionsHook = Extract<VitePlugin['outputOptions'], Function>;
3
3
  type OutputOptions = Parameters<OutputOptionsHook>[0];
4
4
  type ExtendManualChunksHooks = {
@@ -6,7 +6,7 @@ export declare function viteBuild(opts: StaticBuildOptions): Promise<{
6
6
  ssrOutputChunkNames: string[];
7
7
  }>;
8
8
  export declare function staticBuild(opts: StaticBuildOptions, internals: BuildInternals, ssrOutputChunkNames: string[]): Promise<void>;
9
- export declare function copyFiles(fromFolder: URL, toFolder: URL, includeDotfiles?: boolean): Promise<void>;
9
+ export declare function copyFiles(fromFolder: URL, toFolder: URL, includeDotfiles?: boolean): Promise<void[] | undefined>;
10
10
  /**
11
11
  * This function takes the virtual module name of any page entrypoint and
12
12
  * transforms it to generate a final `.mjs` output file.
@@ -21,6 +21,7 @@ import { PAGE_SCRIPT_ID } from "../../vite-plugin-scripts/index.js";
21
21
  import { AstroError, AstroErrorData } from "../errors/index.js";
22
22
  import { routeIsRedirect } from "../redirects/index.js";
23
23
  import { getOutDirWithinCwd } from "./common.js";
24
+ import { CHUNKS_PATH } from "./consts.js";
24
25
  import { generatePages } from "./generate.js";
25
26
  import { trackPageData } from "./internal.js";
26
27
  import { createPluginContainer } from "./plugin.js";
@@ -146,7 +147,7 @@ async function ssrBuild(opts, internals, input, container) {
146
147
  // We need to keep these separate
147
148
  chunkFileNames(chunkInfo) {
148
149
  const { name } = chunkInfo;
149
- let prefix = "chunks/";
150
+ let prefix = CHUNKS_PATH;
150
151
  let suffix = "_[hash].mjs";
151
152
  if (isContentCache) {
152
153
  prefix += `${buildID}/`;
@@ -345,7 +346,7 @@ async function copyFiles(fromFolder, toFolder, includeDotfiles = false) {
345
346
  });
346
347
  if (files.length === 0)
347
348
  return;
348
- await Promise.all(
349
+ return await Promise.all(
349
350
  files.map(async function copyFile(filename) {
350
351
  const from = new URL(filename, fromFolder);
351
352
  const to = new URL(filename, toFolder);
@@ -7,6 +7,7 @@ export declare function validateConfig(userConfig: any, root: string, cmd: strin
7
7
  /** Convert the generic "yargs" flag object into our own, custom TypeScript object. */
8
8
  export declare function resolveFlags(flags: Partial<Flags>): CLIFlags;
9
9
  export declare function resolveRoot(cwd?: string | URL): string;
10
+ export declare const configPaths: readonly string[];
10
11
  interface ResolveConfigPathOptions {
11
12
  root: string;
12
13
  configFile?: string;
@@ -45,15 +45,16 @@ function resolveRoot(cwd) {
45
45
  }
46
46
  return cwd ? path.resolve(cwd) : process.cwd();
47
47
  }
48
+ const configPaths = Object.freeze([
49
+ "astro.config.mjs",
50
+ "astro.config.js",
51
+ "astro.config.ts",
52
+ "astro.config.mts",
53
+ "astro.config.cjs",
54
+ "astro.config.cts"
55
+ ]);
48
56
  async function search(fsMod, root) {
49
- const paths = [
50
- "astro.config.mjs",
51
- "astro.config.js",
52
- "astro.config.ts",
53
- "astro.config.mts",
54
- "astro.config.cjs",
55
- "astro.config.cts"
56
- ].map((p) => path.join(root, p));
57
+ const paths = configPaths.map((p) => path.join(root, p));
57
58
  for (const file of paths) {
58
59
  if (fsMod.existsSync(file)) {
59
60
  return file;
@@ -121,6 +122,7 @@ async function resolveConfig(inlineConfig, command, fsMod = fs) {
121
122
  return { userConfig, astroConfig };
122
123
  }
123
124
  export {
125
+ configPaths,
124
126
  resolveConfig,
125
127
  resolveConfigPath,
126
128
  resolveFlags,
@@ -1,4 +1,4 @@
1
- export { resolveConfig, resolveConfigPath, resolveFlags, resolveRoot } from './config.js';
1
+ export { configPaths, resolveConfig, resolveConfigPath, resolveFlags, resolveRoot, } from './config.js';
2
2
  export { createNodeLogger } from './logging.js';
3
3
  export { mergeConfig } from './merge.js';
4
4
  export type { AstroConfigType } from './schema.js';
@@ -1,9 +1,16 @@
1
- import { resolveConfig, resolveConfigPath, resolveFlags, resolveRoot } from "./config.js";
1
+ import {
2
+ configPaths,
3
+ resolveConfig,
4
+ resolveConfigPath,
5
+ resolveFlags,
6
+ resolveRoot
7
+ } from "./config.js";
2
8
  import { createNodeLogger } from "./logging.js";
3
9
  import { mergeConfig } from "./merge.js";
4
10
  import { createSettings } from "./settings.js";
5
11
  import { loadTSConfig, updateTSConfigForFramework } from "./tsconfig.js";
6
12
  export {
13
+ configPaths,
7
14
  createNodeLogger,
8
15
  createSettings,
9
16
  loadTSConfig,