From 02639d3ec8911c8eed229d8c68a014b4a42e02fd Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 25 Apr 2026 15:46:01 +0100 Subject: [PATCH] fix(plugins): alias wildcard runtime dependency exports --- src/plugins/loader.test.ts | 12 +++++- src/plugins/loader.ts | 80 +++++++++++++++++++++++++++++++++++--- 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/src/plugins/loader.test.ts b/src/plugins/loader.test.ts index 189ece88510..a48d67c0ef9 100644 --- a/src/plugins/loader.test.ts +++ b/src/plugins/loader.test.ts @@ -1589,10 +1589,14 @@ module.exports = { "./oauth": { import: "./oauth.js", }, + "./*": { + import: "./dist/*", + }, }, }), "utf-8", ); + fs.mkdirSync(path.join(packageDepRoot, "dist", "client"), { recursive: true }); fs.writeFileSync( path.join(packageDepRoot, "index.js"), "export default { marker: 'root-ok' };\n", @@ -1603,12 +1607,18 @@ module.exports = { "export const oauthMarker = 'oauth-ok';\n", "utf-8", ); + fs.writeFileSync( + path.join(packageDepRoot, "dist", "client", "index.js"), + "export const clientMarker = 'client-ok';\n", + "utf-8", + ); fs.writeFileSync( path.join(packageRoot, "dist", "manifest-support.js"), [ `import support from "root-support";`, `import { oauthMarker } from "root-support/oauth";`, - `export const marker = [support.marker, oauthMarker].join(":");`, + `import { clientMarker } from "root-support/client/index.js";`, + `export const marker = [support.marker, oauthMarker, clientMarker].join(":");`, "", ].join("\n"), "utf-8", diff --git a/src/plugins/loader.ts b/src/plugins/loader.ts index b686ac05f49..4b09f2e5a3f 100644 --- a/src/plugins/loader.ts +++ b/src/plugins/loader.ts @@ -516,7 +516,64 @@ function resolveRuntimePackageImportTarget(exportsField: unknown): string | null return null; } +function collectRuntimePackageWildcardImportTargets( + dependencyRoot: string, + exportKey: string, + targetPattern: string, +): Map { + const targets = new Map(); + const wildcardIndex = exportKey.indexOf("*"); + const targetWildcardIndex = targetPattern.indexOf("*"); + if (wildcardIndex === -1 || targetWildcardIndex === -1) { + return targets; + } + const exportPrefix = exportKey.slice(0, wildcardIndex); + const exportSuffix = exportKey.slice(wildcardIndex + 1); + const targetPrefix = targetPattern.slice(0, targetWildcardIndex); + const targetSuffix = targetPattern.slice(targetWildcardIndex + 1); + const targetBase = path.resolve(dependencyRoot, targetPrefix); + if (!isPathInside(dependencyRoot, targetBase) || !safeStatSync(targetBase)?.isDirectory()) { + return targets; + } + const stack = [targetBase]; + while (stack.length > 0) { + const currentDir = stack.pop(); + if (!currentDir) { + continue; + } + let entries: fs.Dirent[]; + try { + entries = fs.readdirSync(currentDir, { withFileTypes: true }); + } catch { + continue; + } + for (const entry of entries) { + const entryPath = path.join(currentDir, entry.name); + if (!isPathInside(dependencyRoot, entryPath)) { + continue; + } + if (entry.isDirectory()) { + stack.push(entryPath); + continue; + } + if (!entry.isFile()) { + continue; + } + const relativeTarget = path.relative(targetBase, entryPath).split(path.sep).join("/"); + if (targetSuffix && !relativeTarget.endsWith(targetSuffix)) { + continue; + } + const wildcardValue = targetSuffix + ? relativeTarget.slice(0, -targetSuffix.length) + : relativeTarget; + targets.set(`${exportPrefix}${wildcardValue}${exportSuffix}`, entryPath); + } + } + return targets; +} + function collectRuntimePackageImportTargets( + dependencyRoot: string, pkg: RuntimeDependencyPackageJson, ): Map { const targets = new Map(); @@ -528,12 +585,22 @@ function collectRuntimePackageImportTargets( Object.keys(exportsField).some((key) => key.startsWith(".")) ) { for (const [exportKey, exportValue] of Object.entries(exportsField)) { - if (!exportKey.startsWith(".") || exportKey.includes("*")) { + if (!exportKey.startsWith(".")) { continue; } const resolved = resolveRuntimePackageImportTarget(exportValue); if (resolved) { - targets.set(exportKey, resolved); + if (exportKey.includes("*")) { + for (const [wildcardExportKey, targetPath] of collectRuntimePackageWildcardImportTargets( + dependencyRoot, + exportKey, + resolved, + )) { + targets.set(wildcardExportKey, targetPath); + } + } else { + targets.set(exportKey, resolved); + } } } return targets; @@ -562,7 +629,10 @@ function registerBundledRuntimeDependencyJitiAliases(rootDir: string): void { continue; } const dependencyRoot = path.dirname(dependencyPackageJsonPath); - for (const [exportKey, entry] of collectRuntimePackageImportTargets(dependencyPackageJson)) { + for (const [exportKey, entry] of collectRuntimePackageImportTargets( + dependencyRoot, + dependencyPackageJson, + )) { if (!entry || entry.startsWith("#")) { continue; } @@ -582,8 +652,8 @@ function resolveBundledRuntimeDependencyJitiAliasMap(): Record | return undefined; } return Object.fromEntries( - [...bundledRuntimeDependencyJitiAliases.entries()].toSorted(([left], [right]) => - left.localeCompare(right), + [...bundledRuntimeDependencyJitiAliases.entries()].toSorted( + ([left], [right]) => right.length - left.length || left.localeCompare(right), ), ); }