


























@@ -0,0 +1,209 @@
1+import fs from "node:fs";
2+import path from "node:path";
3+import {
4+collectInstalledRuntimeDependencyRoots,
5+dependencyNodeModulesPath,
6+findContainingRealRoot,
7+resolveInstalledDirectDependencyNames,
8+selectRuntimeDependencyRootsToCopy,
9+} from "./bundled-runtime-deps-package-tree.mjs";
10+import { pruneStagedRuntimeDependencyCargo } from "./bundled-runtime-deps-prune.mjs";
11+import {
12+assertPathIsNotSymlink,
13+makePluginOwnedTempDir,
14+removeOwnedTempPathBestEffort,
15+removePathIfExists,
16+replaceDirAtomically,
17+writeJsonAtomically,
18+} from "./bundled-runtime-deps-stage-state.mjs";
19+20+function copyMaterializedDependencyTree(params) {
21+const { activeRoots, allowedRealRoots, sourcePath, targetPath } = params;
22+const sourceStats = fs.lstatSync(sourcePath);
23+24+if (sourceStats.isSymbolicLink()) {
25+let resolvedPath;
26+try {
27+resolvedPath = fs.realpathSync(sourcePath);
28+} catch {
29+return false;
30+}
31+const containingRoot = findContainingRealRoot(resolvedPath, allowedRealRoots);
32+if (containingRoot === null) {
33+return false;
34+}
35+if (activeRoots.has(containingRoot)) {
36+return true;
37+}
38+const nextActiveRoots = new Set(activeRoots);
39+nextActiveRoots.add(containingRoot);
40+return copyMaterializedDependencyTree({
41+activeRoots: nextActiveRoots,
42+ allowedRealRoots,
43+sourcePath: resolvedPath,
44+ targetPath,
45+});
46+}
47+48+if (sourceStats.isDirectory()) {
49+fs.mkdirSync(targetPath, { recursive: true });
50+for (const entry of fs
51+.readdirSync(sourcePath, { withFileTypes: true })
52+.toSorted((left, right) => left.name.localeCompare(right.name))) {
53+if (
54+!copyMaterializedDependencyTree({
55+ activeRoots,
56+ allowedRealRoots,
57+sourcePath: path.join(sourcePath, entry.name),
58+targetPath: path.join(targetPath, entry.name),
59+})
60+) {
61+return false;
62+}
63+}
64+return true;
65+}
66+67+if (sourceStats.isFile()) {
68+fs.mkdirSync(path.dirname(targetPath), { recursive: true });
69+fs.copyFileSync(sourcePath, targetPath);
70+fs.chmodSync(targetPath, sourceStats.mode);
71+return true;
72+}
73+74+return true;
75+}
76+77+export function listBundledPluginRuntimeDirs(repoRoot) {
78+const extensionsRoot = path.join(repoRoot, "dist", "extensions");
79+if (!fs.existsSync(extensionsRoot)) {
80+return [];
81+}
82+83+return fs
84+.readdirSync(extensionsRoot, { withFileTypes: true })
85+.filter((dirent) => dirent.isDirectory())
86+.map((dirent) => path.join(extensionsRoot, dirent.name))
87+.filter((pluginDir) => fs.existsSync(path.join(pluginDir, "package.json")));
88+}
89+90+export function resolveInstalledWorkspacePluginRoot(repoRoot, pluginId) {
91+const currentPluginRoot = path.join(repoRoot, "extensions", pluginId);
92+if (fs.existsSync(path.join(currentPluginRoot, "node_modules"))) {
93+return currentPluginRoot;
94+}
95+96+const nodeModulesDir = path.join(repoRoot, "node_modules");
97+if (!fs.existsSync(nodeModulesDir)) {
98+return currentPluginRoot;
99+}
100+101+let installedWorkspaceRoot;
102+try {
103+installedWorkspaceRoot = path.dirname(fs.realpathSync(nodeModulesDir));
104+} catch {
105+return currentPluginRoot;
106+}
107+108+const installedPluginRoot = path.join(installedWorkspaceRoot, "extensions", pluginId);
109+if (fs.existsSync(path.join(installedPluginRoot, "package.json"))) {
110+return installedPluginRoot;
111+}
112+113+return currentPluginRoot;
114+}
115+116+export function stageInstalledRootRuntimeDeps(params) {
117+const {
118+ directDependencyPackageRoot = null,
119+ cheapFingerprint,
120+ fingerprint,
121+ packageJson,
122+ pluginDir,
123+ pruneConfig,
124+ repoRoot,
125+ stampPath,
126+} = params;
127+const dependencySpecs = {
128+ ...packageJson.dependencies,
129+ ...packageJson.optionalDependencies,
130+};
131+const optionalDependencyNames = new Set(Object.keys(packageJson.optionalDependencies ?? {}));
132+const rootNodeModulesDir = path.join(repoRoot, "node_modules");
133+if (Object.keys(dependencySpecs).length === 0 || !fs.existsSync(rootNodeModulesDir)) {
134+return false;
135+}
136+137+const directDependencyNames = resolveInstalledDirectDependencyNames(
138+rootNodeModulesDir,
139+dependencySpecs,
140+directDependencyPackageRoot,
141+optionalDependencyNames,
142+);
143+if (directDependencyNames === null) {
144+return false;
145+}
146+const resolution = collectInstalledRuntimeDependencyRoots(
147+rootNodeModulesDir,
148+dependencySpecs,
149+directDependencyPackageRoot,
150+optionalDependencyNames,
151+);
152+if (resolution === null) {
153+return false;
154+}
155+const rootsToCopy = selectRuntimeDependencyRootsToCopy(resolution);
156+const nodeModulesDir = path.join(pluginDir, "node_modules");
157+if (rootsToCopy.length === 0) {
158+assertPathIsNotSymlink(nodeModulesDir, "remove runtime deps");
159+removePathIfExists(nodeModulesDir);
160+writeJsonAtomically(stampPath, {
161+ cheapFingerprint,
162+ fingerprint,
163+generatedAt: new Date().toISOString(),
164+});
165+return true;
166+}
167+const allowedRealRoots = rootsToCopy.map((record) => record.realRoot);
168+169+const stagedNodeModulesDir = path.join(
170+makePluginOwnedTempDir(pluginDir, "stage"),
171+"node_modules",
172+);
173+174+try {
175+for (const record of rootsToCopy.toSorted((left, right) =>
176+left.name.localeCompare(right.name),
177+)) {
178+const sourcePath = record.realRoot;
179+const targetPath = dependencyNodeModulesPath(stagedNodeModulesDir, record.name);
180+if (targetPath === null) {
181+return false;
182+}
183+fs.mkdirSync(path.dirname(targetPath), { recursive: true });
184+const sourceRootReal = findContainingRealRoot(sourcePath, allowedRealRoots);
185+if (
186+sourceRootReal === null ||
187+!copyMaterializedDependencyTree({
188+activeRoots: new Set([sourceRootReal]),
189+ allowedRealRoots,
190+ sourcePath,
191+ targetPath,
192+})
193+) {
194+return false;
195+}
196+}
197+pruneStagedRuntimeDependencyCargo(stagedNodeModulesDir, pruneConfig);
198+199+replaceDirAtomically(nodeModulesDir, stagedNodeModulesDir);
200+writeJsonAtomically(stampPath, {
201+ cheapFingerprint,
202+ fingerprint,
203+generatedAt: new Date().toISOString(),
204+});
205+return true;
206+} finally {
207+removeOwnedTempPathBestEffort(path.dirname(stagedNodeModulesDir));
208+}
209+}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。