From d69941c3359be2dd4ed876fff7da64a66cf85f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Thu, 23 Oct 2025 12:58:25 +0200 Subject: [PATCH 1/3] Fix visualizing duplicate links --- packages/host/src/node/cli/link-modules.ts | 25 +++++++---------- packages/host/src/node/cli/program.ts | 12 +++++---- packages/host/src/node/duplicates.ts | 12 --------- packages/host/src/node/path-utils.ts | 31 ++++++++++++---------- 4 files changed, 34 insertions(+), 46 deletions(-) delete mode 100644 packages/host/src/node/duplicates.ts diff --git a/packages/host/src/node/cli/link-modules.ts b/packages/host/src/node/cli/link-modules.ts index 8b3bf2e0..a2d274f6 100644 --- a/packages/host/src/node/cli/link-modules.ts +++ b/packages/host/src/node/cli/link-modules.ts @@ -11,9 +11,10 @@ import { findNodeApiModulePathsByDependency, getAutolinkPath, getLibraryName, - logModulePaths, + visualizeLibraryMap, NamingStrategy, PlatformName, + getLibraryMap, } from "../path-utils"; export type ModuleLinker = ( @@ -78,9 +79,14 @@ export async function linkModules({ ), ); - if (hasDuplicateLibraryNames(absoluteModulePaths, naming)) { - logModulePaths(absoluteModulePaths, naming); - throw new Error("Found conflicting library names"); + const libraryMap = getLibraryMap(absoluteModulePaths, naming); + const duplicates = new Map( + Array.from(libraryMap.entries()).filter(([, paths]) => paths.length > 1), + ); + + if (duplicates.size > 0) { + const visualized = visualizeLibraryMap(duplicates); + throw new Error("Found conflicting library names:\n" + visualized); } return Promise.all( @@ -133,17 +139,6 @@ export async function pruneLinkedModules( ); } -export function hasDuplicateLibraryNames( - modulePaths: string[], - naming: NamingStrategy, -): boolean { - const libraryNames = modulePaths.map((modulePath) => { - return getLibraryName(modulePath, naming); - }); - const uniqueNames = new Set(libraryNames); - return uniqueNames.size !== libraryNames.length; -} - export function getLinkedModuleOutputPath( platform: PlatformName, modulePath: string, diff --git a/packages/host/src/node/cli/program.ts b/packages/host/src/node/cli/program.ts index 6fd037b3..169ca85b 100644 --- a/packages/host/src/node/cli/program.ts +++ b/packages/host/src/node/cli/program.ts @@ -16,10 +16,11 @@ import { findNodeApiModulePathsByDependency, getAutolinkPath, getLibraryName, - logModulePaths, + visualizeLibraryMap, normalizeModulePath, PlatformName, PLATFORMS, + getLibraryMap, } from "../path-utils"; import { command as vendorHermes } from "./hermes"; @@ -115,10 +116,10 @@ program successText: `Linked ${platformDisplayName} Node-API modules into ${prettyPath( platformOutputPath, )}`, - failText: (error) => + failText: () => `Failed to link ${platformDisplayName} Node-API modules into ${prettyPath( platformOutputPath, - )}: ${error.message}`, + )}`, }, ); @@ -209,14 +210,15 @@ program dependencies, )) { console.log( - chalk.blueBright(dependencyName), + "\n" + chalk.blueBright(dependencyName), "→", prettyPath(dependency.path), ); - logModulePaths( + const libraryMap = getLibraryMap( dependency.modulePaths.map((p) => path.join(dependency.path, p)), { packageName, pathSuffix }, ); + console.log(visualizeLibraryMap(libraryMap)); } } }), diff --git a/packages/host/src/node/duplicates.ts b/packages/host/src/node/duplicates.ts deleted file mode 100644 index 5e8be7f2..00000000 --- a/packages/host/src/node/duplicates.ts +++ /dev/null @@ -1,12 +0,0 @@ -export function findDuplicates(values: string[]) { - const seen = new Set(); - const duplicates = new Set(); - for (const value of values) { - if (seen.has(value)) { - duplicates.add(value); - } else { - seen.add(value); - } - } - return duplicates; -} diff --git a/packages/host/src/node/path-utils.ts b/packages/host/src/node/path-utils.ts index f898d566..5fbafff1 100644 --- a/packages/host/src/node/path-utils.ts +++ b/packages/host/src/node/path-utils.ts @@ -7,8 +7,6 @@ import { createRequire } from "node:module"; import { chalk, prettyPath } from "@react-native-node-api/cli-utils"; -import { findDuplicates } from "./duplicates"; - // TODO: Change to .apple.node export const PLATFORMS = ["android", "apple"] as const; export type PlatformName = "android" | "apple"; @@ -267,32 +265,37 @@ export function resolvePackageRoot( } } -export function logModulePaths( +/** + * Module paths per library name. + */ +export type LibraryMap = Map; + +export function getLibraryMap( modulePaths: string[], // TODO: Default to iterating and printing for all supported naming strategies naming: NamingStrategy, ) { - const pathsPerName = new Map(); + const result = new Map(); for (const modulePath of modulePaths) { const libraryName = getLibraryName(modulePath, naming); - const existingPaths = pathsPerName.get(libraryName) ?? []; + const existingPaths = result.get(libraryName) ?? []; existingPaths.push(modulePath); - pathsPerName.set(libraryName, existingPaths); + result.set(libraryName, existingPaths); } + return result; +} - const allModulePaths = modulePaths.map((modulePath) => modulePath); - const duplicatePaths = findDuplicates(allModulePaths); - for (const [libraryName, modulePaths] of pathsPerName) { - console.log( +export function visualizeLibraryMap(libraryMap: LibraryMap) { + const result = []; + for (const [libraryName, modulePaths] of libraryMap) { + result.push( chalk.greenBright(`${libraryName}`), ...modulePaths.flatMap((modulePath) => { - const line = duplicatePaths.has(modulePath) - ? chalk.redBright(prettyPath(modulePath)) - : prettyPath(modulePath); - return `\n ↳ ${line}`; + return ` ↳ ${prettyPath(modulePath)}`; }), ); } + return result.join("\n"); } /** From 9ff51d906f54f460b95d78c7008e407991400649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Thu, 23 Oct 2025 13:56:46 +0200 Subject: [PATCH 2/3] Remove outdated comment --- packages/host/src/node/path-utils.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/host/src/node/path-utils.ts b/packages/host/src/node/path-utils.ts index 5fbafff1..60fd0ffa 100644 --- a/packages/host/src/node/path-utils.ts +++ b/packages/host/src/node/path-utils.ts @@ -270,11 +270,7 @@ export function resolvePackageRoot( */ export type LibraryMap = Map; -export function getLibraryMap( - modulePaths: string[], - // TODO: Default to iterating and printing for all supported naming strategies - naming: NamingStrategy, -) { +export function getLibraryMap(modulePaths: string[], naming: NamingStrategy) { const result = new Map(); for (const modulePath of modulePaths) { const libraryName = getLibraryName(modulePath, naming); From 18c9a72d9803e1b279705536ab6cc740e8cb1f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Thu, 23 Oct 2025 13:57:38 +0200 Subject: [PATCH 3/3] Add changeset --- .changeset/polite-bikes-stay.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/polite-bikes-stay.md diff --git a/.changeset/polite-bikes-stay.md b/.changeset/polite-bikes-stay.md new file mode 100644 index 00000000..1a457c7f --- /dev/null +++ b/.changeset/polite-bikes-stay.md @@ -0,0 +1,5 @@ +--- +"react-native-node-api": patch +--- + +Fixed visualizing duplicate library names