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