{"version":3,"file":"traversalNodeModulesCollector.js","sourceRoot":"","sources":["../../src/node-module-collector/traversalNodeModulesCollector.ts"],"names":[],"mappings":"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","sourcesContent":["import { log } from \"builder-util\"\nimport * as path from \"path\"\nimport { LogMessageByKey } from \"./moduleManager\"\nimport { NodeModulesCollector } from \"./nodeModulesCollector\"\nimport { PM } from \"./packageManager.js\"\nimport { TraversedDependency } from \"./types.js\"\n\n// manual traversal of node_modules for package managers without CLI support for dependency tree extraction (e.g., bun) OR as a fallback (e.g. corepack enabled w/ strict mode)\nexport class TraversalNodeModulesCollector extends NodeModulesCollector<TraversedDependency, TraversedDependency> {\n  public installOptions = {\n    manager: PM.TRAVERSAL,\n    lockfile: \"none\",\n  }\n\n  protected getArgs(): string[] {\n    return []\n  }\n\n  protected getDependenciesTree(_pm: PM): Promise<TraversedDependency> {\n    log.info(null, \"using manual traversal of node_modules to build dependency tree\")\n    return this.buildNodeModulesTreeManually(this.rootDir, undefined)\n  }\n\n  protected async collectAllDependencies(tree: TraversedDependency, appPackageName: string) {\n    for (const [packageKey, value] of Object.entries({ ...tree.dependencies, ...tree.optionalDependencies })) {\n      const normalizedDep = this.normalizePackageVersion(packageKey, value)\n      this.allDependencies.set(normalizedDep.id, normalizedDep.pkgOverride)\n      await this.collectAllDependencies(value, appPackageName)\n    }\n  }\n\n  // we don't need to check optional dependencies here because they're pre-processed in `buildNodeModulesTreeManually`\n  protected async extractProductionDependencyGraph(tree: TraversedDependency, dependencyId: string): Promise<void> {\n    if (this.productionGraph[dependencyId]) {\n      return\n    }\n    this.productionGraph[dependencyId] = { dependencies: [] }\n\n    const prodDependencies = { ...(tree.dependencies || {}), ...(tree.optionalDependencies || {}) }\n\n    const collectedDependencies: string[] = []\n    for (const packageName in prodDependencies) {\n      const dependency = prodDependencies[packageName]\n      const { id: childDependencyId, pkgOverride } = this.normalizePackageVersion(packageName, dependency)\n      await this.extractProductionDependencyGraph(pkgOverride, childDependencyId)\n      collectedDependencies.push(childDependencyId)\n    }\n    this.productionGraph[dependencyId] = { dependencies: collectedDependencies }\n  }\n\n  /**\n   * Builds a dependency tree using only package.json dependencies and optionalDependencies.\n   * This skips devDependencies and uses Node.js module resolution (require.resolve).\n   */\n  private async buildNodeModulesTreeManually(baseDir: string, aliasName: string | undefined): Promise<TraversedDependency> {\n    // Track visited packages by their resolved path to prevent infinite loops\n    const visited = new Set<string>()\n    const resolvedBaseDir = await this.cache.realPath[baseDir]\n\n    /**\n     * Recursively builds dependency tree starting from a package directory.\n     * @param packageDir - The directory of the package to process\n     * @param aliasName - Optional alias name for npm aliased dependencies (e.g., \"foo\": \"npm:@scope/bar@1.0.0\")\n     *                    When provided, this name is used instead of the package.json name for the module name,\n     *                    ensuring the package is copied to the correct location in node_modules.\n     */\n    const buildFromPackage = async (packageDir: string, aliasName: string | undefined): Promise<TraversedDependency> => {\n      const pkgPath = path.join(packageDir, \"package.json\")\n\n      if (!(await this.cache.exists[pkgPath])) {\n        throw new Error(`package.json not found at ${pkgPath}`)\n      }\n\n      const pkg = (await this.cache.json[pkgPath])!\n      const resolvedPackageDir = await this.cache.realPath[packageDir]\n\n      // Use the alias name if provided, otherwise fall back to the package.json name\n      // This ensures npm aliased packages are copied to the correct location\n      const moduleName = aliasName ?? pkg.name\n\n      // Use resolved path as the unique identifier to prevent circular dependencies\n      if (visited.has(resolvedPackageDir)) {\n        log.debug({ name: moduleName, version: pkg.version, path: resolvedPackageDir }, \"skipping already visited package\")\n\n        return {\n          name: moduleName,\n          version: pkg.version,\n          path: resolvedPackageDir,\n        }\n      }\n\n      visited.add(resolvedPackageDir)\n\n      const buildPackage = async (dependencies: Record<string, string> | undefined, nullHandler: (depName: string, version: string) => void) => {\n        const builtPackages: Record<string, TraversedDependency> = {}\n        for (const [depName, depVersion] of Object.entries(dependencies || {})) {\n          const pkg = await this.locatePackageWithVersion({ name: depName, version: depVersion, path: resolvedPackageDir })\n\n          const logFields = { parent: moduleName, dependency: depName, version: depVersion }\n          if (pkg == null) {\n            nullHandler(depName, depVersion)\n            continue\n          }\n\n          // Skip if this dependency resolves to the base directory or any parent we're already processing\n          if (pkg.packageDir === resolvedPackageDir || pkg.packageDir === resolvedBaseDir) {\n            this.cache.logSummary[LogMessageByKey.PKG_SELF_REF].push(`${depName}@${depVersion}`)\n            continue\n          }\n\n          log.debug(logFields, \"processing production dependency\")\n          builtPackages[depName] = await buildFromPackage(pkg.packageDir, depName)\n        }\n        return builtPackages\n      }\n\n      const prodDeps = await buildPackage(pkg.dependencies, (depName: string, version: string) => {\n        log.error({ parent: moduleName, dependency: depName, version }, \"production dependency not found\")\n        throw new Error(`Production dependency ${depName} not found for package ${moduleName}`)\n      })\n\n      const optionalDeps = await buildPackage(pkg.optionalDependencies, (depName: string, version: string) => {\n        log.debug({ parent: moduleName, dependency: depName }, \"optional dependency not installed, skipping\")\n        this.cache.logSummary[LogMessageByKey.PKG_OPTIONAL_NOT_INSTALLED].push(`${depName}@${version}`)\n      })\n\n      return {\n        name: moduleName,\n        version: pkg.version,\n        path: resolvedPackageDir,\n        dependencies: Object.keys(prodDeps).length > 0 ? prodDeps : undefined,\n        optionalDependencies: Object.keys(optionalDeps).length > 0 ? optionalDeps : undefined,\n      }\n    }\n\n    return buildFromPackage(baseDir, aliasName)\n  }\n}\n"]}