import { logger } from '../../logger' ; import { cache } from '../../util/cache/package/decorator' ; import { parse } from '../../util/html' ; import { HttpError } from '../../util/http/types' ; import { regEx } from '../../util/regex' ; import { joinUrlParts } from '../../util/url' ; import { Datasource } from '../datasource' ; import type { GetReleasesConfig , Release , ReleaseResult } from '../types' ; import { datasource } from './common' ; export class ArtifactoryDatasource extends Datasource { static readonly id = datasource ; constructor ( ) { super ( datasource ) ; } override readonly customRegistrySupport = true ; override readonly caching = true ; override readonly registryStrategy = 'merge' ; @ cache ( { namespace : `datasource-${ datasource }` , key : ( { registryUrl , lookupName } ) => `${ registryUrl }:${ lookupName }` , } ) async getReleases ( { lookupName , registryUrl , } ) { if ( ! registryUrl ) { logger . warn ( { lookupName } , 'artifactory datasource requires custom registryUrl. Skipping datasource' ) ; return null ; } const url = joinUrlParts ( registryUrl , lookupName ) ; const result = { releases : [ ] , } ; try { const response = await this . http . get ( url ) ; const body = parse ( response . body , { blockTextElements : { script : true , noscript : true , style : true , } , } ) ; const nodes = body . querySelectorAll ( 'a' ) ; nodes . filter ( ( node ) => node . innerHTML !== '../' && node . innerHTML !== '..' ) . forEach ( ( node ) => { const version = node . innerHTML . slice ( - 1 ) === '/' ? node . innerHTML . slice ( 0 , - 1 ) : node . innerHTML ; const published = ArtifactoryDatasource . parseReleaseTimestamp ( node . nextSibling ?. text ) ; const thisRelease = { version , releaseTimestamp : published , } ; result . releases . push ( thisRelease ) ; } ) ; if ( result . releases . length ) { logger . trace ( { registryUrl , lookupName , versions : result . releases . length } , 'artifactory: Found versions' ) ; } else { logger . trace ( { registryUrl , lookupName } , 'artifactory: No versions found' ) ; } } catch ( err ) { if ( err instanceof HttpError ) { if ( err . response ?. statusCode === 404 ) { logger . warn ( { registryUrl , lookupName } , 'artifactory: `Not Found` error' ) ; return null ; } } this . handleGenericErrors ( err ) ; } return result . releases . length ? result : null ; } private static parseReleaseTimestamp ( rawText ) { return rawText . trim ( ) . replace ( regEx ( / ?-$/ ) , '' ) + 'Z' ; } }