Skip to content

Commit 045e9e5

Browse files
authored
Filter node_modules from package roots (#178)
* Fix findNodeApiModulePaths to exclude from root node_modules of the app itself * Turn findNodeApiModulePaths async * Add changeset * Commit change to package-lock.json
1 parent 97bdb76 commit 045e9e5

File tree

6 files changed

+76
-54
lines changed

6 files changed

+76
-54
lines changed

.changeset/three-pugs-relate.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"react-native-node-api": patch
3+
---
4+
5+
Fix hasDuplicateLibraryNames by filtering out node_modules in package rootse

package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/host/src/node/cli/link-modules.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,18 @@ export async function linkModules({
6161
linker,
6262
}: LinkModulesOptions): Promise<ModuleOutput[]> {
6363
// Find all their xcframeworks
64-
const dependenciesByName = findNodeApiModulePathsByDependency({
64+
const dependenciesByName = await findNodeApiModulePathsByDependency({
6565
fromPath,
6666
platform,
6767
includeSelf: true,
6868
});
6969

7070
// Find absolute paths to xcframeworks
7171
const absoluteModulePaths = Object.values(dependenciesByName).flatMap(
72-
(dependency) => dependency.modulePaths.map(
73-
(modulePath) => path.join(dependency.path, modulePath)
74-
)
72+
(dependency) =>
73+
dependency.modulePaths.map((modulePath) =>
74+
path.join(dependency.path, modulePath)
75+
)
7576
);
7677

7778
if (hasDuplicateLibraryNames(absoluteModulePaths, naming)) {

packages/host/src/node/cli/program.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ program
169169
.addOption(pathSuffixOption)
170170
.action(async (fromArg, { json, pathSuffix }) => {
171171
const rootPath = path.resolve(fromArg);
172-
const dependencies = findNodeApiModulePathsByDependency({
172+
const dependencies = await findNodeApiModulePathsByDependency({
173173
fromPath: rootPath,
174174
platform: PLATFORMS,
175175
includeSelf: true,

packages/host/src/node/path-utils.test.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -300,13 +300,13 @@ describe("findPackageDependencyPaths", () => {
300300
});
301301

302302
describe("findNodeApiModulePaths", () => {
303-
it("should find .apple.node paths", (context) => {
303+
it("should find .apple.node paths", async (context) => {
304304
const tempDir = setupTempDirectory(context, {
305305
"root.apple.node/react-native-node-api-module": "",
306306
"sub-directory/lib-a.apple.node/react-native-node-api-module": "",
307307
"sub-directory/lib-b.apple.node/react-native-node-api-module": "",
308308
});
309-
const result = findNodeApiModulePaths({
309+
const result = await findNodeApiModulePaths({
310310
fromPath: tempDir,
311311
platform: "apple",
312312
});
@@ -317,14 +317,15 @@ describe("findNodeApiModulePaths", () => {
317317
]);
318318
});
319319

320-
it("respects default exclude patterns", (context) => {
320+
it("respects default exclude patterns", async (context) => {
321321
const tempDir = setupTempDirectory(context, {
322322
"root.apple.node/react-native-node-api-module": "",
323+
"node_modules/dependency/lib.apple.node/react-native-node-api-module": "",
323324
"child-dir/dependency/lib.apple.node/react-native-node-api-module": "",
324325
"child-dir/node_modules/dependency/lib.apple.node/react-native-node-api-module":
325326
"",
326327
});
327-
const result = findNodeApiModulePaths({
328+
const result = await findNodeApiModulePaths({
328329
fromPath: tempDir,
329330
platform: "apple",
330331
});
@@ -334,14 +335,14 @@ describe("findNodeApiModulePaths", () => {
334335
]);
335336
});
336337

337-
it("respects explicit exclude patterns", (context) => {
338+
it("respects explicit exclude patterns", async (context) => {
338339
const tempDir = setupTempDirectory(context, {
339340
"root.apple.node/react-native-node-api-module": "",
340341
"child-dir/dependency/lib.apple.node/react-native-node-api-module": "",
341342
"child-dir/node_modules/dependency/lib.apple.node/react-native-node-api-module":
342343
"",
343344
});
344-
const result = findNodeApiModulePaths({
345+
const result = await findNodeApiModulePaths({
345346
fromPath: tempDir,
346347
platform: "apple",
347348
excludePatterns: [/root/],
@@ -352,13 +353,13 @@ describe("findNodeApiModulePaths", () => {
352353
]);
353354
});
354355

355-
it("disregards parts futher up in filesystem when excluding", (context) => {
356+
it("disregards parts futher up in filesystem when excluding", async (context) => {
356357
const tempDir = setupTempDirectory(context, {
357358
"node_modules/root.apple.node/react-native-node-api-module": "",
358359
"node_modules/child-dir/node_modules/dependency/lib.apple.node/react-native-node-api-module":
359360
"",
360361
});
361-
const result = findNodeApiModulePaths({
362+
const result = await findNodeApiModulePaths({
362363
fromPath: path.join(tempDir, "node_modules"),
363364
platform: "apple",
364365
});
@@ -415,13 +416,16 @@ describe("findNodeAddonForBindings()", () => {
415416
};
416417

417418
for (const [name, relPath] of Object.entries(expectedPaths)) {
418-
it(`should look for addons in common paths (${name} in "${relPath}")`, (context) => {
419+
it(`should look for addons in common paths (${name} in "${relPath}")`, async (context) => {
419420
// Arrange
420421
const tempDirectoryPath = setupTempDirectory(context, {
421422
[relPath]: "// This is supposed to be a binary file",
422423
});
423424
// Act
424-
const actualPath = findNodeAddonForBindings(name, tempDirectoryPath);
425+
const actualPath = await findNodeAddonForBindings(
426+
name,
427+
tempDirectoryPath
428+
);
425429
// Assert
426430
const expectedAbsPath = path.join(tempDirectoryPath, relPath);
427431
assert.equal(actualPath, expectedAbsPath);

packages/host/src/node/path-utils.ts

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,9 @@ export const MAGIC_FILENAME = "react-native-node-api-module";
279279
* Default patterns to use when excluding paths from the search for Node-API modules.
280280
*/
281281
export const DEFAULT_EXCLUDE_PATTERNS = [
282-
/\/react-native-node-api\//,
283-
/\/node_modules\//,
284-
/\/.git\//,
282+
/(^|\/)react-native-node-api\//,
283+
/(^|\/)node_modules\//,
284+
/(^|\/).git\//,
285285
];
286286

287287
export function hasPlatformExtension(
@@ -302,13 +302,12 @@ export type FindNodeApiModuleOptions = {
302302
};
303303

304304
/**
305-
* Recursively search into a directory for xcframeworks containing Node-API modules.
306-
* TODO: Turn this asynchronous
305+
* Recursively search into a directory for directories containing Node-API modules.
307306
*/
308-
export function findNodeApiModulePaths(
307+
export async function findNodeApiModulePaths(
309308
options: FindNodeApiModuleOptions,
310309
suffix = ""
311-
): string[] {
310+
): Promise<string[]> {
312311
const {
313312
fromPath,
314313
platform,
@@ -325,27 +324,33 @@ export function findNodeApiModulePaths(
325324
return [];
326325
}
327326

328-
return fs
329-
.readdirSync(candidatePath, { withFileTypes: true })
330-
.flatMap((file) => {
331-
if (
332-
file.isFile() &&
333-
file.name === MAGIC_FILENAME &&
334-
hasPlatformExtension(platform, candidatePath)
335-
) {
336-
return [candidatePath];
337-
} else if (file.isDirectory()) {
338-
// Traverse into the child directory
339-
return findNodeApiModulePaths(options, path.join(suffix, file.name));
340-
}
341-
return [];
342-
});
327+
const result: string[] = [];
328+
const pendingResults: Promise<string[]>[] = [];
329+
330+
for await (const dirent of await fs.promises.opendir(candidatePath)) {
331+
if (
332+
dirent.isFile() &&
333+
dirent.name === MAGIC_FILENAME &&
334+
hasPlatformExtension(platform, candidatePath)
335+
) {
336+
result.push(candidatePath);
337+
} else if (dirent.isDirectory()) {
338+
// Traverse into the child directory
339+
// Pushing result into a list instead of awaiting immediately to parallelize the search
340+
pendingResults.push(
341+
findNodeApiModulePaths(options, path.join(suffix, dirent.name))
342+
);
343+
}
344+
}
345+
const childResults = await Promise.all(pendingResults);
346+
result.push(...childResults.flatMap((filePath) => filePath));
347+
return result;
343348
}
344349

345350
/**
346351
* Finds all dependencies of the app package and their xcframeworks.
347352
*/
348-
export function findNodeApiModulePathsByDependency({
353+
export async function findNodeApiModulePathsByDependency({
349354
fromPath,
350355
includeSelf,
351356
...options
@@ -360,25 +365,32 @@ export function findNodeApiModulePathsByDependency({
360365
const { name } = readPackageSync({ cwd: packageRoot });
361366
packagePathsByName[name] = packageRoot;
362367
}
363-
// Find all their xcframeworks
364-
return Object.fromEntries(
365-
Object.entries(packagePathsByName)
366-
.map(([dependencyName, dependencyPath]) => {
368+
369+
// Find all their node api module paths
370+
const resultEntries = await Promise.all(
371+
Object.entries(packagePathsByName).map(
372+
async ([dependencyName, dependencyPath]) => {
367373
// Make all the xcframeworks relative to the dependency path
368-
const modulePaths = findNodeApiModulePaths({
374+
const absoluteModulePaths = await findNodeApiModulePaths({
369375
fromPath: dependencyPath,
370376
...options,
371-
}).map((p) => path.relative(dependencyPath, p));
377+
});
372378
return [
373379
dependencyName,
374380
{
375381
path: dependencyPath,
376-
modulePaths,
382+
modulePaths: absoluteModulePaths.map((p) =>
383+
path.relative(dependencyPath, p)
384+
),
377385
},
378386
] as const;
379-
})
380-
// Remove any dependencies without module paths
381-
.filter(([, { modulePaths }]) => modulePaths.length > 0)
387+
}
388+
)
389+
);
390+
// Return an object by dependency name
391+
return Object.fromEntries(
392+
// Remove any dependencies without Node-API module paths
393+
resultEntries.filter(([, { modulePaths }]) => modulePaths.length > 0)
382394
);
383395
}
384396

0 commit comments

Comments
 (0)