

























@@ -0,0 +1,208 @@
1+import fs from "node:fs";
2+import path from "node:path";
3+import { isPathInside, safeStatSync } from "./path-safety.js";
4+import { normalizeJitiAliasTargetPath } from "./sdk-alias.js";
5+6+type RuntimeDependencyPackageJson = {
7+dependencies?: Record<string, unknown>;
8+optionalDependencies?: Record<string, unknown>;
9+peerDependencies?: Record<string, unknown>;
10+exports?: unknown;
11+module?: string;
12+main?: string;
13+};
14+15+const bundledRuntimeDependencyJitiAliases = new Map<string, string>();
16+17+function readRuntimeDependencyPackageJson(
18+packageJsonPath: string,
19+): RuntimeDependencyPackageJson | null {
20+try {
21+return JSON.parse(fs.readFileSync(packageJsonPath, "utf-8")) as RuntimeDependencyPackageJson;
22+} catch {
23+return null;
24+}
25+}
26+27+function collectRuntimeDependencyNames(pkg: RuntimeDependencyPackageJson): string[] {
28+return [
29+ ...Object.keys(pkg.dependencies ?? {}),
30+ ...Object.keys(pkg.optionalDependencies ?? {}),
31+ ...Object.keys(pkg.peerDependencies ?? {}),
32+].toSorted((left, right) => left.localeCompare(right));
33+}
34+35+function resolveRuntimePackageImportTarget(exportsField: unknown): string | null {
36+if (typeof exportsField === "string") {
37+return exportsField;
38+}
39+if (Array.isArray(exportsField)) {
40+for (const entry of exportsField) {
41+const resolved = resolveRuntimePackageImportTarget(entry);
42+if (resolved) {
43+return resolved;
44+}
45+}
46+return null;
47+}
48+if (!exportsField || typeof exportsField !== "object" || Array.isArray(exportsField)) {
49+return null;
50+}
51+const record = exportsField as Record<string, unknown>;
52+if (Object.prototype.hasOwnProperty.call(record, ".")) {
53+return resolveRuntimePackageImportTarget(record["."]);
54+}
55+for (const condition of ["import", "node", "default"] as const) {
56+const resolved = resolveRuntimePackageImportTarget(record[condition]);
57+if (resolved) {
58+return resolved;
59+}
60+}
61+return null;
62+}
63+64+function collectRuntimePackageWildcardImportTargets(
65+dependencyRoot: string,
66+exportKey: string,
67+targetPattern: string,
68+): Map<string, string> {
69+const targets = new Map<string, string>();
70+const wildcardIndex = exportKey.indexOf("*");
71+const targetWildcardIndex = targetPattern.indexOf("*");
72+if (wildcardIndex === -1 || targetWildcardIndex === -1) {
73+return targets;
74+}
75+const exportPrefix = exportKey.slice(0, wildcardIndex);
76+const exportSuffix = exportKey.slice(wildcardIndex + 1);
77+const targetPrefix = targetPattern.slice(0, targetWildcardIndex);
78+const targetSuffix = targetPattern.slice(targetWildcardIndex + 1);
79+const targetBase = path.resolve(dependencyRoot, targetPrefix);
80+if (!isPathInside(dependencyRoot, targetBase) || !safeStatSync(targetBase)?.isDirectory()) {
81+return targets;
82+}
83+const stack = [targetBase];
84+while (stack.length > 0) {
85+const currentDir = stack.pop();
86+if (!currentDir) {
87+continue;
88+}
89+let entries: fs.Dirent[];
90+try {
91+entries = fs.readdirSync(currentDir, { withFileTypes: true });
92+} catch {
93+continue;
94+}
95+for (const entry of entries) {
96+const entryPath = path.join(currentDir, entry.name);
97+if (!isPathInside(dependencyRoot, entryPath)) {
98+continue;
99+}
100+if (entry.isDirectory()) {
101+stack.push(entryPath);
102+continue;
103+}
104+if (!entry.isFile()) {
105+continue;
106+}
107+const relativeTarget = path.relative(targetBase, entryPath).split(path.sep).join("/");
108+if (targetSuffix && !relativeTarget.endsWith(targetSuffix)) {
109+continue;
110+}
111+const wildcardValue = targetSuffix
112+ ? relativeTarget.slice(0, -targetSuffix.length)
113+ : relativeTarget;
114+targets.set(`${exportPrefix}${wildcardValue}${exportSuffix}`, entryPath);
115+}
116+}
117+return targets;
118+}
119+120+function collectRuntimePackageImportTargets(
121+dependencyRoot: string,
122+pkg: RuntimeDependencyPackageJson,
123+): Map<string, string> {
124+const targets = new Map<string, string>();
125+const exportsField = pkg.exports;
126+if (
127+exportsField &&
128+typeof exportsField === "object" &&
129+!Array.isArray(exportsField) &&
130+Object.keys(exportsField).some((key) => key.startsWith("."))
131+) {
132+for (const [exportKey, exportValue] of Object.entries(exportsField)) {
133+if (!exportKey.startsWith(".")) {
134+continue;
135+}
136+const resolved = resolveRuntimePackageImportTarget(exportValue);
137+if (resolved) {
138+if (exportKey.includes("*")) {
139+for (const [wildcardExportKey, targetPath] of collectRuntimePackageWildcardImportTargets(
140+dependencyRoot,
141+exportKey,
142+resolved,
143+)) {
144+targets.set(wildcardExportKey, targetPath);
145+}
146+} else {
147+targets.set(exportKey, resolved);
148+}
149+}
150+}
151+return targets;
152+}
153+const rootEntry = resolveRuntimePackageImportTarget(exportsField) ?? pkg.module ?? pkg.main;
154+if (rootEntry) {
155+targets.set(".", rootEntry);
156+}
157+return targets;
158+}
159+160+export function clearBundledRuntimeDependencyJitiAliases(): void {
161+bundledRuntimeDependencyJitiAliases.clear();
162+}
163+164+export function registerBundledRuntimeDependencyJitiAliases(rootDir: string): void {
165+const rootPackageJson = readRuntimeDependencyPackageJson(path.join(rootDir, "package.json"));
166+if (!rootPackageJson) {
167+return;
168+}
169+for (const dependencyName of collectRuntimeDependencyNames(rootPackageJson)) {
170+const dependencyPackageJsonPath = path.join(
171+rootDir,
172+"node_modules",
173+ ...dependencyName.split("/"),
174+"package.json",
175+);
176+const dependencyPackageJson = readRuntimeDependencyPackageJson(dependencyPackageJsonPath);
177+if (!dependencyPackageJson) {
178+continue;
179+}
180+const dependencyRoot = path.dirname(dependencyPackageJsonPath);
181+for (const [exportKey, entry] of collectRuntimePackageImportTargets(
182+dependencyRoot,
183+dependencyPackageJson,
184+)) {
185+if (!entry || entry.startsWith("#")) {
186+continue;
187+}
188+const targetPath = path.resolve(dependencyRoot, entry);
189+if (!isPathInside(dependencyRoot, targetPath) || !fs.existsSync(targetPath)) {
190+continue;
191+}
192+const aliasKey =
193+exportKey === "." ? dependencyName : `${dependencyName}${exportKey.slice(1)}`;
194+bundledRuntimeDependencyJitiAliases.set(aliasKey, normalizeJitiAliasTargetPath(targetPath));
195+}
196+}
197+}
198+199+export function resolveBundledRuntimeDependencyJitiAliasMap(): Record<string, string> | undefined {
200+if (bundledRuntimeDependencyJitiAliases.size === 0) {
201+return undefined;
202+}
203+return Object.fromEntries(
204+[...bundledRuntimeDependencyJitiAliases.entries()].toSorted(
205+([left], [right]) => right.length - left.length || left.localeCompare(right),
206+),
207+);
208+}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。