
























@@ -10,6 +10,7 @@ import { createLowDiskSpaceWarning } from "../infra/disk-space.js";
1010import { resolveHomeRelativePath } from "../infra/home-dir.js";
1111import { createNpmProjectInstallEnv } from "../infra/npm-install-env.js";
1212import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
13+import { sanitizeTerminalText } from "../terminal/safe-text.js";
1314import { beginBundledRuntimeDepsInstall } from "./bundled-runtime-deps-activity.js";
1415import { normalizePluginsConfig } from "./config-state.js";
1516import { satisfies, validRange, validSemver } from "./semver.runtime.js";
@@ -65,6 +66,7 @@ const BUNDLED_RUNTIME_DEPS_LOCK_WAIT_MS = 100;
6566const BUNDLED_RUNTIME_DEPS_LOCK_TIMEOUT_MS = 5 * 60_000;
6667const BUNDLED_RUNTIME_DEPS_LOCK_STALE_MS = 10 * 60_000;
6768const BUNDLED_RUNTIME_DEPS_OWNERLESS_LOCK_STALE_MS = 30_000;
69+const BUNDLED_RUNTIME_DEPS_INSTALL_PROGRESS_INTERVAL_MS = 5_000;
6870const BUNDLED_RUNTIME_MIRROR_MATERIALIZED_EXTENSIONS = new Set([".cjs", ".js", ".mjs"]);
6971const BUNDLED_RUNTIME_MIRROR_PLUGIN_REGION_RE = /(?:^|\n)\/\/#region extensions\/[^/\s]+(?:\/|$)/u;
7072const MIRRORED_PACKAGE_RUNTIME_DEP_NAMES = ["tslog"] as const;
@@ -1587,13 +1589,58 @@ function formatBundledRuntimeDepsInstallError(result: {
15871589return output || "npm install failed";
15881590}
158915911592+function formatBundledRuntimeDepsInstallElapsed(ms: number): string {
1593+const seconds = Math.max(0, Math.round(ms / 1000));
1594+if (seconds < 60) {
1595+return `${seconds}s`;
1596+}
1597+const minutes = Math.floor(seconds / 60);
1598+const remainingSeconds = seconds % 60;
1599+return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
1600+}
1601+1602+function emitBundledRuntimeDepsOutputProgress(
1603+chunk: Buffer,
1604+stream: "stdout" | "stderr",
1605+onProgress: ((message: string) => void) | undefined,
1606+): void {
1607+if (!onProgress) {
1608+return;
1609+}
1610+const lines = chunk
1611+.toString("utf8")
1612+.split(/\r\n|\n|\r/u)
1613+.map((line) => sanitizeTerminalText(line).trim())
1614+.filter((line) => line.length > 0)
1615+.slice(-3);
1616+for (const line of lines) {
1617+onProgress(`npm ${stream}: ${line}`);
1618+}
1619+}
1620+15901621async function spawnBundledRuntimeDepsInstall(params: {
15911622command: string;
15921623args: string[];
15931624cwd: string;
15941625env: NodeJS.ProcessEnv;
1626+onProgress?: (message: string) => void;
15951627}): Promise<void> {
15961628await new Promise<void>((resolve, reject) => {
1629+const startedAtMs = Date.now();
1630+const heartbeat =
1631+params.onProgress &&
1632+setInterval(() => {
1633+params.onProgress?.(
1634+`npm install still running (${formatBundledRuntimeDepsInstallElapsed(Date.now() - startedAtMs)} elapsed)`,
1635+);
1636+}, BUNDLED_RUNTIME_DEPS_INSTALL_PROGRESS_INTERVAL_MS);
1637+heartbeat?.unref?.();
1638+const settle = (fn: () => void) => {
1639+if (heartbeat) {
1640+clearInterval(heartbeat);
1641+}
1642+fn();
1643+};
15971644const child = spawn(params.command, params.args, {
15981645cwd: params.cwd,
15991646env: params.env,
@@ -1602,24 +1649,32 @@ async function spawnBundledRuntimeDepsInstall(params: {
16021649});
16031650const stdout: Buffer[] = [];
16041651const stderr: Buffer[] = [];
1605-child.stdout?.on("data", (chunk: Buffer) => stdout.push(chunk));
1606-child.stderr?.on("data", (chunk: Buffer) => stderr.push(chunk));
1652+child.stdout?.on("data", (chunk: Buffer) => {
1653+stdout.push(chunk);
1654+emitBundledRuntimeDepsOutputProgress(chunk, "stdout", params.onProgress);
1655+});
1656+child.stderr?.on("data", (chunk: Buffer) => {
1657+stderr.push(chunk);
1658+emitBundledRuntimeDepsOutputProgress(chunk, "stderr", params.onProgress);
1659+});
16071660child.on("error", (error) => {
1608-reject(new Error(formatBundledRuntimeDepsInstallError({ error })));
1661+settle(() => reject(new Error(formatBundledRuntimeDepsInstallError({ error }))));
16091662});
16101663child.on("close", (status, signal) => {
16111664if (status === 0 && !signal) {
1612-resolve();
1665+settle(resolve);
16131666return;
16141667}
1615-reject(
1616-new Error(
1617-formatBundledRuntimeDepsInstallError({
1618- status,
1619- signal,
1620-stdout: Buffer.concat(stdout).toString("utf8"),
1621-stderr: Buffer.concat(stderr).toString("utf8"),
1622-}),
1668+settle(() =>
1669+reject(
1670+new Error(
1671+formatBundledRuntimeDepsInstallError({
1672+ status,
1673+ signal,
1674+stdout: Buffer.concat(stdout).toString("utf8"),
1675+stderr: Buffer.concat(stderr).toString("utf8"),
1676+}),
1677+),
16231678),
16241679);
16251680});
@@ -1703,6 +1758,7 @@ export async function installBundledRuntimeDepsAsync(params: {
17031758missingSpecs: string[];
17041759env: NodeJS.ProcessEnv;
17051760warn?: (message: string) => void;
1761+onProgress?: (message: string) => void;
17061762}): Promise<void> {
17071763const installExecutionRoot = params.installExecutionRoot ?? params.installRoot;
17081764const isolatedExecutionRoot =
@@ -1731,11 +1787,15 @@ export async function installBundledRuntimeDepsAsync(params: {
17311787env: installEnv,
17321788npmArgs: createBundledRuntimeDepsInstallArgs(params.missingSpecs),
17331789});
1790+params.onProgress?.(
1791+`Starting npm install for bundled plugin runtime deps: ${params.missingSpecs.join(", ")}`,
1792+);
17341793await spawnBundledRuntimeDepsInstall({
17351794command: npmRunner.command,
17361795args: npmRunner.args,
17371796cwd: installExecutionRoot,
17381797env: npmRunner.env ?? installEnv,
1798+onProgress: params.onProgress,
17391799});
17401800assertBundledRuntimeDepsInstalled(installExecutionRoot, params.missingSpecs);
17411801if (isolatedExecutionRoot) {
@@ -1858,6 +1918,7 @@ export async function repairBundledRuntimeDepsInstallRootAsync(params: {
18581918env: NodeJS.ProcessEnv;
18591919installDeps?: (params: BundledRuntimeDepsInstallParams) => Promise<void>;
18601920warn?: (message: string) => void;
1921+onProgress?: (message: string) => void;
18611922}): Promise<{ installSpecs: string[] }> {
18621923return await withBundledRuntimeDepsInstallRootLockAsync(params.installRoot, async () => {
18631924const retainedManifestSpecs = readRetainedRuntimeDepsManifest(params.installRoot);
@@ -1872,6 +1933,7 @@ export async function repairBundledRuntimeDepsInstallRootAsync(params: {
18721933missingSpecs: installParams.installSpecs ?? installParams.missingSpecs,
18731934env: params.env,
18741935warn: params.warn,
1936+onProgress: params.onProgress,
18751937}));
18761938const finishActivity = beginBundledRuntimeDepsInstall({
18771939installRoot: params.installRoot,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。