first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
import { PackageRevision, SupportedPlatform } from '../types';
import { type ResolutionResult } from './types';
import { type Memoizer } from '../memoize';
import { RNConfigReactNativeProjectConfig } from '../reactNativeConfig';
export interface CachedDependenciesSearchOptions {
excludeNames: Set<string>;
searchPaths: string[];
}
export interface CachedDependenciesLinker {
memoizer: Memoizer;
getOptionsForPlatform(platform: SupportedPlatform): Promise<CachedDependenciesSearchOptions>;
loadReactNativeProjectConfig(): Promise<RNConfigReactNativeProjectConfig | null>;
scanDependenciesFromRNProjectConfig(): Promise<ResolutionResult>;
scanDependenciesRecursively(): Promise<ResolutionResult>;
scanDependenciesInSearchPath(searchPath: string): Promise<ResolutionResult>;
}
export declare function makeCachedDependenciesLinker(params: {
projectRoot: string;
}): CachedDependenciesLinker;
export declare function scanDependencyResolutionsForPlatform(linker: CachedDependenciesLinker, platform: SupportedPlatform, include?: string[]): Promise<ResolutionResult>;
export declare function scanExpoModuleResolutionsForPlatform(linker: CachedDependenciesLinker, platform: SupportedPlatform): Promise<Record<string, PackageRevision>>;

View File

