Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions packages/host/src/node/cli/link-modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import {
findNodeApiModulePathsByDependency,
getAutolinkPath,
getLibraryName,
logModulePaths,
visualizeLibraryMap,
NamingStrategy,
PlatformName,
getLibraryMap,
} from "../path-utils";

export type ModuleLinker = (
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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,
Expand Down
12 changes: 7 additions & 5 deletions packages/host/src/node/cli/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import {
findNodeApiModulePathsByDependency,
getAutolinkPath,
getLibraryName,
logModulePaths,
visualizeLibraryMap,
normalizeModulePath,
PlatformName,
PLATFORMS,
getLibraryMap,
} from "../path-utils";

import { command as vendorHermes } from "./hermes";
Expand Down Expand Up @@ -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}`,
)}`,
Comment on lines +119 to +122
Copy link

Copilot AI Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error parameter was removed from the failText callback, but the error's message is no longer included in the output. This loses valuable debugging information. Consider retaining the error parameter and including error.message in the error text, or document why the error details are intentionally omitted.

Copilot uses AI. Check for mistakes.
},
);

Expand Down Expand Up @@ -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));
}
}
}),
Expand Down
12 changes: 0 additions & 12 deletions packages/host/src/node/duplicates.ts

This file was deleted.

31 changes: 17 additions & 14 deletions packages/host/src/node/path-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -267,32 +265,37 @@ export function resolvePackageRoot(
}
}

export function logModulePaths(
/**
* Module paths per library name.
*/
export type LibraryMap = Map<string, string[]>;

export function getLibraryMap(
modulePaths: string[],
// TODO: Default to iterating and printing for all supported naming strategies
Copy link

Copilot AI Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TODO comment references 'printing' but this function no longer handles printing/logging - that responsibility has been moved to visualizeLibraryMap. Update the TODO to reflect that this is about supporting multiple naming strategies for building the map, or move it to visualizeLibraryMap if the intent is about visualizing multiple strategies.

Suggested change
// TODO: Default to iterating and printing for all supported naming strategies
// TODO: Default to iterating for all supported naming strategies

Copilot uses AI. Check for mistakes.
naming: NamingStrategy,
) {
const pathsPerName = new Map<string, string[]>();
const result = new Map<string, string[]>();
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");
}

/**
Expand Down
Loading