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.
- package/dist/assets/build/generate.d.ts +8 -1
- package/dist/assets/build/generate.js +21 -1
- package/dist/assets/fonts/providers/index.js +12 -2
- package/dist/assets/types.d.ts +13 -0
- package/dist/assets/vite-plugin-assets.js +8 -0
- package/dist/cli/add/index.js +1 -1
- package/dist/cli/agent.d.ts +1 -0
- package/dist/cli/agent.js +11 -0
- package/dist/cli/dev/background.d.ts +3 -16
- package/dist/cli/dev/background.js +7 -93
- package/dist/cli/dev/index.d.ts +12 -0
- package/dist/cli/dev/index.js +30 -23
- package/dist/cli/dev/logs.js +2 -64
- package/dist/cli/dev/status.d.ts +2 -9
- package/dist/cli/dev/status.js +6 -24
- package/dist/cli/dev/stop.d.ts +2 -6
- package/dist/cli/dev/stop.js +6 -14
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/cli/install-package.js +1 -1
- package/dist/cli/preview/index.js +77 -3
- package/dist/cli/server.d.ts +60 -0
- package/dist/cli/server.js +274 -0
- package/dist/content/content-layer.js +3 -3
- package/dist/content/runtime.d.ts +2 -0
- package/dist/content/runtime.js +2 -0
- package/dist/content/types-generator.js +1 -0
- package/dist/content/vite-plugin-content-assets.js +6 -1
- package/dist/content/vite-plugin-content-imports.js +12 -3
- package/dist/content/vite-plugin-content-virtual-mod.js +28 -16
- package/dist/core/app/entrypoints/index.d.ts +2 -0
- package/dist/core/app/entrypoints/index.js +14 -0
- package/dist/core/build/config-hash/index.d.ts +8 -0
- package/dist/core/build/config-hash/index.js +23 -0
- package/dist/core/build/config-hash/input.d.ts +199 -0
- package/dist/core/build/config-hash/input.js +43 -0
- package/dist/core/build/generate.d.ts +3 -1
- package/dist/core/build/generate.js +149 -14
- package/dist/core/build/incremental-content-collector.d.ts +10 -0
- package/dist/core/build/incremental-content-collector.js +33 -0
- package/dist/core/build/incremental-image-collector.d.ts +11 -0
- package/dist/core/build/incremental-image-collector.js +32 -0
- package/dist/core/build/incremental-metadata.d.ts +9 -0
- package/dist/core/build/incremental-metadata.js +17 -0
- package/dist/core/build/incremental.d.ts +123 -0
- package/dist/core/build/incremental.js +178 -0
- package/dist/core/build/index.d.ts +3 -0
- package/dist/core/build/index.js +6 -2
- package/dist/core/build/internal.d.ts +19 -0
- package/dist/core/build/lockfile/finder.d.ts +22 -0
- package/dist/core/build/lockfile/finder.js +45 -0
- package/dist/core/build/lockfile/hasher.d.ts +16 -0
- package/dist/core/build/lockfile/hasher.js +46 -0
- package/dist/core/build/lockfile/index.d.ts +9 -0
- package/dist/core/build/lockfile/index.js +16 -0
- package/dist/core/build/plugins/index.js +3 -1
- package/dist/core/build/plugins/plugin-incremental.d.ts +14 -0
- package/dist/core/build/plugins/plugin-incremental.js +134 -0
- package/dist/core/build/types.d.ts +2 -0
- package/dist/core/config/schemas/base.d.ts +3 -2
- package/dist/core/config/schemas/base.js +1 -0
- package/dist/core/config/schemas/defaults.d.ts +1 -0
- package/dist/core/config/schemas/defaults.js +1 -0
- package/dist/core/config/schemas/relative.d.ts +7 -4
- package/dist/core/constants.js +1 -1
- package/dist/core/create-vite.js +2 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/dev/lockfile.d.ts +8 -7
- package/dist/core/dev/lockfile.js +13 -13
- package/dist/core/encryption.d.ts +6 -0
- package/dist/core/encryption.js +14 -2
- package/dist/core/errors/default-handler.js +4 -5
- package/dist/core/fetch/index.js +1 -1
- package/dist/core/logger/config.d.ts +1 -1
- package/dist/core/logger/load.d.ts +3 -1
- package/dist/core/logger/load.js +3 -3
- package/dist/core/logger/utils.d.ts +6 -4
- package/dist/core/logger/utils.js +13 -5
- package/dist/core/logger/vite-plugin.js +1 -1
- package/dist/core/messages/runtime.js +1 -1
- package/dist/core/preview/static-preview-server.d.ts +2 -0
- package/dist/core/preview/static-preview-server.js +1 -0
- package/dist/core/routing/handler.js +1 -1
- package/dist/core/session/config.d.ts +2 -2
- package/dist/core/session/config.js +2 -1
- package/dist/core/session/provider-disabled.d.ts +2 -0
- package/dist/core/session/provider-disabled.js +7 -0
- package/dist/core/session/provider.d.ts +1 -0
- package/dist/core/session/provider.js +4 -0
- package/dist/core/session/utils.js +3 -0
- package/dist/core/session/vite-plugin.d.ts +3 -0
- package/dist/core/session/vite-plugin.js +41 -6
- package/dist/integrations/hooks.js +3 -1
- package/dist/runtime/prerender/static-paths.js +5 -1
- package/dist/runtime/server/render/util.js +3 -0
- package/dist/types/public/common.d.ts +1 -0
- package/dist/types/public/config.d.ts +59 -2
- package/dist/types/public/integrations.d.ts +29 -2
- package/dist/types/public/preview.d.ts +2 -0
- package/dist/vite-plugin-config-alias/index.js +1 -0
- package/dist/vite-plugin-environment/index.js +4 -1
- 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 {
|
|
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
|
-
|
|
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.
|
|
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.
|
|
208
|
-
this.#store.metaStore().set("astro-version", "7.
|
|
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;
|
package/dist/content/runtime.js
CHANGED
|
@@ -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 {
|
|
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
|
|
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 {
|
|
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
|
|
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
|
|
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 {
|
|
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 {
|
|
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
|
-
|
|
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';
|