@@ -0,0 +1,130 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeCachedDependenciesLinker = makeCachedDependenciesLinker;
exports.scanDependencyResolutionsForPlatform = scanDependencyResolutionsForPlatform;
exports.scanExpoModuleResolutionsForPlatform = scanExpoModuleResolutionsForPlatform;
const fs_1 = __importDefault(require("fs"));
const resolution_1 = require("./resolution");
const rncliLocal_1 = require("./rncliLocal");
const scanning_1 = require("./scanning");
const utils_1 = require("./utils");
const findModules_1 = require("../autolinking/findModules");
const autolinkingOptions_1 = require("../commands/autolinkingOptions");
const memoize_1 = require("../memoize");
const reactNativeConfig_1 = require("../reactNativeConfig");
const config_1 = require("../reactNativeConfig/config");
function makeCachedDependenciesLinker(params) {
const memoizer = (0, memoize_1.createMemoizer)();
const autolinkingOptionsLoader = (0, autolinkingOptions_1.createAutolinkingOptionsLoader)({
projectRoot: params.projectRoot,
});
let appRoot;
const getAppRoot = () => appRoot || (appRoot = autolinkingOptionsLoader.getAppRoot());
const dependenciesResultBySearchPath = new Map();
let reactNativeProjectConfig;
let reactNativeProjectConfigDependencies;
let recursiveDependencies;
return {
memoizer,
async getOptionsForPlatform(platform) {
const options = await autolinkingOptionsLoader.getPlatformOptions(platform);
return makeCachedDependenciesSearchOptions(options);
},
async loadReactNativeProjectConfig() {
if (reactNativeProjectConfig === undefined) {
reactNativeProjectConfig = memoizer.call(config_1.loadConfigAsync, await getAppRoot());
}
return reactNativeProjectConfig;
},
async scanDependenciesFromRNProjectConfig() {
if (reactNativeProjectConfigDependencies === undefined) {
reactNativeProjectConfigDependencies = memoizer.withMemoizer(async () => {
return await (0, rncliLocal_1.scanDependenciesFromRNProjectConfig)(await getAppRoot(), await this.loadReactNativeProjectConfig());
});
}
return reactNativeProjectConfigDependencies;
},
async scanDependenciesRecursively() {
if (recursiveDependencies === undefined) {
recursiveDependencies = memoizer.withMemoizer(async () => {
return (0, resolution_1.scanDependenciesRecursively)(await getAppRoot());
});
}
return recursiveDependencies;
},
async scanDependenciesInSearchPath(searchPath) {
let result = dependenciesResultBySearchPath.get(searchPath);
if (!result) {
dependenciesResultBySearchPath.set(searchPath, (result = memoizer.withMemoizer(scanning_1.scanDependenciesInSearchPath, searchPath)));
}
return result;
},
};
}
async function scanDependencyResolutionsForPlatform(linker, platform, include) {
const { excludeNames, searchPaths } = await linker.getOptionsForPlatform(platform);
const includeNames = new Set(include);
const reactNativeProjectConfig = await linker.loadReactNativeProjectConfig();
const resolutions = (0, utils_1.mergeResolutionResults)(await Promise.all([
linker.scanDependenciesFromRNProjectConfig(),
...searchPaths.map((searchPath) => {
return linker.scanDependenciesInSearchPath(searchPath);
}),
linker.scanDependenciesRecursively(),
]));
return await linker.memoizer.withMemoizer(async () => {
const dependencies = await (0, utils_1.filterMapResolutionResult)(resolutions, async (resolution) => {
if (excludeNames.has(resolution.name)) {
return null;
}
else if (includeNames.has(resolution.name)) {
return resolution;
}
else if (resolution.source === 2 /* DependencyResolutionSource.RN_CLI_LOCAL */) {
// If the dependency was resolved frpom the React Native project config, we'll only
// attempt to resolve it as a React Native module
const reactNativeModuleDesc = await (0, reactNativeConfig_1.resolveReactNativeModule)(resolution, reactNativeProjectConfig, platform, excludeNames);
if (!reactNativeModuleDesc) {
return null;
}
}
else {
const [reactNativeModule, expoModule] = await Promise.all([
(0, reactNativeConfig_1.resolveReactNativeModule)(resolution, reactNativeProjectConfig, platform, excludeNames),
(0, findModules_1.resolveExpoModule)(resolution, platform, excludeNames),
]);
if (!reactNativeModule && !expoModule) {
return null;
}
}
return resolution;
});
return dependencies;
});
}
async function scanExpoModuleResolutionsForPlatform(linker, platform) {
const { excludeNames, searchPaths } = await linker.getOptionsForPlatform(platform);
const resolutions = (0, utils_1.mergeResolutionResults)(await Promise.all([
...searchPaths.map((searchPath) => {
return linker.scanDependenciesInSearchPath(searchPath);
}),
linker.scanDependenciesRecursively(),
].filter((x) => x != null)));
return await linker.memoizer.withMemoizer(async () => {
return await (0, utils_1.filterMapResolutionResult)(resolutions, async (resolution) => {
return !excludeNames.has(resolution.name)
? await (0, findModules_1.resolveExpoModule)(resolution, platform, excludeNames)
: null;
});
});
}
const makeCachedDependenciesSearchOptions = (options) => ({
excludeNames: new Set(options.exclude),
searchPaths: options.nativeModulesDir && fs_1.default.existsSync(options.nativeModulesDir)
? [options.nativeModulesDir, ...(options.searchPaths ?? [])]
: (options.searchPaths ?? []),
});
//# sourceMappingURL=CachedDependenciesLinker.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,6 @@
export { scanDependenciesRecursively } from './resolution';
export { scanDependenciesInSearchPath } from './scanning';
export { scanDependenciesFromRNProjectConfig } from './rncliLocal';
export { filterMapResolutionResult, mergeResolutionResults } from './utils';
export * from './CachedDependenciesLinker';
export * from './types';

View File

