import { isNonEmptyString } from '@sindresorhus/is'; import * as hostRules from '../../../util/host-rules.ts'; import { regEx } from '../../../util/regex.ts'; import { parseRegistryUrl } from '../../datasource/nuget/common.ts'; import { NugetDatasource } from '../../datasource/nuget/index.ts'; import type { ParsedRegistryUrl } from '../../datasource/nuget/types.ts'; import type { PackageSourceCredential, PackageSourceMap, Registry, } from './types.ts'; export function createNuGetConfigXml(registries: Registry[]): string { let contents = `\n\n\n`; let unnamedRegistryCount = 0; const credentials: PackageSourceCredential[] = []; const packageSourceMaps: PackageSourceMap[] = []; const seenUrls = new Set(); for (const registry of registries) { // Skip if we've already seen this URL if (seenUrls.has(registry.url)) { continue; } seenUrls.add(registry.url); const registryName = registry.name ?? `Package source ${++unnamedRegistryCount}`; const registryInfo = parseRegistryUrl(registry.url); contents += formatPackageSourceElement(registryInfo, registryName); const { password, username } = hostRules.find({ hostType: NugetDatasource.id, url: registry.url, }); if (isNonEmptyString(password) || isNonEmptyString(username)) { credentials.push({ name: registryName, password, username, }); } if (registry.sourceMappedPackagePatterns) { packageSourceMaps.push({ name: registryName, patterns: registry.sourceMappedPackagePatterns, }); } } contents += '\n'; if (credentials.length > 0) { contents += '\n'; for (const credential of credentials) { contents += formatPackageSourceCredentialElement(credential); } contents += '\n'; } if (packageSourceMaps.length > 0) { contents += '\n'; for (const packageSourceMap of packageSourceMaps) { contents += formatPackageSource(packageSourceMap); } contents += ''; } contents += '\n'; return contents; } function formatPackageSourceElement( registryInfo: ParsedRegistryUrl, name: string, ): string { let element = `\n`; } function formatPackageSourceCredentialElement( credential: PackageSourceCredential, ): string { const escapedName = escapeName(credential.name); let packageSourceCredential = `<${escapedName}>\n`; if (credential.username) { packageSourceCredential += `\n`; } if (credential.password) { packageSourceCredential += `\n`; } packageSourceCredential += ``; packageSourceCredential += `\n`; return packageSourceCredential; } function formatPackageSource(packageSourceMap: PackageSourceMap): string { let packageSource = `\n`; for (const pattern of packageSourceMap.patterns) { packageSource += `\n`; } return `${packageSource}\n`; } const charactersToEscape = regEx(/[^A-Za-z0-9\-_.]/); function escapeName(name: string): string { let escapedName = ''; for (const char of name) { if (char.match(charactersToEscape)) { escapedName += `_x${char.codePointAt(0)!.toString(16).padStart(4, '0')}_`; } else { escapedName += char; } } return escapedName; }