Files

116 lines
3.5 KiB
TypeScript

import upath from 'upath';
import { logger } from '../../../logger/index.ts';
import { regEx } from '../../../util/regex.ts';
import { parseUrl } from '../../../util/url.ts';
import type { PackageDependency } from '../types.ts';
import { getOciChartDep } from './oci.ts';
import type { ChartDefinition, Repository } from './types.ts';
export function parseRepository(
depName: string,
repositoryURL: string,
registryAliases?: Record<string, string>,
): PackageDependency {
const res: PackageDependency = {};
const url = parseUrl(repositoryURL);
if (!url) {
logger.debug({ repositoryURL }, 'Error parsing url');
res.skipReason = 'invalid-url';
return res;
}
switch (url.protocol) {
case 'oci:':
return getOciChartDep(repositoryURL, depName, registryAliases);
case 'file:':
res.skipReason = 'local-dependency';
break;
default:
res.registryUrls = [repositoryURL];
}
return res;
}
/**
* Resolves alias in repository string.
*
* @param repository to be resolved string
* @param registryAliases Records containing registryAliases as key and to be resolved URLs as values
*
* @returns resolved alias. If repository does not contain an alias the repository string will be returned. Should it contain an alias which can not be resolved using `registryAliases`, null will be returned
*/
export function resolveAlias(
repository: string,
registryAliases: Record<string, string>,
): string | null {
if (!isAlias(repository)) {
return repository;
}
const repoWithPrefixRemoved = repository.slice(
repository.startsWith('@') ? 1 : 6,
);
const alias = registryAliases[repoWithPrefixRemoved];
if (alias) {
return alias;
}
return null;
}
export function getRepositories(definitions: ChartDefinition[]): Repository[] {
const repositoryList = definitions
.flatMap((value) => value.dependencies)
.filter((dependency) => dependency.repository) // only keep non-local references --> if no repository is defined the chart will be searched in charts/<name>
.filter((dependency) => !isAlias(dependency.repository)) // do not add registryAliases
.filter((dependency) => !dependency.repository.startsWith('file:')) // skip repositories which are locally referenced
.map((dependency) => {
// remove additional keys to prevent interference at deduplication
return {
name: dependency.name,
repository: dependency.repository,
};
});
const dedup = new Set();
return repositoryList.filter((el) => {
const duplicate = dedup.has(el.repository);
dedup.add(el.repository);
return !duplicate;
});
}
/**
* Checks whether a chart reference points at a chart in the repository instead
* of a remote registry.
*
* @param path chart reference to check
*
* @returns `true` if the reference is a relative or absolute local path
*/
export function isLocalChartPath(path: string): boolean {
return ['./', '../', '/'].some((localPrefix) => path.startsWith(localPrefix));
}
export function isAlias(repository: string): boolean {
if (!repository) {
return false;
}
return repository.startsWith('@') || repository.startsWith('alias:');
}
export function aliasRecordToRepositories(
registryAliases: Record<string, string>,
): Repository[] {
return Object.entries(registryAliases)
.filter(([, url]) => regEx(/^(?:https?|oci):\/\/.+/).exec(url))
.map(([alias, url]) => {
return {
name: alias,
repository: url,
};
});
}
export function isFileInDir(dir: string, file: string): boolean {
return upath.dirname(file) === dir;
}