@@ -0,0 +1,29 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.mergeResolutionResults = exports.filterMapResolutionResult = exports.scanDependenciesFromRNProjectConfig = exports.scanDependenciesInSearchPath = exports.scanDependenciesRecursively = void 0;
var resolution_1 = require("./resolution");
Object.defineProperty(exports, "scanDependenciesRecursively", { enumerable: true, get: function () { return resolution_1.scanDependenciesRecursively; } });
var scanning_1 = require("./scanning");
Object.defineProperty(exports, "scanDependenciesInSearchPath", { enumerable: true, get: function () { return scanning_1.scanDependenciesInSearchPath; } });
var rncliLocal_1 = require("./rncliLocal");
Object.defineProperty(exports, "scanDependenciesFromRNProjectConfig", { enumerable: true, get: function () { return rncliLocal_1.scanDependenciesFromRNProjectConfig; } });
var utils_1 = require("./utils");
Object.defineProperty(exports, "filterMapResolutionResult", { enumerable: true, get: function () { return utils_1.filterMapResolutionResult; } });
Object.defineProperty(exports, "mergeResolutionResults", { enumerable: true, get: function () { return utils_1.mergeResolutionResults; } });
__exportStar(require("./CachedDependenciesLinker"), exports);
__exportStar(require("./types"), exports);
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dependencies/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2CAA2D;AAAlD,yHAAA,2BAA2B,OAAA;AACpC,uCAA0D;AAAjD,wHAAA,4BAA4B,OAAA;AACrC,2CAAmE;AAA1D,iIAAA,mCAAmC,OAAA;AAC5C,iCAA4E;AAAnE,kHAAA,yBAAyB,OAAA;AAAE,+GAAA,sBAAsB,OAAA;AAC1D,6DAA2C;AAC3C,0CAAwB","sourcesContent":["export { scanDependenciesRecursively } from './resolution';\nexport { scanDependenciesInSearchPath } from './scanning';\nexport { scanDependenciesFromRNProjectConfig } from './rncliLocal';\nexport { filterMapResolutionResult, mergeResolutionResults } from './utils';\nexport * from './CachedDependenciesLinker';\nexport * from './types';\n"]}

View File

@@ -0,0 +1,10 @@
import { type ResolutionResult } from './types';
declare module 'node:module' {
function _nodeModulePaths(base: string): readonly string[];
}
interface ResolutionOptions {
shouldIncludeDependency?(name: string): boolean;
limitDepth?: number;
}
export declare function scanDependenciesRecursively(rawPath: string, { shouldIncludeDependency, limitDepth }?: ResolutionOptions): Promise<ResolutionResult>;
export {};

View File

