astro 7.1.6 → 7.2.0

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 (101) hide show
  1. package/dist/assets/build/generate.d.ts +8 -1
  2. package/dist/assets/build/generate.js +21 -1
  3. package/dist/assets/fonts/providers/index.js +12 -2
  4. package/dist/assets/types.d.ts +13 -0
  5. package/dist/assets/vite-plugin-assets.js +8 -0
  6. package/dist/cli/add/index.js +1 -1
  7. package/dist/cli/agent.d.ts +1 -0
  8. package/dist/cli/agent.js +11 -0
  9. package/dist/cli/dev/background.d.ts +3 -16
  10. package/dist/cli/dev/background.js +7 -93
  11. package/dist/cli/dev/index.d.ts +12 -0
  12. package/dist/cli/dev/index.js +30 -23
  13. package/dist/cli/dev/logs.js +2 -64
  14. package/dist/cli/dev/status.d.ts +2 -9
  15. package/dist/cli/dev/status.js +6 -24
  16. package/dist/cli/dev/stop.d.ts +2 -6
  17. package/dist/cli/dev/stop.js +6 -14
  18. package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
  19. package/dist/cli/install-package.js +1 -1
  20. package/dist/cli/preview/index.js +77 -3
  21. package/dist/cli/server.d.ts +60 -0
  22. package/dist/cli/server.js +274 -0
  23. package/dist/content/content-layer.js +3 -3
  24. package/dist/content/runtime.d.ts +2 -0
  25. package/dist/content/runtime.js +2 -0
  26. package/dist/content/types-generator.js +1 -0
  27. package/dist/content/vite-plugin-content-assets.js +6 -1
  28. package/dist/content/vite-plugin-content-imports.js +12 -3
  29. package/dist/content/vite-plugin-content-virtual-mod.js +28 -16
  30. package/dist/core/app/entrypoints/index.d.ts +2 -0
  31. package/dist/core/app/entrypoints/index.js +14 -0
  32. package/dist/core/build/config-hash/index.d.ts +8 -0
  33. package/dist/core/build/config-hash/index.js +23 -0
  34. package/dist/core/build/config-hash/input.d.ts +199 -0
  35. package/dist/core/build/config-hash/input.js +43 -0
  36. package/dist/core/build/generate.d.ts +3 -1
  37. package/dist/core/build/generate.js +149 -14
  38. package/dist/core/build/incremental-content-collector.d.ts +10 -0
  39. package/dist/core/build/incremental-content-collector.js +33 -0
  40. package/dist/core/build/incremental-image-collector.d.ts +11 -0
  41. package/dist/core/build/incremental-image-collector.js +32 -0
  42. package/dist/core/build/incremental-metadata.d.ts +9 -0
  43. package/dist/core/build/incremental-metadata.js +17 -0
  44. package/dist/core/build/incremental.d.ts +123 -0
  45. package/dist/core/build/incremental.js +178 -0
  46. package/dist/core/build/index.d.ts +3 -0
  47. package/dist/core/build/index.js +6 -2
  48. package/dist/core/build/internal.d.ts +19 -0
  49. package/dist/core/build/lockfile/finder.d.ts +22 -0
  50. package/dist/core/build/lockfile/finder.js +45 -0
  51. package/dist/core/build/lockfile/hasher.d.ts +16 -0
  52. package/dist/core/build/lockfile/hasher.js +46 -0
  53. package/dist/core/build/lockfile/index.d.ts +9 -0
  54. package/dist/core/build/lockfile/index.js +16 -0
  55. package/dist/core/build/plugins/index.js +3 -1
  56. package/dist/core/build/plugins/plugin-incremental.d.ts +14 -0
  57. package/dist/core/build/plugins/plugin-incremental.js +134 -0
  58. package/dist/core/build/types.d.ts +2 -0
  59. package/dist/core/config/schemas/base.d.ts +3 -2
  60. package/dist/core/config/schemas/base.js +1 -0
  61. package/dist/core/config/schemas/defaults.d.ts +1 -0
  62. package/dist/core/config/schemas/defaults.js +1 -0
  63. package/dist/core/config/schemas/relative.d.ts +7 -4
  64. package/dist/core/constants.js +1 -1
  65. package/dist/core/create-vite.js +2 -1
  66. package/dist/core/dev/dev.js +1 -1
  67. package/dist/core/dev/lockfile.d.ts +8 -7
  68. package/dist/core/dev/lockfile.js +13 -13
  69. package/dist/core/encryption.d.ts +6 -0
  70. package/dist/core/encryption.js +14 -2
  71. package/dist/core/errors/default-handler.js +4 -5
  72. package/dist/core/fetch/index.js +1 -1
  73. package/dist/core/logger/config.d.ts +1 -1
  74. package/dist/core/logger/load.d.ts +3 -1
  75. package/dist/core/logger/load.js +3 -3
  76. package/dist/core/logger/utils.d.ts +6 -4
  77. package/dist/core/logger/utils.js +13 -5
  78. package/dist/core/logger/vite-plugin.js +1 -1
  79. package/dist/core/messages/runtime.js +1 -1
  80. package/dist/core/preview/static-preview-server.d.ts +2 -0
  81. package/dist/core/preview/static-preview-server.js +1 -0
  82. package/dist/core/routing/handler.js +1 -1
  83. package/dist/core/session/config.d.ts +2 -2
  84. package/dist/core/session/config.js +2 -1
  85. package/dist/core/session/provider-disabled.d.ts +2 -0
  86. package/dist/core/session/provider-disabled.js +7 -0
  87. package/dist/core/session/provider.d.ts +1 -0
  88. package/dist/core/session/provider.js +4 -0
  89. package/dist/core/session/utils.js +3 -0
  90. package/dist/core/session/vite-plugin.d.ts +3 -0
  91. package/dist/core/session/vite-plugin.js +41 -6
  92. package/dist/integrations/hooks.js +3 -1
  93. package/dist/runtime/prerender/static-paths.js +5 -1
  94. package/dist/runtime/server/render/util.js +3 -0
  95. package/dist/types/public/common.d.ts +1 -0
  96. package/dist/types/public/config.d.ts +59 -2
  97. package/dist/types/public/integrations.d.ts +29 -2
  98. package/dist/types/public/preview.d.ts +2 -0
  99. package/dist/vite-plugin-config-alias/index.js +1 -0
  100. package/dist/vite-plugin-environment/index.js +4 -1
  101. package/package.json +1 -2
