"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DenoDatasource = void 0;
const tslib_1 = require("tslib");
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const p_map_1 = tslib_1.__importDefault(require("p-map"));
const logger_1 = require("../../../logger");
const packageCache = tslib_1.__importStar(require("../../../util/cache/package"));
const decorator_1 = require("../../../util/cache/package/decorator");
const regex_1 = require("../../../util/regex");
const url_1 = require("../../../util/url");
const semanticVersioning = tslib_1.__importStar(require("../../versioning/semver"));
const datasource_1 = require("../datasource");
const schema_1 = require("./schema");
class DenoDatasource extends datasource_1.Datasource {
    static id = 'deno';
    customRegistrySupport = true;
    registryStrategy = 'first';
    defaultVersioning = semanticVersioning.id;
    defaultRegistryUrls = ['https://apiland.deno.dev'];
    constructor() {
        super(DenoDatasource.id);
    }
    async getReleases({ packageName, registryUrl, }) {
        const massagedRegistryUrl = registryUrl;
        const extractResult = (0, regex_1.regEx)(/^(https:\/\/deno.land\/)(?<rawPackageName>[^@\s]+)/).exec(packageName);
        const rawPackageName = extractResult?.groups?.rawPackageName;
        if (is_1.default.nullOrUndefined(rawPackageName)) {
            logger_1.logger.debug(`Could not extract rawPackageName from packageName: "${packageName}"`);
            return null;
        }
        // remove third-party prefix if defined. The only internal library is `std` and is available under the same API
        const massagedPackageName = rawPackageName.replace('x/', '');
        // https://apiland.deno.dev/v2/modules/postgres
        const moduleAPIURL = (0, url_1.joinUrlParts)(massagedRegistryUrl, 'v2/modules', massagedPackageName);
        return await this.getReleaseResult(moduleAPIURL);
    }
    async getReleaseResult(moduleAPIURL) {
        const releasesCache = (await packageCache.get(`datasource-${DenoDatasource.id}-details`, moduleAPIURL)) ?? {};
        let cacheModified = false;
        const { body: { versions, tags }, } = await this.http.getJson(moduleAPIURL, schema_1.DenoAPIModuleResponse);
        // get details for the versions
        const releases = await (0, p_map_1.default)(versions, async (version) => {
            const cacheRelease = releasesCache[version];
            // istanbul ignore if
            if (cacheRelease) {
                return cacheRelease;
            }
            // https://apiland.deno.dev/v2/modules/postgres/v0.17.0
            const url = (0, url_1.joinUrlParts)(moduleAPIURL, version);
            const { body: release } = await this.http.getJson(url, schema_1.DenoAPIModuleVersionResponse.catch(({ error: err }) => {
                logger_1.logger.warn({ err }, `Deno: failed to get version details for ${version}`);
                return { version };
            }));
            releasesCache[release.version] = release;
            cacheModified = true;
            return release;
        }, { concurrency: 5 });
        if (cacheModified) {
            // 1 week. Releases at Deno are immutable, therefore we can use a long term cache here.
            await packageCache.set(`datasource-${DenoDatasource.id}-details`, moduleAPIURL, releasesCache, 10080);
        }
        return { releases, tags };
    }
}
exports.DenoDatasource = DenoDatasource;
tslib_1.__decorate([
    (0, decorator_1.cache)({
        namespace: `datasource-${DenoDatasource.id}`,
        key: ({ packageName, registryUrl }) => 
        // TODO: types (#7154)
        `${registryUrl}:${packageName}`,
    })
], DenoDatasource.prototype, "getReleases", null);
tslib_1.__decorate([
    (0, decorator_1.cache)({
        namespace: `datasource-${DenoDatasource.id}-versions`,
        key: (moduleAPIURL) => moduleAPIURL,
    })
], DenoDatasource.prototype, "getReleaseResult", null);
//# sourceMappingURL=index.js.map