@@ -0,0 +1,137 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.scanDependenciesRecursively = scanDependenciesRecursively;
const node_module_1 = __importDefault(require("node:module"));
const utils_1 = require("./utils");
const concurrency_1 = require("../concurrency");
const utils_2 = require("../utils");
// NOTE(@kitten): There's no need to search very deep for modules
// We don't expect native modules to be excessively nested in the dependency tree
const MAX_DEPTH = 8;
const createNodeModulePathsCreator = () => {
const _nodeModulePathCache = new Map();
return async function getNodeModulePaths(packagePath) {
const outputPaths = [];
const nodeModulePaths = node_module_1.default._nodeModulePaths(packagePath);
for (let idx = 0; idx < nodeModulePaths.length; idx++) {
const nodeModulePath = nodeModulePaths[idx];
let target = _nodeModulePathCache.get(nodeModulePath);
if (target === undefined) {
target = await (0, utils_2.maybeRealpath)(nodeModulePath);
if (idx !== 0) {
_nodeModulePathCache.set(nodeModulePath, target);
}
}
if (target != null) {
outputPaths.push(target);
}
}
return outputPaths;
};
};
async function resolveDependencies(packageJson, nodeModulePaths, depth, shouldIncludeDependency) {
const dependencies = Object.create(null);
if (packageJson.dependencies != null && typeof packageJson.dependencies === 'object') {
Object.assign(dependencies, packageJson.dependencies);
}
// NOTE(@kitten): Also traverse devDependencies for top-level package.json
if (depth === 0 &&
packageJson.devDependencies != null &&
typeof packageJson.devDependencies === 'object') {
Object.assign(dependencies, packageJson.devDependencies);
}
if (packageJson.peerDependencies != null && typeof packageJson.peerDependencies === 'object') {
const peerDependenciesMeta = packageJson.peerDependenciesMeta != null &&
typeof packageJson.peerDependenciesMeta === 'object'
? packageJson.peerDependenciesMeta
: undefined;
for (const dependencyName in packageJson.peerDependencies) {
// NOTE(@kitten): We only check peer dependencies because some package managers auto-install them
// which would mean they'd have no reference in any dependencies. However, optional peer dependencies
// don't auto-install and we can skip them
if (!isOptionalPeerDependencyMeta(peerDependenciesMeta, dependencyName)) {
dependencies[dependencyName] = '';
}
}
}
const resolveDependency = async (dependencyName) => {
for (let idx = 0; idx < nodeModulePaths.length; idx++) {
const originPath = (0, utils_2.fastJoin)(nodeModulePaths[idx], dependencyName);
const nodeModulePath = await (0, utils_2.maybeRealpath)(originPath);
if (nodeModulePath != null) {
return {
source: 0 /* DependencyResolutionSource.RECURSIVE_RESOLUTION */,
name: dependencyName,
version: '',
path: nodeModulePath,
originPath,
duplicates: null,
depth,
};
}
}
return null;
};
const modules = await (0, concurrency_1.taskAll)(Object.keys(dependencies).filter((dependencyName) => shouldIncludeDependency(dependencyName)), (dependencyName) => resolveDependency(dependencyName));
return modules.filter((resolution) => resolution != null);
}
async function scanDependenciesRecursively(rawPath, { shouldIncludeDependency = utils_1.defaultShouldIncludeDependency, limitDepth } = {}) {
const rootPath = await (0, utils_2.maybeRealpath)(rawPath);
if (!rootPath) {
return {};
}
const _visitedPackagePaths = new Set();
const getNodeModulePaths = createNodeModulePathsCreator();
const maxDepth = limitDepth != null ? limitDepth : MAX_DEPTH;
const recurse = async (resolution, depth = 0) => {
const searchResults = Object.create(null);
if (_visitedPackagePaths.has(resolution.path)) {
return searchResults;
}
else {
_visitedPackagePaths.add(resolution.path);
}
const [nodeModulePaths, packageJson] = await Promise.all([
getNodeModulePaths(resolution.path),
(0, utils_2.loadPackageJson)((0, utils_2.fastJoin)(resolution.path, 'package.json')),
]);
if (!packageJson) {
return searchResults;
}
else {
resolution.version = packageJson.version || '';
}
const modules = await resolveDependencies(packageJson, nodeModulePaths, depth, shouldIncludeDependency);
for (let idx = 0; idx < modules.length; idx++) {
searchResults[modules[idx].name] = modules[idx];
}
if (depth + 1 < maxDepth) {
const childResults = await (0, concurrency_1.taskAll)(modules, (resolution) => recurse(resolution, depth + 1));
return (0, utils_1.mergeResolutionResults)(childResults, searchResults);
}
else {
return searchResults;
}
};
const searchResults = await recurse({
source: 0 /* DependencyResolutionSource.RECURSIVE_RESOLUTION */,
name: '',
version: '',
path: rootPath,
originPath: rawPath,
duplicates: null,
depth: -1,
});
return searchResults;
}
const isOptionalPeerDependencyMeta = (peerDependenciesMeta, packageName) => {
return (peerDependenciesMeta &&
peerDependenciesMeta[packageName] != null &&
typeof peerDependenciesMeta[packageName] === 'object' &&
'optional' in peerDependenciesMeta[packageName] &&
!!peerDependenciesMeta[packageName].optional);
};
//# sourceMappingURL=resolution.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
import { type ResolutionResult } from './types';
import { RNConfigReactNativeProjectConfig } from '../reactNativeConfig';
interface ResolutionOptions {
shouldIncludeDependency?(name: string): boolean;
}
export declare function scanDependenciesFromRNProjectConfig(rawPath: string, projectConfig: RNConfigReactNativeProjectConfig | null, { shouldIncludeDependency }?: ResolutionOptions): Promise<ResolutionResult>;
export {};

