import upath from 'upath'; import { logger } from '../../../logger/index.ts'; import { isNotNullOrUndefined } from '../../../util/array.ts'; import { regEx } from '../../../util/regex.ts'; import { LooseArray } from '../../../util/schema-utils/index.ts'; import { getDep } from '../dockerfile/extract.ts'; import type { ExtractConfig, PackageDependency, PackageFileContent, } from '../types.ts'; import * as bazelrc from './bazelrc.ts'; import { RuleToCratePackageDep } from './parser/crate.ts'; import { parse } from './parser/index.ts'; import { RuleToMavenPackageDep, fillRegistryUrls } from './parser/maven.ts'; import { RuleToDockerPackageDep } from './parser/oci.ts'; import type { ResultFragment } from './parser/types.ts'; import * as rules from './rules.ts'; import { GitRepositoryToPackageDep, RuleToBazelModulePackageDep, } from './rules.ts'; import { transformRulesImgCalls } from './rules-img.ts'; export async function extractPackageFile( content: string, packageFile: string, config?: ExtractConfig, ): Promise { try { const records = parse(content); const pfc = await extractBazelPfc(records, packageFile); const gitRepositoryDeps = extractGitRepositoryDeps(records); const mavenDeps = extractMavenDeps(records); const dockerDeps = LooseArray(RuleToDockerPackageDep) .transform((deps) => deps.map((dep) => { // Reconstruct the image reference from parsed data const imageRef = `${dep.packageName}${dep.currentValue ? `:${dep.currentValue}` : ''}${dep.currentDigest ? `@${dep.currentDigest}` : ''}`; // Use getDep to handle registry aliases properly const processedDep = getDep(imageRef, false, config?.registryAliases); return { ...processedDep, depType: 'oci_pull', depName: dep.depName, // Keep the original name field from bazel replaceString: dep.replaceString, // Keep the original replace string }; }), ) .parse(records); const rulesImgDeps = transformRulesImgCalls(records); const crateDeps = LooseArray(RuleToCratePackageDep).parse(records); if (gitRepositoryDeps.length) { pfc.deps.push(...gitRepositoryDeps); } if (mavenDeps.length) { pfc.deps.push(...mavenDeps); } if (dockerDeps.length) { pfc.deps.push(...dockerDeps); } if (rulesImgDeps.length) { pfc.deps.push(...rulesImgDeps); } if (crateDeps.length) { pfc.deps.push(...crateDeps); } return pfc.deps.length ? pfc : null; } catch (err) { logger.debug({ err, packageFile }, 'Failed to parse bazel module file.'); return null; } } async function extractBazelPfc( records: ResultFragment[], packageFile: string, ): Promise { const pfc: PackageFileContent = LooseArray(RuleToBazelModulePackageDep) .transform(rules.toPackageDependencies) .transform((deps) => ({ deps })) .parse(records); const registryUrls = (await bazelrc.read(upath.dirname(packageFile))) // Ignore any entries for custom configurations .filter((ce) => ce.config === undefined) .map((ce) => ce.getOption('registry')?.value) .map((url) => url?.replace(regEx(/^["']|["']$/g), '')) .filter(isNotNullOrUndefined); if (registryUrls.length) { pfc.registryUrls = registryUrls; } return pfc; } function extractGitRepositoryDeps( records: ResultFragment[], ): PackageDependency[] { return LooseArray(GitRepositoryToPackageDep).parse(records); } function extractMavenDeps(records: ResultFragment[]): PackageDependency[] { return LooseArray(RuleToMavenPackageDep) .transform(fillRegistryUrls) .parse(records); }