@@ -1,14 +1,25 @@
1
1
  import colors from "piccolore";
2
+ import { pathToFileURL } from "node:url";
3
+ import { checkExistingServer, removeLockFile, writeLockFile } from "../../core/dev/lockfile.js";
4
+ import { resolveRoot } from "../../core/config/config.js";
2
5
  import { printHelp } from "../../core/messages/runtime.js";
3
6
  import previewServer from "../../core/preview/index.js";
4
- import { flagsToAstroInlineConfig } from "../flags.js";
7
+ import { isRunByAgent } from "../agent.js";
8
+ import { createLoggerFromFlags, flagsToAstroInlineConfig } from "../flags.js";
9
+ import { background, logs, previewServerCommand, status, stop } from "../server.js";
5
10
  async function preview({ flags }) {
6
11
  if (flags?.help || flags?.h) {
7
12
  printHelp({
8
13
  commandName: "astro preview",
9
- usage: "[...flags]",
14
+ usage: "[command] [...flags]",
10
15
  tables: {
16
+ Commands: [
17
+ ["stop", "Stop a running background preview server."],
18
+ ["status", "Check if a preview server is running."],
19
+ ["logs [--follow]", "View logs from a background preview server."]
20
+ ],
11
21
  Flags: [
22
+ ["--background", "Start the preview server as a background process."],
12
23
  ["--port", `Specify which port to run on. Defaults to 4321.`],
13
24
  ["--host", `Listen on all addresses, including LAN and public addresses.`],
14
25
  ["--host <custom-address>", `Expose on a network IP address at <custom-address>`],
@@ -26,8 +37,71 @@ async function preview({ flags }) {
26
37
  });
27
38
  return;
28
39
  }
40
+ const agentDetected = !process.env.ASTRO_PREVIEW_BACKGROUND && isRunByAgent();
41
+ if (agentDetected) {
42
+ flags.json = true;
43
+ }
44
+ const logger = createLoggerFromFlags(flags);
45
+ const subcommand = flags._[3]?.toString();
46
+ if (subcommand === "stop") {
47
+ await stop({ flags, logger, config: previewServerCommand });
48
+ return;
49
+ }
50
+ if (subcommand === "status") {
51
+ await status({ flags, logger, config: previewServerCommand });
52
+ return;
53
+ }
54
+ if (subcommand === "logs") {
55
+ await logs({ flags, logger, config: previewServerCommand });
56
+ return;
57
+ }
58
+ if (flags.background || agentDetected) {
59
+ await background({ flags, logger, config: previewServerCommand });
60
+ return;
61
+ }
62
+ if (subcommand) {
63
+ logger.error(
64
+ "SKIP_FORMAT",
65
+ `Unknown command: astro preview ${subcommand}
66
+
67
+ Run \`astro preview --help\` to see available commands.`
68
+ );
69
+ process.exit(1);
70
+ }
71
+ const root = pathToFileURL(resolveRoot(flags.root) + "/");
72
+ const existingServer = checkExistingServer(root, "preview");
73
+ if (existingServer) {
74
+ const message = [
75
+ "Another astro preview server is already running.",
76
+ "",
77
+ ` URL: ${existingServer.url}`,
78
+ ` PID: ${existingServer.pid}`,
79
+ "",
80
+ `Run \`astro preview stop\` to stop it, or use \`astro preview --force\` to replace it.`
81
+ ].join("\n");
82
+ throw new Error(message);
83
+ }
29
84
  const inlineConfig = flagsToAstroInlineConfig(flags);
30
- return await previewServer(inlineConfig);
85
+ const server = await previewServer(inlineConfig);
86
+ const serverUrl = server.urls?.local[0] ? new URL(server.urls.local[0]).origin : `http://${server.host ?? "localhost"}:${server.port}`;
87
+ writeLockFile(
88
+ root,
89
+ {
90
+ pid: process.pid,
91
+ port: server.port,
92
+ url: serverUrl,
93
+ urls: server.urls,
94
+ background: !!process.env.ASTRO_PREVIEW_BACKGROUND,
95
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
96
+ },
97
+ "preview"
98
+ );
99
+ const originalStop = server.stop.bind(server);
100
+ server.stop = async () => {
101
+ removeLockFile(root, "preview");
102
+ await originalStop();
103
+ };
104
+ return server;
31
105
  }
32
106
  export {
33
107
  preview
@@ -0,0 +1,60 @@
1
+ import { type LockFileData, type ServerCommand } from '../core/dev/lockfile.js';
2
+ import type { AstroLogger } from '../core/logger/core.js';
3
+ import type { Flags } from './flags.js';
4
+ export interface BackgroundCommandConfig {
5
+ command: ServerCommand;
6
+ displayName: string;
7
+ envVar: 'ASTRO_DEV_BACKGROUND' | 'ASTRO_PREVIEW_BACKGROUND';
8
+ }
9
+ export declare const devServerCommand: BackgroundCommandConfig;
10
+ export declare const previewServerCommand: BackgroundCommandConfig;
11
+ export interface BackgroundResult {
12
+ pid: number;
13
+ url: string;
14
+ existing?: boolean;
15
+ }
16
+ export interface BackgroundErrorResult {
17
+ error: string;
18
+ message: string;
19
+ }
20
+ export interface StopResult {
21
+ stopped: boolean;
22
+ pid?: number;
23
+ reason?: string;
24
+ }
25
+ export interface StatusResult {
26
+ running: boolean;
27
+ pid?: number;
28
+ url?: string;
29
+ port?: number;
30
+ background?: boolean;
31
+ uptime?: number;
32
+ }
33
+ export declare function formatBackgroundOutput(result: BackgroundResult | BackgroundErrorResult): string;
34
+ export declare function formatStopOutput(result: StopResult): string;
35
+ export declare function formatStatusOutput(result: StatusResult): string;
36
+ export declare function formatServerRunningMessage(data: LockFileData, config: BackgroundCommandConfig, { existing }?: {
37
+ existing?: boolean;
38
+ }): string;
39
+ export declare function buildBackgroundArgs(command: ServerCommand, flags: Flags): string[];
40
+ export declare function stopExistingServer(root: URL, command: ServerCommand, pid: number): Promise<void>;
41
+ export declare function background({ flags, logger, config, }: {
42
+ flags: Flags;
43
+ logger: AstroLogger;
44
+ config: BackgroundCommandConfig;
45
+ }): Promise<void>;
46
+ export declare function stop({ flags, logger, config, }: {
47
+ flags: Flags;
48
+ logger: AstroLogger;
49
+ config: BackgroundCommandConfig;
50
+ }): Promise<void>;
51
+ export declare function status({ flags, logger, config, }: {
52
+ flags: Flags;
53
+ logger: AstroLogger;
54
+ config: BackgroundCommandConfig;
55
+ }): Promise<void>;
56
+ export declare function logs({ flags, logger, config, }: {
57
+ flags: Flags;
58
+ logger: AstroLogger;
59
+ config: BackgroundCommandConfig;
60
+ }): Promise<void>;
@@ -0,0 +1,274 @@
1
+ import { spawn } from "node:child_process";
2
+ import {
3
+ createReadStream,
4
+ existsSync,
5
+ mkdirSync,
6
+ openSync,
7
+ readFileSync,
8
+ statSync,
9
+ watch
10
+ } from "node:fs";
11
+ import { createRequire } from "node:module";
12
+ import { dirname, resolve } from "node:path";
13
+ import { fileURLToPath, pathToFileURL } from "node:url";
14
+ import { resolveRoot } from "../core/config/config.js";
15
+ import {
16
+ GRACEFUL_SHUTDOWN_TIMEOUT,
17
+ checkExistingServer,
18
+ getLogFileURL,
19
+ isProcessAlive,
20
+ readLockFile,
21
+ removeLockFile
22
+ } from "../core/dev/lockfile.js";
23
+ const require2 = createRequire(import.meta.url);
24
+ const devServerCommand = {
25
+ command: "dev",
26
+ displayName: "Dev server",
27
+ envVar: "ASTRO_DEV_BACKGROUND"
28
+ };
29
+ const previewServerCommand = {
30
+ command: "preview",
31
+ displayName: "Preview server",
32
+ envVar: "ASTRO_PREVIEW_BACKGROUND"
33
+ };
34
+ function formatBackgroundOutput(result) {
35
+ return JSON.stringify(result);
36
+ }
37
+ function formatStopOutput(result) {
38
+ return JSON.stringify(result);
39
+ }
40
+ function formatStatusOutput(result) {
41
+ return JSON.stringify(result);
42
+ }
43
+ function formatServerRunningMessage(data, config, { existing = false } = {}) {
44
+ const command = `astro ${config.command}`;
45
+ const lines = [
46
+ `${config.displayName} ${existing ? "already running" : "running"} at ${data.url} (pid ${data.pid})`
47
+ ];
48
+ if (data.urls && data.urls.network.length > 0) {
49
+ lines.push(" Network:");
50
+ for (const url of data.urls.network) {
51
+ lines.push(` ${url}`);
52
+ }
53
+ }
54
+ lines.push(
55
+ ` Stop: ${command} stop`,
56
+ ` Status: ${command} status`,
57
+ ` Logs: ${command} logs`
58
+ );
59
+ return lines.join("\n");
60
+ }
61
+ function getRootURL(flags) {
62
+ return pathToFileURL(resolveRoot(flags.root) + "/");
63
+ }
64
+ function buildBackgroundArgs(command, flags) {
65
+ const args = [command];
66
+ if (flags.port) args.push("--port", String(flags.port));
67
+ if (flags.host != null) {
68
+ if (typeof flags.host === "string") {
69
+ args.push("--host", flags.host);
70
+ } else {
71
+ args.push("--host");
72
+ }
73
+ }
74
+ if (flags.config) args.push("--config", String(flags.config));
75
+ if (flags.root) args.push("--root", String(flags.root));
76
+ if (flags.allowedHosts) args.push("--allowed-hosts", String(flags.allowedHosts));
77
+ if (flags.json) args.push("--json");
78
+ return args;
79
+ }
80
+ async function stopExistingServer(root, command, pid) {
81
+ try {
82
+ process.kill(pid, "SIGTERM");
83
+ } catch {
84
+ }
85
+ const deadline = Date.now() + GRACEFUL_SHUTDOWN_TIMEOUT;
86
+ while (Date.now() < deadline) {
87
+ if (!isProcessAlive(pid)) break;
88
+ await new Promise((r) => setTimeout(r, 100));
89
+ }
90
+ if (isProcessAlive(pid)) {
91
+ try {
92
+ process.kill(pid, "SIGKILL");
93
+ } catch {
94
+ }
95
+ }
96
+ removeLockFile(root, command);
97
+ }
98
+ async function background({
99
+ flags,
100
+ logger,
101
+ config
102
+ }) {
103
+ const root = getRootURL(flags);
104
+ const existing = checkExistingServer(root, config.command);
105
+ if (existing && !flags.force) {
106
+ logger.info("SKIP_FORMAT", formatServerRunningMessage(existing, config, { existing: true }));
107
+ return;
108
+ }
109
+ if (existing && flags.force) {
110
+ await stopExistingServer(root, config.command, existing.pid);
111
+ }
112
+ const args = buildBackgroundArgs(config.command, flags);
113
+ const logFileURL = getLogFileURL(root, config.command);
114
+ const logFilePath = fileURLToPath(logFileURL);
115
+ const dotAstroDir = fileURLToPath(new URL(".astro/", root));
116
+ if (!existsSync(dotAstroDir)) {
117
+ mkdirSync(dotAstroDir, { recursive: true });
118
+ }
119
+ const logFd = openSync(logFilePath, "w");
120
+ const rootPath = fileURLToPath(root);
121
+ const astroBin = resolve(dirname(require2.resolve("astro/package.json")), "bin", "astro.mjs");
122
+ const child = spawn(process.execPath, [astroBin, ...args], {
123
+ detached: true,
124
+ windowsHide: true,
125
+ stdio: ["ignore", logFd, logFd],
126
+ cwd: rootPath,
127
+ env: { ...process.env, [config.envVar]: "1" }
128
+ });
129
+ child.unref();
130
+ const childPid = child.pid;
131
+ if (!childPid) {
132
+ logger.error("SKIP_FORMAT", `Failed to spawn background ${config.command} server process.`);
133
+ process.exit(1);
134
+ }
135
+ const timeout = 3e4;
136
+ const deadline = Date.now() + timeout;
137
+ while (Date.now() < deadline) {
138
+ if (!isProcessAlive(childPid)) {
139
+ logger.error("SKIP_FORMAT", `${config.displayName} process exited before becoming ready.`);
140
+ process.exit(1);
141
+ }
142
+ const lockData = readLockFile(root, config.command);
143
+ if (lockData && lockData.pid === childPid) {
144
+ logger.info("SKIP_FORMAT", formatServerRunningMessage(lockData, config));
145
+ return;
146
+ }
147
+ await new Promise((r) => setTimeout(r, 200));
148
+ }
149
+ try {
150
+ process.kill(childPid, "SIGTERM");
151
+ } catch {
152
+ }
153
+ removeLockFile(root, config.command);
154
+ logger.error("SKIP_FORMAT", `${config.displayName} failed to start within ${timeout / 1e3}s.`);
155
+ process.exit(1);
156
+ }
157
+ async function stop({
158
+ flags,
159
+ logger,
160
+ config
161
+ }) {
162
+ const root = getRootURL(flags);
163
+ const existing = checkExistingServer(root, config.command);
164
+ if (!existing) {
165
+ logger.info("SKIP_FORMAT", `No ${config.command} server is running.`);
166
+ return;
167
+ }
168
+ await stopExistingServer(root, config.command, existing.pid);
169
+ logger.info("SKIP_FORMAT", `Stopped ${config.command} server (pid ${existing.pid}).`);
170
+ }
171
+ async function status({
172
+ flags,
173
+ logger,
174
+ config
175
+ }) {
176
+ const root = getRootURL(flags);
177
+ const existing = checkExistingServer(root, config.command);
178
+ if (!existing) {
179
+ logger.info("SKIP_FORMAT", `No ${config.command} server is running.`);
180
+ return;
181
+ }
182
+ const startedAt = new Date(existing.startedAt).getTime();
183
+ const uptime = Math.floor((Date.now() - startedAt) / 1e3);
184
+ const lines = [
185
+ `${config.displayName} running at ${existing.url} (pid ${existing.pid}, uptime ${uptime}s${existing.background ? ", background" : ""})`
186
+ ];
187
+ if (existing.urls && existing.urls.network.length > 0) {
188
+ lines.push(" Network:");
189
+ for (const url of existing.urls.network) {
190
+ lines.push(` ${url}`);
191
+ }
192
+ }
193
+ logger.info("SKIP_FORMAT", lines.join("\n"));
194
+ }
195
+ async function logs({
196
+ flags,
197
+ logger,
198
+ config
199
+ }) {
200
+ const root = getRootURL(flags);
201
+ const existing = checkExistingServer(root, config.command);
202
+ if (!existing) {
203
+ logger.error("SKIP_FORMAT", `No ${config.command} server is running.`);
204
+ process.exit(1);
205
+ }
206
+ if (!existing.background) {
207
+ logger.error(
208
+ "SKIP_FORMAT",
209
+ `The running ${config.command} server was not started with \`astro ${config.command} --background\`. View logs in the terminal where it was started.`
210
+ );
211
+ process.exit(1);
212
+ }
213
+ const logFileURL = getLogFileURL(root, config.command);
214
+ const logFilePath = fileURLToPath(logFileURL);
215
+ if (!existsSync(logFilePath)) {
216
+ logger.error("SKIP_FORMAT", "No log file found.");
217
+ process.exit(1);
218
+ }
219
+ const follow = flags.follow || flags.f;
220
+ if (!follow) {
221
+ const content = readFileSync(logFilePath, "utf-8");
222
+ process.stdout.write(content);
223
+ return;
224
+ }
225
+ let offset = statSync(logFilePath).size;
226
+ if (offset > 0) {
227
+ const content = readFileSync(logFilePath, "utf-8");
228
+ process.stdout.write(content);
229
+ }
230
+ const watcher = watch(logFilePath, () => {
231
+ const currentSize = statSync(logFilePath).size;
232
+ if (currentSize > offset) {
233
+ const stream = createReadStream(logFilePath, { start: offset, encoding: "utf-8" });
234
+ stream.on("data", (chunk) => process.stdout.write(chunk));
235
+ stream.on("end", () => {
236
+ offset = currentSize;
237
+ });
238
+ }
239
+ });
240
+ const aliveCheck = setInterval(() => {
241
+ if (!isProcessAlive(existing.pid)) {
242
+ const currentSize = statSync(logFilePath).size;
243
+ if (currentSize > offset) {
244
+ const remaining = readFileSync(logFilePath, { encoding: "utf-8" }).slice(offset);
245
+ process.stdout.write(remaining);
246
+ }
247
+ watcher.close();
248
+ clearInterval(aliveCheck);
249
+ }
250
+ }, 1e3);
251
+ const cleanup = () => {
252
+ watcher.close();
253
+ clearInterval(aliveCheck);
254
+ process.exit(0);
255
+ };
256
+ process.on("SIGINT", cleanup);
257
+ process.on("SIGTERM", cleanup);
258
+ await new Promise(() => {
259
+ });
260
+ }
261
+ export {
262
+ background,
263
+ buildBackgroundArgs,
264
+ devServerCommand,
265
+ formatBackgroundOutput,
266
+ formatServerRunningMessage,
267
+ formatStatusOutput,
268
+ formatStopOutput,
269
+ logs,
270
+ previewServerCommand,
271
+ status,
272
+ stop,
273
+ stopExistingServer
274
+ };
@@ -196,7 +196,7 @@ ${contentConfig.error.message}`
196
196
  logger.info("Content config changed");
197
197
  shouldClear = true;
198
198
  }
199
- if (previousAstroVersion && previousAstroVersion !== "7.1.6") {
199
+ if (previousAstroVersion && previousAstroVersion !== "7.2.0") {
200
200
  logger.info("Astro version changed");
201
201
  shouldClear = true;
202
202
  }
@@ -204,8 +204,8 @@ ${contentConfig.error.message}`
204
204
  logger.info("Clearing content store");
205
205
  this.#store.clearAll();
206
206
  }
207
- if ("7.1.6") {
208
- this.#store.metaStore().set("astro-version", "7.1.6");
207
+ if ("7.2.0") {
208
+ this.#store.metaStore().set("astro-version", "7.2.0");
209
209
  }
210
210
  if (currentConfigDigest) {
211
211
  this.#store.metaStore().set("content-config-digest", currentConfigDigest);
@@ -33,12 +33,14 @@ type ContentEntryResult = {
33
33
  body: string;
34
34
  collection: string;
35
35
  data: Record<string, any>;
36
+ digest?: string | number;
36
37
  render(): Promise<RenderResult>;
37
38
  };
38
39
  type DataEntryResult = {
39
40
  id: string;
40
41
  collection: string;
41
42
  data: Record<string, any>;
43
+ digest?: string | number;
42
44
  };
43
45
  type EntryLookupObject = {
44
46
  collection: string;
@@ -3,6 +3,7 @@ import { forEach } from "neotraverse";
3
3
  import * as z from "zod/v4";
4
4
  import { createSvgComponent } from "../assets/runtime.js";
5
5
  import { imageSrcToImportId } from "../assets/utils/resolveImports.js";
6
+ import { recordContentEntryRender } from "../core/build/incremental-content-collector.js";
6
7
  import { AstroError, AstroErrorData } from "../core/errors/index.js";
7
8
  import { isRemotePath, prependForwardSlash } from "../core/path.js";
8
9
  import {
@@ -385,6 +386,7 @@ async function renderEntry(entry) {
385
386
  if (!entry) {
386
387
  throw new AstroError(AstroErrorData.RenderUndefinedEntryError);
387
388
  }
389
+ recordContentEntryRender(entry.filePath);
388
390
  if (entry.deferredRender) {
389
391
  try {
390
392
  const { default: contentModules } = await import("astro:content-module-imports");
@@ -373,6 +373,7 @@ async function writeContentFiles({
373
373
  data: ${dataType};
374
374
  rendered?: RenderedContent;
375
375
  filePath?: string;
376
+ digest?: string | number;
376
377
  }>;
377
378
  `;
378
379
  if (collectionConfig && (collectionConfig.schema || await getContentLayerSchema(collectionConfig, collectionKey))) {
@@ -1,5 +1,6 @@
1
1
  import { extname } from "node:path";
2
2
  import { getAssetsPrefix } from "../assets/utils/getAssetsPrefix.js";
3
+ import { createContentDataIncrementalMetadata } from "../core/build/incremental-metadata.js";
3
4
  import { fileExtension } from "../core/path.js";
4
5
  import { fileURLToPath } from "node:url";
5
6
  import { isRunnableDevEnvironment } from "vite";
@@ -107,7 +108,11 @@ function astroContentAssetPropagationPlugin({
107
108
  const defaultMod = { __astroPropagation: true, getMod, collectedLinks, collectedStyles, collectedScripts: [] };
108
109
  export default defaultMod;
109
110
  `;
110
- return { code, map: { mappings: "" } };
111
+ return {
112
+ code,
113
+ map: { mappings: "" },
114
+ meta: createContentDataIncrementalMetadata()
115
+ };
111
116
  }
112
117
  }
113
118
  }
@@ -2,6 +2,8 @@ import { extname } from "node:path";
2
2
  import { pathToFileURL } from "node:url";
3
3
  import * as devalue from "devalue";
4
4
  import { getProxyCode } from "../assets/utils/proxy.js";
5
+ import { createContentDataIncrementalMetadata } from "../core/build/incremental-metadata.js";
6
+ import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../core/constants.js";
5
7
  import { AstroError } from "../core/errors/errors.js";
6
8
  import { AstroErrorData } from "../core/errors/index.js";
7
9
  import { CONTENT_FLAG, DATA_FLAG } from "./consts.js";
@@ -22,7 +24,6 @@ import {
22
24
  reloadContentConfigObserver,
23
25
  reverseSymlink
24
26
  } from "./utils.js";
25
- import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../core/constants.js";
26
27
  function getContentRendererByViteId(viteId, settings) {
27
28
  let ext = viteId.split(".").pop();
28
29
  if (!ext) return void 0;
@@ -91,7 +92,11 @@ export const _internal = {
91
92
  rawData: ${JSON.stringify(_internal.rawData)},
92
93
  };
93
94
  `;
94
- return code;
95
+ return {
96
+ code,
97
+ map: { mappings: "" },
98
+ meta: createContentDataIncrementalMetadata()
99
+ };
95
100
  } else if (hasContentFlag(viteId, CONTENT_FLAG)) {
96
101
  const fileId = reverseSymlink({ entry: viteId.split("?")[0], contentDir, symlinks });
97
102
  const { id, slug, collection, body, data, _internal } = await getContentEntryModule({
@@ -114,7 +119,11 @@ export const _internal = {
114
119
  filePath: ${JSON.stringify(_internal.filePath)},
115
120
  rawData: ${JSON.stringify(_internal.rawData)},
116
121
  };`;
117
- return { code, map: { mappings: "" } };
122
+ return {
123
+ code,
124
+ map: { mappings: "" },
125
+ meta: createContentDataIncrementalMetadata()
126
+ };
118
127
  }
119
128
  }
120
129
  },
@@ -1,7 +1,7 @@
1
1
  import nodeFs from "node:fs";
2
2
  import { fileURLToPath } from "node:url";
3
- import { dataToEsm } from "@rollup/pluginutils";
4
3
  import { isRunnableDevEnvironment, normalizePath } from "vite";
4
+ import { createContentDataIncrementalMetadata } from "../core/build/incremental-metadata.js";
5
5
  import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../core/constants.js";
6
6
  import { AstroError, AstroErrorData } from "../core/errors/index.js";
7
7
  import { rootRelativePath } from "../core/viteUtils.js";
@@ -28,7 +28,6 @@ import {
28
28
  } from "./consts.js";
29
29
  import { getDataStoreChunkSize, getDataStoreDir, getDataStoreFile } from "./paths.js";
30
30
  import { getContentPaths, isDeferredModule } from "./utils.js";
31
- const LARGE_DATA_STORE_THRESHOLD = 5 * 1024 * 1024;
32
31
  function invalidateAssetImports(viteServer, filePath) {
33
32
  const timestamp = Date.now();
34
33
  for (const environment of Object.values(viteServer.environments)) {
@@ -149,14 +148,20 @@ function astroContentVirtualModPlugin({
149
148
  if (id === MODULES_MJS_ID) {
150
149
  const modules = new URL(MODULES_IMPORTS_FILE, settings.dotAstroDir);
151
150
  if (fs.existsSync(modules)) {
152
- return fileURLToPath(modules);
151
+ return {
152
+ id: fileURLToPath(modules),
153
+ meta: createContentDataIncrementalMetadata()
154
+ };
153
155
  }
154
156
  return MODULES_MJS_VIRTUAL_ID;
155
157
  }
156
158
  if (id === ASSET_IMPORTS_VIRTUAL_ID) {
157
159
  const assetImportsFile = new URL(ASSET_IMPORTS_FILE, settings.dotAstroDir);
158
160
  if (fs.existsSync(assetImportsFile)) {
159
- return fileURLToPath(assetImportsFile);
161
+ return {
162
+ id: fileURLToPath(assetImportsFile),
163
+ meta: createContentDataIncrementalMetadata()
164
+ };
160
165
  }
161
166
  return ASSET_IMPORTS_RESOLVED_STUB_ID;
162
167
  }
@@ -208,7 +213,10 @@ function astroContentVirtualModPlugin({
208
213
  }
209
214
  if (id === RESOLVED_DATA_STORE_VIRTUAL_ID) {
210
215
  if (!fs.existsSync(dataStoreFile)) {
211
- return { code: "export default new Map()" };
216
+ return {
217
+ code: "export default new Map()",
218
+ meta: createContentDataIncrementalMetadata()
219
+ };
212
220
  }
213
221
  const jsonData = await fs.promises.readFile(dataStoreFile, "utf-8");
214
222
  if (getDataStoreChunkSize(settings) !== void 0) {
@@ -219,36 +227,40 @@ function astroContentVirtualModPlugin({
219
227
  ([collection, parts]) => `${JSON.stringify(collection)}:[${parts.map(chunkImport).join(",")}]`
220
228
  );
221
229
  const code = `export default{${entries.join(",")}}`;
222
- return { code, map: { mappings: "" } };
230
+ return {
231
+ code,
232
+ map: { mappings: "" },
233
+ meta: createContentDataIncrementalMetadata()
234
+ };
223
235
  } catch (err) {
224
236
  const message = "Could not parse data store manifest JSON file";
225
237
  this.error({ message, id, cause: err });
226
238
  }
227
239
  }
228
240
  try {
229
- const parsed = JSON.parse(jsonData);
230
- const useRuntimeJsonParse = isDev && Buffer.byteLength(jsonData) > LARGE_DATA_STORE_THRESHOLD;
231
- return {
232
- code: useRuntimeJsonParse ? `export default JSON.parse(${JSON.stringify(jsonData)})` : dataToEsm(parsed, {
233
- compact: true
234
- }),
235
- map: { mappings: "" }
236
- };
241
+ JSON.parse(jsonData);
237
242
  } catch (err) {
238
243
  const message = "Could not parse JSON file";
239
244
  this.error({ message, id, cause: err });
240
245
  }
246
+ return {
247
+ code: `export default JSON.parse(${JSON.stringify(jsonData)})`,
248
+ map: { mappings: "" },
249
+ meta: createContentDataIncrementalMetadata()
250
+ };
241
251
  }
242
252
  if (id === ASSET_IMPORTS_RESOLVED_STUB_ID) {
243
253
  const assetImportsFile = new URL(ASSET_IMPORTS_FILE, settings.dotAstroDir);
244
254
  return {
245
- code: fs.existsSync(assetImportsFile) ? fs.readFileSync(assetImportsFile, "utf-8") : "export default new Map()"
255
+ code: fs.existsSync(assetImportsFile) ? fs.readFileSync(assetImportsFile, "utf-8") : "export default new Map()",
256
+ meta: createContentDataIncrementalMetadata()
246
257
  };
247
258
  }
248
259
  if (id === MODULES_MJS_VIRTUAL_ID) {
249
260
  const modules = new URL(MODULES_IMPORTS_FILE, settings.dotAstroDir);
250
261
  return {
251
- code: fs.existsSync(modules) ? fs.readFileSync(modules, "utf-8") : "export default new Map()"
262
+ code: fs.existsSync(modules) ? fs.readFileSync(modules, "utf-8") : "export default new Map()",
263
+ meta: createContentDataIncrementalMetadata()
252
264
  };
253
265
  }
254
266
  }
@@ -5,3 +5,5 @@ export { fromRoutingStrategy, toRoutingStrategy } from '../common.js';
5
5
  export { createConsoleLogger } from '../../logger/impls/console.js';
6
6
  export { deserializeManifest, deserializeRouteData, deserializeRouteInfo, serializeRouteData, serializeRouteInfo, } from '../manifest.js';
7
7
  export { AppPipeline } from '../pipeline.js';
8
+ export { beginContentEntryCollection, endContentEntryCollection, } from '../../build/incremental-content-collector.js';
9
+ export { beginImageCollection, endImageCollection, recordStaticImage, } from '../../build/incremental-image-collector.js';