View File

@@ -0,0 +1,37 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.scanDependenciesFromRNProjectConfig = scanDependenciesFromRNProjectConfig;
const path_1 = __importDefault(require("path"));
const utils_1 = require("./utils");
const concurrency_1 = require("../concurrency");
const utils_2 = require("../utils");
async function scanDependenciesFromRNProjectConfig(rawPath, projectConfig, { shouldIncludeDependency = utils_1.defaultShouldIncludeDependency } = {}) {
const rootPath = await (0, utils_2.maybeRealpath)(rawPath);
const searchResults = Object.create(null);
if (!rootPath || !projectConfig || !projectConfig.dependencies) {
return searchResults;
}
await (0, concurrency_1.taskAll)(Object.keys(projectConfig.dependencies).filter((dependencyName) => shouldIncludeDependency(dependencyName)), async (dependencyName) => {
const dependencyConfig = projectConfig.dependencies[dependencyName];
if (dependencyConfig && dependencyConfig.root && typeof dependencyConfig.root === 'string') {
const originPath = path_1.default.resolve(rootPath, dependencyConfig.root);
const realPath = await (0, utils_2.maybeRealpath)(originPath);
if (realPath) {
searchResults[dependencyName] = {
source: 2 /* DependencyResolutionSource.RN_CLI_LOCAL */,
name: dependencyName,
version: '',
path: realPath,
originPath,
duplicates: null,
depth: 0,
};
}
}
});
return searchResults;
}
//# sourceMappingURL=rncliLocal.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"rncliLocal.js","sourceRoot":"","sources":["../../src/dependencies/rncliLocal.ts"],"names":[],"mappings":";;;;;AAYA,kFAoCC;AAhDD,gDAAwB;AAGxB,mCAAyD;AACzD,gDAAyC;AAEzC,oCAAyC;AAMlC,KAAK,UAAU,mCAAmC,CACvD,OAAe,EACf,aAAsD,EACtD,EAAE,uBAAuB,GAAG,sCAA8B,KAAwB,EAAE;IAEpF,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAqB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC,QAAQ,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;QAC/D,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,MAAM,IAAA,qBAAO,EACX,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,cAAc,EAAE,EAAE,CAChE,uBAAuB,CAAC,cAAc,CAAC,CACxC,EACD,KAAK,EAAE,cAAc,EAAE,EAAE;QACvB,MAAM,gBAAgB,GAAG,aAAa,CAAC,YAAa,CAAC,cAAc,CAAC,CAAC;QACrE,IAAI,gBAAgB,IAAI,gBAAgB,CAAC,IAAI,IAAI,OAAO,gBAAgB,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3F,MAAM,UAAU,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACjE,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,UAAU,CAAC,CAAC;YACjD,IAAI,QAAQ,EAAE,CAAC;gBACb,aAAa,CAAC,cAAc,CAAC,GAAG;oBAC9B,MAAM,iDAAyC;oBAC/C,IAAI,EAAE,cAAc;oBACpB,OAAO,EAAE,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,UAAU;oBACV,UAAU,EAAE,IAAI;oBAChB,KAAK,EAAE,CAAC;iBACT,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC,CACF,CAAC;IAEF,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import path from 'path';\n\nimport { DependencyResolutionSource, type ResolutionResult } from './types';\nimport { defaultShouldIncludeDependency } from './utils';\nimport { taskAll } from '../concurrency';\nimport { RNConfigReactNativeProjectConfig } from '../reactNativeConfig';\nimport { maybeRealpath } from '../utils';\n\ninterface ResolutionOptions {\n shouldIncludeDependency?(name: string): boolean;\n}\n\nexport async function scanDependenciesFromRNProjectConfig(\n rawPath: string,\n projectConfig: RNConfigReactNativeProjectConfig | null,\n { shouldIncludeDependency = defaultShouldIncludeDependency }: ResolutionOptions = {}\n): Promise<ResolutionResult> {\n const rootPath = await maybeRealpath(rawPath);\n const searchResults: ResolutionResult = Object.create(null);\n if (!rootPath || !projectConfig || !projectConfig.dependencies) {\n return searchResults;\n }\n\n await taskAll(\n Object.keys(projectConfig.dependencies).filter((dependencyName) =>\n shouldIncludeDependency(dependencyName)\n ),\n async (dependencyName) => {\n const dependencyConfig = projectConfig.dependencies![dependencyName];\n if (dependencyConfig && dependencyConfig.root && typeof dependencyConfig.root === 'string') {\n const originPath = path.resolve(rootPath, dependencyConfig.root);\n const realPath = await maybeRealpath(originPath);\n if (realPath) {\n searchResults[dependencyName] = {\n source: DependencyResolutionSource.RN_CLI_LOCAL,\n name: dependencyName,\n version: '',\n path: realPath,\n originPath,\n duplicates: null,\n depth: 0,\n };\n }\n }\n }\n );\n\n return searchResults;\n}\n"]}

