11cb0ef41Sopenharmony_ci"use strict";
21cb0ef41Sopenharmony_civar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
31cb0ef41Sopenharmony_ci    if (k2 === undefined) k2 = k;
41cb0ef41Sopenharmony_ci    var desc = Object.getOwnPropertyDescriptor(m, k);
51cb0ef41Sopenharmony_ci    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
61cb0ef41Sopenharmony_ci      desc = { enumerable: true, get: function() { return m[k]; } };
71cb0ef41Sopenharmony_ci    }
81cb0ef41Sopenharmony_ci    Object.defineProperty(o, k2, desc);
91cb0ef41Sopenharmony_ci}) : (function(o, m, k, k2) {
101cb0ef41Sopenharmony_ci    if (k2 === undefined) k2 = k;
111cb0ef41Sopenharmony_ci    o[k2] = m[k];
121cb0ef41Sopenharmony_ci}));
131cb0ef41Sopenharmony_civar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
141cb0ef41Sopenharmony_ci    Object.defineProperty(o, "default", { enumerable: true, value: v });
151cb0ef41Sopenharmony_ci}) : function(o, v) {
161cb0ef41Sopenharmony_ci    o["default"] = v;
171cb0ef41Sopenharmony_ci});
181cb0ef41Sopenharmony_civar __importStar = (this && this.__importStar) || function (mod) {
191cb0ef41Sopenharmony_ci    if (mod && mod.__esModule) return mod;
201cb0ef41Sopenharmony_ci    var result = {};
211cb0ef41Sopenharmony_ci    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
221cb0ef41Sopenharmony_ci    __setModuleDefault(result, mod);
231cb0ef41Sopenharmony_ci    return result;
241cb0ef41Sopenharmony_ci};
251cb0ef41Sopenharmony_civar __importDefault = (this && this.__importDefault) || function (mod) {
261cb0ef41Sopenharmony_ci    return (mod && mod.__esModule) ? mod : { "default": mod };
271cb0ef41Sopenharmony_ci};
281cb0ef41Sopenharmony_ciObject.defineProperty(exports, "__esModule", { value: true });
291cb0ef41Sopenharmony_ciexports.Updater = void 0;
301cb0ef41Sopenharmony_ciconst models_1 = require("@tufjs/models");
311cb0ef41Sopenharmony_ciconst debug_1 = __importDefault(require("debug"));
321cb0ef41Sopenharmony_ciconst fs = __importStar(require("fs"));
331cb0ef41Sopenharmony_ciconst path = __importStar(require("path"));
341cb0ef41Sopenharmony_ciconst config_1 = require("./config");
351cb0ef41Sopenharmony_ciconst error_1 = require("./error");
361cb0ef41Sopenharmony_ciconst fetcher_1 = require("./fetcher");
371cb0ef41Sopenharmony_ciconst store_1 = require("./store");
381cb0ef41Sopenharmony_ciconst url = __importStar(require("./utils/url"));
391cb0ef41Sopenharmony_ciconst log = (0, debug_1.default)('tuf:cache');
401cb0ef41Sopenharmony_ciclass Updater {
411cb0ef41Sopenharmony_ci    constructor(options) {
421cb0ef41Sopenharmony_ci        const { metadataDir, metadataBaseUrl, targetDir, targetBaseUrl, fetcher, config, } = options;
431cb0ef41Sopenharmony_ci        this.dir = metadataDir;
441cb0ef41Sopenharmony_ci        this.metadataBaseUrl = metadataBaseUrl;
451cb0ef41Sopenharmony_ci        this.targetDir = targetDir;
461cb0ef41Sopenharmony_ci        this.targetBaseUrl = targetBaseUrl;
471cb0ef41Sopenharmony_ci        this.forceCache = options.forceCache ?? false;
481cb0ef41Sopenharmony_ci        const data = this.loadLocalMetadata(models_1.MetadataKind.Root);
491cb0ef41Sopenharmony_ci        this.trustedSet = new store_1.TrustedMetadataStore(data);
501cb0ef41Sopenharmony_ci        this.config = { ...config_1.defaultConfig, ...config };
511cb0ef41Sopenharmony_ci        this.fetcher =
521cb0ef41Sopenharmony_ci            fetcher ||
531cb0ef41Sopenharmony_ci                new fetcher_1.DefaultFetcher({
541cb0ef41Sopenharmony_ci                    timeout: this.config.fetchTimeout,
551cb0ef41Sopenharmony_ci                    retry: this.config.fetchRetries ?? this.config.fetchRetry,
561cb0ef41Sopenharmony_ci                });
571cb0ef41Sopenharmony_ci    }
581cb0ef41Sopenharmony_ci    // refresh and load the metadata before downloading the target
591cb0ef41Sopenharmony_ci    // refresh should be called once after the client is initialized
601cb0ef41Sopenharmony_ci    async refresh() {
611cb0ef41Sopenharmony_ci        // If forceCache is true, try to load the timestamp from local storage
621cb0ef41Sopenharmony_ci        // without fetching it from the remote. Otherwise, load the root and
631cb0ef41Sopenharmony_ci        // timestamp from the remote per the TUF spec.
641cb0ef41Sopenharmony_ci        if (this.forceCache) {
651cb0ef41Sopenharmony_ci            // If anything fails, load the root and timestamp from the remote. This
661cb0ef41Sopenharmony_ci            // should cover any situation where the local metadata is corrupted or
671cb0ef41Sopenharmony_ci            // expired.
681cb0ef41Sopenharmony_ci            try {
691cb0ef41Sopenharmony_ci                await this.loadTimestamp({ checkRemote: false });
701cb0ef41Sopenharmony_ci            }
711cb0ef41Sopenharmony_ci            catch (error) {
721cb0ef41Sopenharmony_ci                await this.loadRoot();
731cb0ef41Sopenharmony_ci                await this.loadTimestamp();
741cb0ef41Sopenharmony_ci            }
751cb0ef41Sopenharmony_ci        }
761cb0ef41Sopenharmony_ci        else {
771cb0ef41Sopenharmony_ci            await this.loadRoot();
781cb0ef41Sopenharmony_ci            await this.loadTimestamp();
791cb0ef41Sopenharmony_ci        }
801cb0ef41Sopenharmony_ci        await this.loadSnapshot();
811cb0ef41Sopenharmony_ci        await this.loadTargets(models_1.MetadataKind.Targets, models_1.MetadataKind.Root);
821cb0ef41Sopenharmony_ci    }
831cb0ef41Sopenharmony_ci    // Returns the TargetFile instance with information for the given target path.
841cb0ef41Sopenharmony_ci    //
851cb0ef41Sopenharmony_ci    // Implicitly calls refresh if it hasn't already been called.
861cb0ef41Sopenharmony_ci    async getTargetInfo(targetPath) {
871cb0ef41Sopenharmony_ci        if (!this.trustedSet.targets) {
881cb0ef41Sopenharmony_ci            await this.refresh();
891cb0ef41Sopenharmony_ci        }
901cb0ef41Sopenharmony_ci        return this.preorderDepthFirstWalk(targetPath);
911cb0ef41Sopenharmony_ci    }
921cb0ef41Sopenharmony_ci    async downloadTarget(targetInfo, filePath, targetBaseUrl) {
931cb0ef41Sopenharmony_ci        const targetPath = filePath || this.generateTargetPath(targetInfo);
941cb0ef41Sopenharmony_ci        if (!targetBaseUrl) {
951cb0ef41Sopenharmony_ci            if (!this.targetBaseUrl) {
961cb0ef41Sopenharmony_ci                throw new error_1.ValueError('Target base URL not set');
971cb0ef41Sopenharmony_ci            }
981cb0ef41Sopenharmony_ci            targetBaseUrl = this.targetBaseUrl;
991cb0ef41Sopenharmony_ci        }
1001cb0ef41Sopenharmony_ci        let targetFilePath = targetInfo.path;
1011cb0ef41Sopenharmony_ci        const consistentSnapshot = this.trustedSet.root.signed.consistentSnapshot;
1021cb0ef41Sopenharmony_ci        if (consistentSnapshot && this.config.prefixTargetsWithHash) {
1031cb0ef41Sopenharmony_ci            const hashes = Object.values(targetInfo.hashes);
1041cb0ef41Sopenharmony_ci            const { dir, base } = path.parse(targetFilePath);
1051cb0ef41Sopenharmony_ci            const filename = `${hashes[0]}.${base}`;
1061cb0ef41Sopenharmony_ci            targetFilePath = dir ? `${dir}/${filename}` : filename;
1071cb0ef41Sopenharmony_ci        }
1081cb0ef41Sopenharmony_ci        const targetUrl = url.join(targetBaseUrl, targetFilePath);
1091cb0ef41Sopenharmony_ci        // Client workflow 5.7.3: download target file
1101cb0ef41Sopenharmony_ci        await this.fetcher.downloadFile(targetUrl, targetInfo.length, async (fileName) => {
1111cb0ef41Sopenharmony_ci            // Verify hashes and length of downloaded file
1121cb0ef41Sopenharmony_ci            await targetInfo.verify(fs.createReadStream(fileName));
1131cb0ef41Sopenharmony_ci            // Copy file to target path
1141cb0ef41Sopenharmony_ci            log('WRITE %s', targetPath);
1151cb0ef41Sopenharmony_ci            fs.copyFileSync(fileName, targetPath);
1161cb0ef41Sopenharmony_ci        });
1171cb0ef41Sopenharmony_ci        return targetPath;
1181cb0ef41Sopenharmony_ci    }
1191cb0ef41Sopenharmony_ci    async findCachedTarget(targetInfo, filePath) {
1201cb0ef41Sopenharmony_ci        if (!filePath) {
1211cb0ef41Sopenharmony_ci            filePath = this.generateTargetPath(targetInfo);
1221cb0ef41Sopenharmony_ci        }
1231cb0ef41Sopenharmony_ci        try {
1241cb0ef41Sopenharmony_ci            if (fs.existsSync(filePath)) {
1251cb0ef41Sopenharmony_ci                await targetInfo.verify(fs.createReadStream(filePath));
1261cb0ef41Sopenharmony_ci                return filePath;
1271cb0ef41Sopenharmony_ci            }
1281cb0ef41Sopenharmony_ci        }
1291cb0ef41Sopenharmony_ci        catch (error) {
1301cb0ef41Sopenharmony_ci            return; // File not found
1311cb0ef41Sopenharmony_ci        }
1321cb0ef41Sopenharmony_ci        return; // File not found
1331cb0ef41Sopenharmony_ci    }
1341cb0ef41Sopenharmony_ci    loadLocalMetadata(fileName) {
1351cb0ef41Sopenharmony_ci        const filePath = path.join(this.dir, `${fileName}.json`);
1361cb0ef41Sopenharmony_ci        log('READ %s', filePath);
1371cb0ef41Sopenharmony_ci        return fs.readFileSync(filePath);
1381cb0ef41Sopenharmony_ci    }
1391cb0ef41Sopenharmony_ci    // Sequentially load and persist on local disk every newer root metadata
1401cb0ef41Sopenharmony_ci    // version available on the remote.
1411cb0ef41Sopenharmony_ci    // Client workflow 5.3: update root role
1421cb0ef41Sopenharmony_ci    async loadRoot() {
1431cb0ef41Sopenharmony_ci        // Client workflow 5.3.2: version of trusted root metadata file
1441cb0ef41Sopenharmony_ci        const rootVersion = this.trustedSet.root.signed.version;
1451cb0ef41Sopenharmony_ci        const lowerBound = rootVersion + 1;
1461cb0ef41Sopenharmony_ci        const upperBound = lowerBound + this.config.maxRootRotations;
1471cb0ef41Sopenharmony_ci        for (let version = lowerBound; version <= upperBound; version++) {
1481cb0ef41Sopenharmony_ci            const rootUrl = url.join(this.metadataBaseUrl, `${version}.root.json`);
1491cb0ef41Sopenharmony_ci            try {
1501cb0ef41Sopenharmony_ci                // Client workflow 5.3.3: download new root metadata file
1511cb0ef41Sopenharmony_ci                const bytesData = await this.fetcher.downloadBytes(rootUrl, this.config.rootMaxLength);
1521cb0ef41Sopenharmony_ci                // Client workflow 5.3.4 - 5.4.7
1531cb0ef41Sopenharmony_ci                this.trustedSet.updateRoot(bytesData);
1541cb0ef41Sopenharmony_ci                // Client workflow 5.3.8: persist root metadata file
1551cb0ef41Sopenharmony_ci                this.persistMetadata(models_1.MetadataKind.Root, bytesData);
1561cb0ef41Sopenharmony_ci            }
1571cb0ef41Sopenharmony_ci            catch (error) {
1581cb0ef41Sopenharmony_ci                break;
1591cb0ef41Sopenharmony_ci            }
1601cb0ef41Sopenharmony_ci        }
1611cb0ef41Sopenharmony_ci    }
1621cb0ef41Sopenharmony_ci    // Load local and remote timestamp metadata.
1631cb0ef41Sopenharmony_ci    // Client workflow 5.4: update timestamp role
1641cb0ef41Sopenharmony_ci    async loadTimestamp({ checkRemote } = { checkRemote: true }) {
1651cb0ef41Sopenharmony_ci        // Load local and remote timestamp metadata
1661cb0ef41Sopenharmony_ci        try {
1671cb0ef41Sopenharmony_ci            const data = this.loadLocalMetadata(models_1.MetadataKind.Timestamp);
1681cb0ef41Sopenharmony_ci            this.trustedSet.updateTimestamp(data);
1691cb0ef41Sopenharmony_ci            // If checkRemote is disabled, return here to avoid fetching the remote
1701cb0ef41Sopenharmony_ci            // timestamp metadata.
1711cb0ef41Sopenharmony_ci            if (!checkRemote) {
1721cb0ef41Sopenharmony_ci                return;
1731cb0ef41Sopenharmony_ci            }
1741cb0ef41Sopenharmony_ci        }
1751cb0ef41Sopenharmony_ci        catch (error) {
1761cb0ef41Sopenharmony_ci            // continue
1771cb0ef41Sopenharmony_ci        }
1781cb0ef41Sopenharmony_ci        //Load from remote (whether local load succeeded or not)
1791cb0ef41Sopenharmony_ci        const timestampUrl = url.join(this.metadataBaseUrl, 'timestamp.json');
1801cb0ef41Sopenharmony_ci        // Client workflow 5.4.1: download timestamp metadata file
1811cb0ef41Sopenharmony_ci        const bytesData = await this.fetcher.downloadBytes(timestampUrl, this.config.timestampMaxLength);
1821cb0ef41Sopenharmony_ci        try {
1831cb0ef41Sopenharmony_ci            // Client workflow 5.4.2 - 5.4.4
1841cb0ef41Sopenharmony_ci            this.trustedSet.updateTimestamp(bytesData);
1851cb0ef41Sopenharmony_ci        }
1861cb0ef41Sopenharmony_ci        catch (error) {
1871cb0ef41Sopenharmony_ci            // If new timestamp version is same as current, discardd the new one.
1881cb0ef41Sopenharmony_ci            // This is normal and should NOT raise an error.
1891cb0ef41Sopenharmony_ci            if (error instanceof error_1.EqualVersionError) {
1901cb0ef41Sopenharmony_ci                return;
1911cb0ef41Sopenharmony_ci            }
1921cb0ef41Sopenharmony_ci            // Re-raise any other error
1931cb0ef41Sopenharmony_ci            throw error;
1941cb0ef41Sopenharmony_ci        }
1951cb0ef41Sopenharmony_ci        // Client workflow 5.4.5: persist timestamp metadata
1961cb0ef41Sopenharmony_ci        this.persistMetadata(models_1.MetadataKind.Timestamp, bytesData);
1971cb0ef41Sopenharmony_ci    }
1981cb0ef41Sopenharmony_ci    // Load local and remote snapshot metadata.
1991cb0ef41Sopenharmony_ci    // Client workflow 5.5: update snapshot role
2001cb0ef41Sopenharmony_ci    async loadSnapshot() {
2011cb0ef41Sopenharmony_ci        //Load local (and if needed remote) snapshot metadata
2021cb0ef41Sopenharmony_ci        try {
2031cb0ef41Sopenharmony_ci            const data = this.loadLocalMetadata(models_1.MetadataKind.Snapshot);
2041cb0ef41Sopenharmony_ci            this.trustedSet.updateSnapshot(data, true);
2051cb0ef41Sopenharmony_ci        }
2061cb0ef41Sopenharmony_ci        catch (error) {
2071cb0ef41Sopenharmony_ci            if (!this.trustedSet.timestamp) {
2081cb0ef41Sopenharmony_ci                throw new ReferenceError('No timestamp metadata');
2091cb0ef41Sopenharmony_ci            }
2101cb0ef41Sopenharmony_ci            const snapshotMeta = this.trustedSet.timestamp.signed.snapshotMeta;
2111cb0ef41Sopenharmony_ci            const maxLength = snapshotMeta.length || this.config.snapshotMaxLength;
2121cb0ef41Sopenharmony_ci            const version = this.trustedSet.root.signed.consistentSnapshot
2131cb0ef41Sopenharmony_ci                ? snapshotMeta.version
2141cb0ef41Sopenharmony_ci                : undefined;
2151cb0ef41Sopenharmony_ci            const snapshotUrl = url.join(this.metadataBaseUrl, version ? `${version}.snapshot.json` : 'snapshot.json');
2161cb0ef41Sopenharmony_ci            try {
2171cb0ef41Sopenharmony_ci                // Client workflow 5.5.1: download snapshot metadata file
2181cb0ef41Sopenharmony_ci                const bytesData = await this.fetcher.downloadBytes(snapshotUrl, maxLength);
2191cb0ef41Sopenharmony_ci                // Client workflow 5.5.2 - 5.5.6
2201cb0ef41Sopenharmony_ci                this.trustedSet.updateSnapshot(bytesData);
2211cb0ef41Sopenharmony_ci                // Client workflow 5.5.7: persist snapshot metadata file
2221cb0ef41Sopenharmony_ci                this.persistMetadata(models_1.MetadataKind.Snapshot, bytesData);
2231cb0ef41Sopenharmony_ci            }
2241cb0ef41Sopenharmony_ci            catch (error) {
2251cb0ef41Sopenharmony_ci                throw new error_1.RuntimeError(`Unable to load snapshot metadata error ${error}`);
2261cb0ef41Sopenharmony_ci            }
2271cb0ef41Sopenharmony_ci        }
2281cb0ef41Sopenharmony_ci    }
2291cb0ef41Sopenharmony_ci    // Load local and remote targets metadata.
2301cb0ef41Sopenharmony_ci    // Client workflow 5.6: update targets role
2311cb0ef41Sopenharmony_ci    async loadTargets(role, parentRole) {
2321cb0ef41Sopenharmony_ci        if (this.trustedSet.getRole(role)) {
2331cb0ef41Sopenharmony_ci            return this.trustedSet.getRole(role);
2341cb0ef41Sopenharmony_ci        }
2351cb0ef41Sopenharmony_ci        try {
2361cb0ef41Sopenharmony_ci            const buffer = this.loadLocalMetadata(role);
2371cb0ef41Sopenharmony_ci            this.trustedSet.updateDelegatedTargets(buffer, role, parentRole);
2381cb0ef41Sopenharmony_ci        }
2391cb0ef41Sopenharmony_ci        catch (error) {
2401cb0ef41Sopenharmony_ci            // Local 'role' does not exist or is invalid: update from remote
2411cb0ef41Sopenharmony_ci            if (!this.trustedSet.snapshot) {
2421cb0ef41Sopenharmony_ci                throw new ReferenceError('No snapshot metadata');
2431cb0ef41Sopenharmony_ci            }
2441cb0ef41Sopenharmony_ci            const metaInfo = this.trustedSet.snapshot.signed.meta[`${role}.json`];
2451cb0ef41Sopenharmony_ci            // TODO: use length for fetching
2461cb0ef41Sopenharmony_ci            const maxLength = metaInfo.length || this.config.targetsMaxLength;
2471cb0ef41Sopenharmony_ci            const version = this.trustedSet.root.signed.consistentSnapshot
2481cb0ef41Sopenharmony_ci                ? metaInfo.version
2491cb0ef41Sopenharmony_ci                : undefined;
2501cb0ef41Sopenharmony_ci            const metadataUrl = url.join(this.metadataBaseUrl, version ? `${version}.${role}.json` : `${role}.json`);
2511cb0ef41Sopenharmony_ci            try {
2521cb0ef41Sopenharmony_ci                // Client workflow 5.6.1: download targets metadata file
2531cb0ef41Sopenharmony_ci                const bytesData = await this.fetcher.downloadBytes(metadataUrl, maxLength);
2541cb0ef41Sopenharmony_ci                // Client workflow 5.6.2 - 5.6.6
2551cb0ef41Sopenharmony_ci                this.trustedSet.updateDelegatedTargets(bytesData, role, parentRole);
2561cb0ef41Sopenharmony_ci                // Client workflow 5.6.7: persist targets metadata file
2571cb0ef41Sopenharmony_ci                this.persistMetadata(role, bytesData);
2581cb0ef41Sopenharmony_ci            }
2591cb0ef41Sopenharmony_ci            catch (error) {
2601cb0ef41Sopenharmony_ci                throw new error_1.RuntimeError(`Unable to load targets error ${error}`);
2611cb0ef41Sopenharmony_ci            }
2621cb0ef41Sopenharmony_ci        }
2631cb0ef41Sopenharmony_ci        return this.trustedSet.getRole(role);
2641cb0ef41Sopenharmony_ci    }
2651cb0ef41Sopenharmony_ci    async preorderDepthFirstWalk(targetPath) {
2661cb0ef41Sopenharmony_ci        // Interrogates the tree of target delegations in order of appearance
2671cb0ef41Sopenharmony_ci        // (which implicitly order trustworthiness), and returns the matching
2681cb0ef41Sopenharmony_ci        // target found in the most trusted role.
2691cb0ef41Sopenharmony_ci        // List of delegations to be interrogated. A (role, parent role) pair
2701cb0ef41Sopenharmony_ci        // is needed to load and verify the delegated targets metadata.
2711cb0ef41Sopenharmony_ci        const delegationsToVisit = [
2721cb0ef41Sopenharmony_ci            {
2731cb0ef41Sopenharmony_ci                roleName: models_1.MetadataKind.Targets,
2741cb0ef41Sopenharmony_ci                parentRoleName: models_1.MetadataKind.Root,
2751cb0ef41Sopenharmony_ci            },
2761cb0ef41Sopenharmony_ci        ];
2771cb0ef41Sopenharmony_ci        const visitedRoleNames = new Set();
2781cb0ef41Sopenharmony_ci        // Client workflow 5.6.7: preorder depth-first traversal of the graph of
2791cb0ef41Sopenharmony_ci        // target delegations
2801cb0ef41Sopenharmony_ci        while (visitedRoleNames.size <= this.config.maxDelegations &&
2811cb0ef41Sopenharmony_ci            delegationsToVisit.length > 0) {
2821cb0ef41Sopenharmony_ci            //  Pop the role name from the top of the stack.
2831cb0ef41Sopenharmony_ci            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
2841cb0ef41Sopenharmony_ci            const { roleName, parentRoleName } = delegationsToVisit.pop();
2851cb0ef41Sopenharmony_ci            // Skip any visited current role to prevent cycles.
2861cb0ef41Sopenharmony_ci            // Client workflow 5.6.7.1: skip already-visited roles
2871cb0ef41Sopenharmony_ci            if (visitedRoleNames.has(roleName)) {
2881cb0ef41Sopenharmony_ci                continue;
2891cb0ef41Sopenharmony_ci            }
2901cb0ef41Sopenharmony_ci            // The metadata for 'role_name' must be downloaded/updated before
2911cb0ef41Sopenharmony_ci            // its targets, delegations, and child roles can be inspected.
2921cb0ef41Sopenharmony_ci            const targets = (await this.loadTargets(roleName, parentRoleName))
2931cb0ef41Sopenharmony_ci                ?.signed;
2941cb0ef41Sopenharmony_ci            if (!targets) {
2951cb0ef41Sopenharmony_ci                continue;
2961cb0ef41Sopenharmony_ci            }
2971cb0ef41Sopenharmony_ci            const target = targets.targets?.[targetPath];
2981cb0ef41Sopenharmony_ci            if (target) {
2991cb0ef41Sopenharmony_ci                return target;
3001cb0ef41Sopenharmony_ci            }
3011cb0ef41Sopenharmony_ci            // After preorder check, add current role to set of visited roles.
3021cb0ef41Sopenharmony_ci            visitedRoleNames.add(roleName);
3031cb0ef41Sopenharmony_ci            if (targets.delegations) {
3041cb0ef41Sopenharmony_ci                const childRolesToVisit = [];
3051cb0ef41Sopenharmony_ci                // NOTE: This may be a slow operation if there are many delegated roles.
3061cb0ef41Sopenharmony_ci                const rolesForTarget = targets.delegations.rolesForTarget(targetPath);
3071cb0ef41Sopenharmony_ci                for (const { role: childName, terminating } of rolesForTarget) {
3081cb0ef41Sopenharmony_ci                    childRolesToVisit.push({
3091cb0ef41Sopenharmony_ci                        roleName: childName,
3101cb0ef41Sopenharmony_ci                        parentRoleName: roleName,
3111cb0ef41Sopenharmony_ci                    });
3121cb0ef41Sopenharmony_ci                    // Client workflow 5.6.7.2.1
3131cb0ef41Sopenharmony_ci                    if (terminating) {
3141cb0ef41Sopenharmony_ci                        delegationsToVisit.splice(0); // empty the array
3151cb0ef41Sopenharmony_ci                        break;
3161cb0ef41Sopenharmony_ci                    }
3171cb0ef41Sopenharmony_ci                }
3181cb0ef41Sopenharmony_ci                childRolesToVisit.reverse();
3191cb0ef41Sopenharmony_ci                delegationsToVisit.push(...childRolesToVisit);
3201cb0ef41Sopenharmony_ci            }
3211cb0ef41Sopenharmony_ci        }
3221cb0ef41Sopenharmony_ci        return; // no matching target found
3231cb0ef41Sopenharmony_ci    }
3241cb0ef41Sopenharmony_ci    generateTargetPath(targetInfo) {
3251cb0ef41Sopenharmony_ci        if (!this.targetDir) {
3261cb0ef41Sopenharmony_ci            throw new error_1.ValueError('Target directory not set');
3271cb0ef41Sopenharmony_ci        }
3281cb0ef41Sopenharmony_ci        // URL encode target path
3291cb0ef41Sopenharmony_ci        const filePath = encodeURIComponent(targetInfo.path);
3301cb0ef41Sopenharmony_ci        return path.join(this.targetDir, filePath);
3311cb0ef41Sopenharmony_ci    }
3321cb0ef41Sopenharmony_ci    persistMetadata(metaDataName, bytesData) {
3331cb0ef41Sopenharmony_ci        try {
3341cb0ef41Sopenharmony_ci            const filePath = path.join(this.dir, `${metaDataName}.json`);
3351cb0ef41Sopenharmony_ci            log('WRITE %s', filePath);
3361cb0ef41Sopenharmony_ci            fs.writeFileSync(filePath, bytesData.toString('utf8'));
3371cb0ef41Sopenharmony_ci        }
3381cb0ef41Sopenharmony_ci        catch (error) {
3391cb0ef41Sopenharmony_ci            throw new error_1.PersistError(`Failed to persist metadata ${metaDataName} error: ${error}`);
3401cb0ef41Sopenharmony_ci        }
3411cb0ef41Sopenharmony_ci    }
3421cb0ef41Sopenharmony_ci}
3431cb0ef41Sopenharmony_ciexports.Updater = Updater;
344