"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RubyGemsDatasource = void 0;
const tslib_1 = require("tslib");
const marshal_1 = require("@qnighy/marshal");
const logger_1 = require("../../../logger");
const decorator_1 = require("../../../util/cache/package/decorator");
const http_1 = require("../../../util/http");
const result_1 = require("../../../util/result");
const url_1 = require("../../../util/url");
const rubyVersioning = tslib_1.__importStar(require("../../versioning/ruby"));
const datasource_1 = require("../datasource");
const common_1 = require("./common");
const http_2 = require("./http");
const metadata_cache_1 = require("./metadata-cache");
const schema_1 = require("./schema");
const versions_endpoint_cache_1 = require("./versions-endpoint-cache");
function unlessServerSide(err, cb) {
    if (err instanceof http_1.HttpError && err.response?.statusCode) {
        const code = err.response.statusCode;
        if (code >= 500 && code <= 599) {
            return result_1.AsyncResult.err(err);
        }
    }
    return cb();
}
class RubyGemsDatasource extends datasource_1.Datasource {
    static id = 'rubygems';
    metadataCache;
    constructor() {
        super(RubyGemsDatasource.id);
        this.http = new http_2.RubygemsHttp(RubyGemsDatasource.id);
        this.versionsEndpointCache = new versions_endpoint_cache_1.VersionsEndpointCache(this.http);
        this.metadataCache = new metadata_cache_1.MetadataCache(this.http);
    }
    defaultRegistryUrls = ['https://rubygems.org'];
    defaultVersioning = rubyVersioning.id;
    registryStrategy = 'hunt';
    versionsEndpointCache;
    async getReleases({ packageName, registryUrl, }) {
        // istanbul ignore if
        if (!registryUrl) {
            return null;
        }
        const registryHostname = (0, url_1.parseUrl)(registryUrl)?.hostname;
        let result;
        if (registryHostname === 'rubygems.org') {
            result = result_1.Result.wrap(this.versionsEndpointCache.getVersions(registryUrl, packageName)).transform((versions) => this.metadataCache.getRelease(registryUrl, packageName, versions));
        }
        else if (registryHostname === 'rubygems.pkg.github.com' ||
            registryHostname === 'gitlab.com') {
            result = this.getReleasesViaDeprecatedAPI(registryUrl, packageName);
        }
        else {
            result = (0, common_1.getV1Releases)(this.http, registryUrl, packageName)
                .catch((err) => unlessServerSide(err, () => this.getReleasesViaInfoEndpoint(registryUrl, packageName)))
                .catch((err) => unlessServerSide(err, () => this.getReleasesViaDeprecatedAPI(registryUrl, packageName)));
        }
        const { val, err } = await result.unwrap();
        if (val) {
            return val;
        }
        if (err instanceof Error) {
            this.handleGenericErrors(err);
        }
        logger_1.logger.debug({ packageName, registryUrl }, `Rubygems fetch error: ${err}`);
        return null;
    }
    getReleasesViaInfoEndpoint(registryUrl, packageName) {
        const url = (0, url_1.joinUrlParts)(registryUrl, '/info', packageName);
        return result_1.Result.wrap(this.http.get(url))
            .transform(({ body }) => body)
            .parse(schema_1.GemInfo);
    }
    getReleasesViaDeprecatedAPI(registryUrl, packageName) {
        const path = (0, url_1.joinUrlParts)(registryUrl, `/api/v1/dependencies`);
        const query = (0, url_1.getQueryString)({ gems: packageName });
        const url = `${path}?${query}`;
        const bufPromise = this.http.getBuffer(url);
        return result_1.Result.wrap(bufPromise).transform(({ body }) => schema_1.MarshalledVersionInfo.safeParse(marshal_1.Marshal.parse(body)));
    }
}
exports.RubyGemsDatasource = RubyGemsDatasource;
tslib_1.__decorate([
    (0, decorator_1.cache)({
        namespace: `datasource-${RubyGemsDatasource.id}`,
        key: ({ packageName, registryUrl }) => 
        // TODO: types (#22198)
        `releases:${registryUrl}:${packageName}`,
        cacheable: ({ registryUrl }) => {
            const registryHostname = (0, url_1.parseUrl)(registryUrl)?.hostname;
            return registryHostname === 'rubygems.org';
        },
    })
], RubyGemsDatasource.prototype, "getReleases", null);
//# sourceMappingURL=index.js.map