View File

@@ -0,0 +1,6 @@
import { type ResolutionResult } from './types';
interface ResolutionOptions {
shouldIncludeDependency?(name: string): boolean;
}
export declare function scanDependenciesInSearchPath(rawPath: string, { shouldIncludeDependency }?: ResolutionOptions): Promise<ResolutionResult>;
export {};

View File

@@ -0,0 +1,112 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.scanDependenciesInSearchPath = scanDependenciesInSearchPath;
const fs_1 = __importDefault(require("fs"));
const concurrency_1 = require("../concurrency");
const utils_1 = require("./utils");
const utils_2 = require("../utils");
async function resolveDependency(basePath, dependencyName, shouldIncludeDependency) {
if (dependencyName && !shouldIncludeDependency(dependencyName)) {
return null;
}
const originPath = dependencyName ? (0, utils_2.fastJoin)(basePath, dependencyName) : basePath;
const realPath = await (0, utils_2.maybeRealpath)(originPath);
const packageJson = await (0, utils_2.loadPackageJson)((0, utils_2.fastJoin)(realPath || originPath, 'package.json'));
if (packageJson) {
return {
source: 1 /* DependencyResolutionSource.SEARCH_PATH */,
name: packageJson.name || '',
version: packageJson.version || '',
path: realPath || originPath,
originPath,
duplicates: null,
depth: 0,
};
}
else if (dependencyName && realPath) {
return {
source: 1 /* DependencyResolutionSource.SEARCH_PATH */,
name: dependencyName.toLowerCase(),
version: '',
path: realPath,
originPath,
duplicates: null,
depth: 0,
};
}
else {
return null;
}
}
async function scanDependenciesInSearchPath(rawPath, { shouldIncludeDependency = utils_1.defaultShouldIncludeDependency } = {}) {
const rootPath = await (0, utils_2.maybeRealpath)(rawPath);
const searchResults = Object.create(null);
if (!rootPath) {
return searchResults;
}
const resolvedDependencies = [];
const localModuleTarget = await (0, utils_2.maybeRealpath)((0, utils_2.fastJoin)(rootPath, 'package.json'));
if (localModuleTarget) {
// If we have a `package.json` file in the search path, we're already dealing with a node module
// and can skip the rest. This is a special case created by create-expo-module's `nativeModulesDir: ../`
const resolution = await resolveDependency(rootPath, null, shouldIncludeDependency);
if (resolution)
resolvedDependencies.push(resolution);
}
else {
const dirents = await fs_1.default.promises.readdir(rootPath, { withFileTypes: true });
await (0, concurrency_1.taskAll)(dirents, async (entry) => {
if (entry.isSymbolicLink()) {
const resolution = await resolveDependency(rootPath, entry.name, shouldIncludeDependency);
if (resolution)
resolvedDependencies.push(resolution);
}
else if (entry.isDirectory()) {
if (entry.name === 'node_modules') {
// Ignore nested node_modules folder
}
if (entry.name[0] === '.') {
// Ignore hidden folders
}
else if (entry.name[0] === '@') {
// NOTE: We don't expect @-scope folders to be symlinks
const entryPath = (0, utils_2.fastJoin)(rootPath, entry.name);
const childEntries = await fs_1.default.promises.readdir(entryPath, { withFileTypes: true });
await Promise.all(childEntries.map(async (child) => {
const dependencyName = `${entry.name}/${child.name}`;
if (child.isDirectory() || child.isSymbolicLink()) {
const resolution = await resolveDependency(rootPath, dependencyName, shouldIncludeDependency);
if (resolution)
resolvedDependencies.push(resolution);
}
}));
}
else {
const resolution = await resolveDependency(rootPath, entry.name, shouldIncludeDependency);
if (resolution)
resolvedDependencies.push(resolution);
}
}
});
}
for (let idx = 0; idx < resolvedDependencies.length; idx++) {
const resolution = resolvedDependencies[idx];
const prevEntry = searchResults[resolution.name];
if (prevEntry != null && resolution.path !== prevEntry.path) {
(prevEntry.duplicates ?? (prevEntry.duplicates = [])).push({
name: resolution.name,
version: resolution.version,
path: resolution.path,
originPath: resolution.originPath,
});
}
else if (prevEntry == null) {
searchResults[resolution.name] = resolution;
}
}
return searchResults;
}
//# sourceMappingURL=scanning.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,18 @@
export declare const enum DependencyResolutionSource {
RECURSIVE_RESOLUTION = 0,
SEARCH_PATH = 1,
RN_CLI_LOCAL = 2
}
export interface BaseDependencyResolution {
name: string;
version: string;
path: string;
originPath: string;
}
export interface DependencyResolution extends BaseDependencyResolution {
source: DependencyResolutionSource;
duplicates: BaseDependencyResolution[] | null;
depth: number;
[prop: string]: unknown;
}
export type ResolutionResult = Record<string, DependencyResolution | undefined>;

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/dependencies/types.ts"],"names":[],"mappings":"","sourcesContent":["export const enum DependencyResolutionSource {\n RECURSIVE_RESOLUTION,\n SEARCH_PATH,\n RN_CLI_LOCAL,\n}\n\nexport interface BaseDependencyResolution {\n name: string;\n version: string;\n path: string;\n originPath: string;\n}\n\nexport interface DependencyResolution extends BaseDependencyResolution {\n source: DependencyResolutionSource;\n duplicates: BaseDependencyResolution[] | null;\n depth: number;\n [prop: string]: unknown;\n}\n\nexport type ResolutionResult = Record<string, DependencyResolution | undefined>;\n"]}

View File

@@ -0,0 +1,7 @@
import { type DependencyResolution, type ResolutionResult } from './types';
export declare function defaultShouldIncludeDependency(dependencyName: string): boolean;
export declare function mergeWithDuplicate(a: DependencyResolution, b: DependencyResolution): DependencyResolution;
export declare function filterMapResolutionResult<T extends {
name: string;
}>(results: ResolutionResult, filterMap: (resolution: DependencyResolution) => Promise<T | null> | T | null): Promise<Record<string, T>>;
export declare function mergeResolutionResults(results: ResolutionResult[], base?: ResolutionResult): ResolutionResult;

View File

@@ -0,0 +1,142 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultShouldIncludeDependency = defaultShouldIncludeDependency;
exports.mergeWithDuplicate = mergeWithDuplicate;
exports.filterMapResolutionResult = filterMapResolutionResult;
exports.mergeResolutionResults = mergeResolutionResults;
const path_1 = __importDefault(require("path"));
const concurrency_1 = require("../concurrency");
const NODE_MODULES_PATTERN = `${path_1.default.sep}node_modules${path_1.default.sep}`;
// The default dependencies we exclude don't contain dependency chains leading to autolinked modules
function defaultShouldIncludeDependency(dependencyName) {
const scopeName = dependencyName[0] === '@' ? dependencyName.slice(1, dependencyName.indexOf('/')) : null;
if (scopeName === 'babel' ||
scopeName === 'types' ||
scopeName === 'eslint' ||
scopeName === 'typescript-eslint' ||
scopeName === 'testing-library' ||
scopeName === 'aws-crypto' ||
scopeName === 'aws-sdk') {
return false;
}
switch (dependencyName) {
case '@expo/cli':
case '@expo/config':
case '@expo/metro-config':
case '@expo/package-manager':
case '@expo/prebuild-config':
case '@expo/webpack-config':
case '@expo/env':
case '@react-native/codegen':
case '@react-native/community-cli-plugin':
case 'eslint':
case 'eslint-config-expo':
case 'eslint-plugin-expo':
case 'eslint-plugin-import':
case 'jest-expo':
case 'jest':
case 'metro':
case 'ts-node':
case 'typescript':
case 'webpack':
return false;
default:
return true;
}
}
function mergeWithDuplicate(a, b) {
let target;
let duplicate;
if (a.depth < b.depth) {
target = a;
duplicate = b;
}
else if (b.depth < a.depth) {
target = b;
duplicate = a;
}
else {
// If both are equal, then the shallowest path wins
const pathDepthA = a.originPath.split(NODE_MODULES_PATTERN).length;
const pathDepthB = b.originPath.split(NODE_MODULES_PATTERN).length;
if (pathDepthA < pathDepthB) {
target = a;
duplicate = b;
}
else if (pathDepthB < pathDepthA) {
target = b;
duplicate = a;
}
else {
target = a;
duplicate = b;
}
}
const duplicates = target.duplicates || (target.duplicates = []);
if (target.path !== duplicate.path) {
if (duplicates.every((parent) => parent.path !== duplicate.path)) {
duplicates.push({
name: duplicate.name,
version: duplicate.version,
path: duplicate.path,
originPath: duplicate.originPath,
});
}
}
else if (!target.version && duplicate.version) {
target.version = duplicate.version;
}
if (duplicate.duplicates?.length) {
duplicates.push(...duplicate.duplicates.filter((child) => duplicates.every((parent) => parent.path !== child.path)));
}
return target;
}
async function filterMapResolutionResult(results, filterMap) {
const resolutions = await (0, concurrency_1.taskAll)(Object.keys(results), async (key) => {
const resolution = results[key];
const result = resolution ? await filterMap(resolution) : null;
// If we failed to find a matching resolution from `searchPaths`, also try the other duplicates
// to see if the `searchPaths` result is not a module but another is
if (resolution?.source === 1 /* DependencyResolutionSource.SEARCH_PATH */ && !result) {
for (let idx = 0; resolution.duplicates && idx < resolution.duplicates.length; idx++) {
const duplicate = resolution.duplicates[idx];
const duplicateResult = await filterMap({ ...resolution, ...duplicate });
if (duplicateResult != null) {
return duplicateResult;
}
}
}
return result;
});
const output = Object.create(null);
for (let idx = 0; idx < resolutions.length; idx++) {
const resolution = resolutions[idx];
if (resolution != null) {
output[resolution.name] = resolution;
}
}
return output;
}
function mergeResolutionResults(results, base) {
if (base == null && results.length === 1) {
return results[0];
}
const output = base == null ? Object.create(null) : base;
for (let idx = 0; idx < results.length; idx++) {
for (const key in results[idx]) {
const resolution = results[idx][key];
const prevResolution = output[key];
if (prevResolution != null) {
output[key] = mergeWithDuplicate(prevResolution, resolution);
}
else {
output[key] = resolution;
}
}
}
return output;
}
//# sourceMappingURL=utils.js.map

File diff suppressed because one or more lines are too long