UNPKG

@decaf-ts/fabric-weaver

Version:
136 lines 18.5 kB
import { Logging } from "@decaf-ts/logging"; import { FabricBinaries } from "../constants/fabric-binaries"; import { PeerChannelCommands, PeerCommands } from "../constants/fabric-peer"; import { runCommand } from "../../utils/child-process"; export class FabricPeerChannelCommandBuilder { constructor(logger) { this.binName = FabricBinaries.PEER; this.baseCommand = PeerCommands.CHANNEL; this.command = PeerChannelCommands.JOIN; this.args = []; if (!logger) this.log = Logging.for(FabricPeerChannelCommandBuilder); else this.log = logger.for(FabricPeerChannelCommandBuilder.name); } setCommand(command) { if (command !== undefined) { this.log.debug(`Setting command to ${command}`); this.command = command; } return this; } setBlockPath(blockPath) { if (blockPath !== undefined) { this.log.debug(`Setting blockpath to ${blockPath}`); this.args.push(`--blockpath ${blockPath}`); } return this; } setBlockReference(blockRef) { if (blockRef !== undefined) { this.log.debug(`Setting block reference to ${blockRef}`); this.blockReference = blockRef; } return this; } setDestination(destination) { if (destination !== undefined) { this.log.debug(`Setting destination to ${destination}`); this.destination = destination; } return this; } setChannelID(channelID) { if (channelID !== undefined) { this.log.debug(`Setting channel ID to ${channelID}`); this.args.push(`--channelID ${channelID}`); } return this; } setOrderer(orderer) { if (orderer !== undefined) { this.log.debug(`Setting orderer to ${orderer}`); this.args.push(`--orderer ${orderer}`); } return this; } enableTLS(enable) { if (enable !== undefined && enable === true) { this.log.debug(`Setting TLS enabled: ${enable}`); this.args.push(`--tls`); } return this; } setTLSCAFile(caFile) { if (caFile !== undefined) { this.log.debug(`Setting TLS CA file: ${caFile}`); this.args.push(`--cafile ${caFile}`); } return this; } build() { const command = [ this.getBinary(), this.getBaseCommand(), this.getCommand(), this.blockReference, this.destination, ...[...new Set(this.args)], ] .filter((item) => item !== undefined && item !== null && item !== "") .join(" "); this.log.debug(`Built command: ${command}`); return command; } getBaseCommand() { return this.baseCommand; } getCommand() { return this.command; } getBinary() { return this.binName; } getArgs() { return [...new Set(this.args)]; } async execute() { const bin = this.getBinary(); const argz = [ this.getBaseCommand(), this.getCommand(), this.blockReference, this.destination, ...this.getArgs(), ].filter((item) => item !== undefined && item !== null && item !== ""); try { // const regex = /\[\s*INFO\s*\] Listening on http/; // can be used as a promise but to lock the logs running as execsync await runCommand(bin, argz); } catch (error) { this.log.error(`Error: Failed to execute the command: ${error}`); process.exit(1); } } } // Flags: // --cafile string Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint // --certfile string Path to file containing PEM-encoded X509 public key to use for mutual TLS communication with the orderer endpoint // --clientauth Use mutual TLS when communicating with the orderer endpoint // --connTimeout duration Timeout for client to connect (default 3s) // -h, --help help for channel // --keyfile string Path to file containing PEM-encoded private key to use for mutual TLS communication with the orderer endpoint // -o, --orderer string Ordering service endpoint // --ordererTLSHostnameOverride string The hostname override to use when validating the TLS connection to the orderer // --tls Use TLS when communicating with the orderer endpoint // --tlsHandshakeTimeShift duration The amount of time to shift backwards for certificate expiration checks during TLS handshakes with the orderer endpoint // -f, --file string Configuration transaction file generated by a tool such as configtxgen for submitting to orderer // -h, --help help for create // --outputBlock string The path to write the genesis block for the channel. (default ./<channelID>.block) // -t, --timeout duration Channel creation timeout (default 10s) // --bestEffort Whether fetch requests should ignore errors and return blocks on a best effort basis // --snapshotpath string Path to the snapshot directory // -f, --file string Configuration transaction file generated by a tool such as configtxgen for submitting to orderer //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFicmljLXBlZXItY2hhbm5lbC1jb21tYW5kLWJ1aWxkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZmFicmljL3BlZXIvZmFicmljLXBlZXItY2hhbm5lbC1jb21tYW5kLWJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFVLE9BQU8sRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsWUFBWSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDN0UsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBRXZELE1BQU0sT0FBTywrQkFBK0I7SUFhMUMsWUFBWSxNQUFlO1FBVm5CLFlBQU8sR0FBbUIsY0FBYyxDQUFDLElBQUksQ0FBQztRQUM5QyxnQkFBVyxHQUFHLFlBQVksQ0FBQyxPQUFPLENBQUM7UUFFbkMsWUFBTyxHQUFHLG1CQUFtQixDQUFDLElBQUksQ0FBQztRQUtuQyxTQUFJLEdBQWEsRUFBRSxDQUFDO1FBRzFCLElBQUksQ0FBQyxNQUFNO1lBQUUsSUFBSSxDQUFDLEdBQUcsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLCtCQUErQixDQUFDLENBQUM7O1lBQ2hFLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQywrQkFBK0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNuRSxDQUFDO0lBRUQsVUFBVSxDQUFDLE9BQTZCO1FBQ3RDLElBQUksT0FBTyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzFCLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLHNCQUFzQixPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQ2hELElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3pCLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNk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QUFDLENBQUM7WUFDakUsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNsQixDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBRUQsU0FBUztBQUNULG1JQUFtSTtBQUNuSSxnS0FBZ0s7QUFDaEssMEdBQTBHO0FBQzFHLHlGQUF5RjtBQUN6RiwrREFBK0Q7QUFDL0QsNEpBQTRKO0FBQzVKLHdFQUF3RTtBQUN4RSw2SEFBNkg7QUFDN0gsbUdBQW1HO0FBQ25HLHNLQUFzSztBQUN0SyxnSUFBZ0k7QUFDaEksK0NBQStDO0FBQy9DLGtIQUFrSDtBQUNsSCxzRUFBc0U7QUFDdEUsa0hBQWtIO0FBQ2xILCtEQUErRDtBQUMvRCx5SEFBeUgiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBMb2dnZXIsIExvZ2dpbmcgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcbmltcG9ydCB7IEZhYnJpY0JpbmFyaWVzIH0gZnJvbSBcIi4uL2NvbnN0YW50cy9mYWJyaWMtYmluYXJpZXNcIjtcbmltcG9ydCB7IFBlZXJDaGFubmVsQ29tbWFuZHMsIFBlZXJDb21tYW5kcyB9IGZyb20gXCIuLi9jb25zdGFudHMvZmFicmljLXBlZXJcIjtcbmltcG9ydCB7IHJ1bkNvbW1hbmQgfSBmcm9tIFwiLi4vLi4vdXRpbHMvY2hpbGQtcHJvY2Vzc1wiO1xuXG5leHBvcnQgY2xhc3MgRmFicmljUGVlckNoYW5uZWxDb21tYW5kQnVpbGRlciB7XG4gIHByaXZhdGUgbG9nOiBMb2dnZXI7XG5cbiAgcHJpdmF0ZSBiaW5OYW1lOiBGYWJyaWNCaW5hcmllcyA9IEZhYnJpY0JpbmFyaWVzLlBFRVI7XG4gIHByaXZhdGUgYmFzZUNvbW1hbmQgPSBQZWVyQ29tbWFuZHMuQ0hBTk5FTDtcblxuICBwcml2YXRlIGNvbW1hbmQgPSBQZWVyQ2hhbm5lbENvbW1hbmRzLkpPSU47XG5cbiAgcHJpdmF0ZSBibG9ja1JlZmVyZW5jZT86IHN0cmluZztcbiAgcHJpdmF0ZSBkZXN0aW5hdGlvbj86IHN0cmluZztcblxuICBwcml2YXRlIGFyZ3M6IHN0cmluZ1tdID0gW107XG5cbiAgY29uc3RydWN0b3IobG9nZ2VyPzogTG9nZ2VyKSB7XG4gICAgaWYgKCFsb2dnZXIpIHRoaXMubG9nID0gTG9nZ2luZy5mb3IoRmFicmljUGVlckNoYW5uZWxDb21tYW5kQnVpbGRlcik7XG4gICAgZWxzZSB0aGlzLmxvZyA9IGxvZ2dlci5mb3IoRmFicmljUGVlckNoYW5uZWxDb21tYW5kQnVpbGRlci5uYW1lKTtcbiAgfVxuXG4gIHNldENvbW1hbmQoY29tbWFuZD86IFBlZXJDaGFubmVsQ29tbWFuZHMpOiB0aGlzIHtcbiAgICBpZiAoY29tbWFuZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBjb21tYW5kIHRvICR7Y29tbWFuZH1gKTtcbiAgICAgIHRoaXMuY29tbWFuZCA9IGNvbW1hbmQ7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0QmxvY2tQYXRoKGJsb2NrUGF0aD86IHN0cmluZyk6IHRoaXMge1xuICAgIGlmIChibG9ja1BhdGggIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgYmxvY2twYXRoIHRvICR7YmxvY2tQYXRofWApO1xuICAgICAgdGhpcy5hcmdzLnB1c2goYC0tYmxvY2twYXRoICR7YmxvY2tQYXRofWApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHNldEJsb2NrUmVmZXJlbmNlKGJsb2NrUmVmPzogc3RyaW5nKTogdGhpcyB7XG4gICAgaWYgKGJsb2NrUmVmICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGJsb2NrIHJlZmVyZW5jZSB0byAke2Jsb2NrUmVmfWApO1xuICAgICAgdGhpcy5ibG9ja1JlZmVyZW5jZSA9IGJsb2NrUmVmO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHNldERlc3RpbmF0aW9uKGRlc3RpbmF0aW9uPzogc3RyaW5nKTogdGhpcyB7XG4gICAgaWYgKGRlc3RpbmF0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGRlc3RpbmF0aW9uIHRvICR7ZGVzdGluYXRpb259YCk7XG4gICAgICB0aGlzLmRlc3RpbmF0aW9uID0gZGVzdGluYXRpb247XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0Q2hhbm5lbElEKGNoYW5uZWxJRD86IHN0cmluZyk6IHRoaXMge1xuICAgIGlmIChjaGFubmVsSUQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgY2hhbm5lbCBJRCB0byAke2NoYW5uZWxJRH1gKTtcbiAgICAgIHRoaXMuYXJncy5wdXNoKGAtLWNoYW5uZWxJRCAke2NoYW5uZWxJRH1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRPcmRlcmVyKG9yZGVyZXI/OiBzdHJpbmcpOiB0aGlzIHtcbiAgICBpZiAob3JkZXJlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2V0dGluZyBvcmRlcmVyIHRvICR7b3JkZXJlcn1gKTtcbiAgICAgIHRoaXMuYXJncy5wdXNoKGAtLW9yZGVyZXIgJHtvcmRlcmVyfWApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGVuYWJsZVRMUyhlbmFibGU/OiBib29sZWFuKTogdGhpcyB7XG4gICAgaWYgKGVuYWJsZSAhPT0gdW5kZWZpbmVkICYmIGVuYWJsZSA9PT0gdHJ1ZSkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgVExTIGVuYWJsZWQ6ICR7ZW5hYmxlfWApO1xuICAgICAgdGhpcy5hcmdzLnB1c2goYC0tdGxzYCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0VExTQ0FGaWxlKGNhRmlsZT86IHN0cmluZyk6IHRoaXMge1xuICAgIGlmIChjYUZpbGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNldHRpbmcgVExTIENBIGZpbGU6ICR7Y2FGaWxlfWApO1xuICAgICAgdGhpcy5hcmdzLnB1c2goYC0tY2FmaWxlICR7Y2FGaWxlfWApO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgYnVpbGQoKTogc3RyaW5nIHtcbiAgICBjb25zdCBjb21tYW5kOiBzdHJpbmcgPSBbXG4gICAgICB0aGlzLmdldEJpbmFyeSgpLFxuICAgICAgdGhpcy5nZXRCYXNlQ29tbWFuZCgpLFxuICAgICAgdGhpcy5nZXRDb21tYW5kKCksXG4gICAgICB0aGlzLmJsb2NrUmVmZXJlbmNlLFxuICAgICAgdGhpcy5kZXN0aW5hdGlvbixcbiAgICAgIC4uLlsuLi5uZXcgU2V0KHRoaXMuYXJncyldLFxuICAgIF1cbiAgICAgIC5maWx0ZXIoKGl0ZW0pID0+IGl0ZW0gIT09IHVuZGVmaW5lZCAmJiBpdGVtICE9PSBudWxsICYmIGl0ZW0gIT09IFwiXCIpXG4gICAgICAuam9pbihcIiBcIik7XG5cbiAgICB0aGlzLmxvZy5kZWJ1ZyhgQnVpbHQgY29tbWFuZDogJHtjb21tYW5kfWApO1xuICAgIHJldHVybiBjb21tYW5kO1xuICB9XG5cbiAgZ2V0QmFzZUNvbW1hbmQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5iYXNlQ29tbWFuZDtcbiAgfVxuXG4gIGdldENvbW1hbmQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5jb21tYW5kO1xuICB9XG5cbiAgZ2V0QmluYXJ5KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuYmluTmFtZTtcbiAgfVxuXG4gIGdldEFyZ3MoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiBbLi4ubmV3IFNldCh0aGlzLmFyZ3MpXTtcbiAgfVxuXG4gIGFzeW5jIGV4ZWN1dGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgYmluID0gdGhpcy5nZXRCaW5hcnkoKTtcbiAgICBjb25zdCBhcmd6ID0gW1xuICAgICAgdGhpcy5nZXRCYXNlQ29tbWFuZCgpLFxuICAgICAgdGhpcy5nZXRDb21tYW5kKCksXG4gICAgICB0aGlzLmJsb2NrUmVmZXJlbmNlLFxuICAgICAgdGhpcy5kZXN0aW5hdGlvbixcbiAgICAgIC4uLnRoaXMuZ2V0QXJncygpLFxuICAgIF0uZmlsdGVyKFxuICAgICAgKGl0ZW0pID0+IGl0ZW0gIT09IHVuZGVmaW5lZCAmJiBpdGVtICE9PSBudWxsICYmIGl0ZW0gIT09IFwiXCJcbiAgICApIGFzIHN0cmluZ1tdO1xuXG4gICAgdHJ5IHtcbiAgICAgIC8vIGNvbnN0IHJlZ2V4ID0gL1xcW1xccypJTkZPXFxzKlxcXSBMaXN0ZW5pbmcgb24gaHR0cC87XG4gICAgICAvLyBjYW4gYmUgdXNlZCBhcyBhIHByb21pc2UgYnV0IHRvIGxvY2sgdGhlIGxvZ3MgcnVubmluZyBhcyBleGVjc3luY1xuICAgICAgYXdhaXQgcnVuQ29tbWFuZChiaW4sIGFyZ3opO1xuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICB0aGlzLmxvZy5lcnJvcihgRXJyb3I6IEZhaWxlZCB0byBleGVjdXRlIHRoZSBjb21tYW5kOiAke2Vycm9yfWApO1xuICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgIH1cbiAgfVxufVxuXG4vLyBGbGFnczpcbi8vICAgICAgIC0tY2FmaWxlIHN0cmluZyAgICAgICAgICAgICAgICAgICAgICAgUGF0aCB0byBmaWxlIGNvbnRhaW5pbmcgUEVNLWVuY29kZWQgdHJ1c3RlZCBjZXJ0aWZpY2F0ZShzKSBmb3IgdGhlIG9yZGVyaW5nIGVuZHBvaW50XG4vLyAgICAgICAtLWNlcnRmaWxlIHN0cmluZyAgICAgICAgICAgICAgICAgICAgIFBhdGggdG8gZmlsZSBjb250YWluaW5nIFBFTS1lbmNvZGVkIFg1MDkgcHVibGljIGtleSB0byB1c2UgZm9yIG11dHVhbCBUTFMgY29tbXVuaWNhdGlvbiB3aXRoIHRoZSBvcmRlcmVyIGVuZHBvaW50XG4vLyAgICAgICAtLWNsaWVudGF1dGggICAgICAgICAgICAgICAgICAgICAgICAgIFVzZSBtdXR1YWwgVExTIHdoZW4gY29tbXVuaWNhdGluZyB3aXRoIHRoZSBvcmRlcmVyIGVuZHBvaW50XG4vLyAgICAgICAtLWNvbm5UaW1lb3V0IGR1cmF0aW9uICAgICAgICAgICAgICAgIFRpbWVvdXQgZm9yIGNsaWVudCB0byBjb25uZWN0IChkZWZhdWx0IDNzKVxuLy8gICAtaCwgLS1oZWxwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWxwIGZvciBjaGFubmVsXG4vLyAgICAgICAtLWtleWZpbGUgc3RyaW5nICAgICAgICAgICAgICAgICAgICAgIFBhdGggdG8gZmlsZSBjb250YWluaW5nIFBFTS1lbmNvZGVkIHByaXZhdGUga2V5IHRvIHVzZSBmb3IgbXV0dWFsIFRMUyBjb21tdW5pY2F0aW9uIHdpdGggdGhlIG9yZGVyZXIgZW5kcG9pbnRcbi8vICAgLW8sIC0tb3JkZXJlciBzdHJpbmcgICAgICAgICAgICAgICAgICAgICAgT3JkZXJpbmcgc2VydmljZSBlbmRwb2ludFxuLy8gICAgICAgLS1vcmRlcmVyVExTSG9zdG5hbWVPdmVycmlkZSBzdHJpbmcgICBUaGUgaG9zdG5hbWUgb3ZlcnJpZGUgdG8gdXNlIHdoZW4gdmFsaWRhdGluZyB0aGUgVExTIGNvbm5lY3Rpb24gdG8gdGhlIG9yZGVyZXJcbi8vICAgICAgIC0tdGxzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVXNlIFRMUyB3aGVuIGNvbW11bmljYXRpbmcgd2l0aCB0aGUgb3JkZXJlciBlbmRwb2ludFxuLy8gICAgICAgLS10bHNIYW5kc2hha2VUaW1lU2hpZnQgZHVyYXRpb24gICAgICBUaGUgYW1vdW50IG9mIHRpbWUgdG8gc2hpZnQgYmFja3dhcmRzIGZvciBjZXJ0aWZpY2F0ZSBleHBpcmF0aW9uIGNoZWNrcyBkdXJpbmcgVExTIGhhbmRzaGFrZXMgd2l0aCB0aGUgb3JkZXJlciBlbmRwb2ludFxuLy8gICAtZiwgLS1maWxlIHN0cmluZyAgICAgICAgICBDb25maWd1cmF0aW9uIHRyYW5zYWN0aW9uIGZpbGUgZ2VuZXJhdGVkIGJ5IGEgdG9vbCBzdWNoIGFzIGNvbmZpZ3R4Z2VuIGZvciBzdWJtaXR0aW5nIHRvIG9yZGVyZXJcbi8vICAgLWgsIC0taGVscCAgICAgICAgICAgICAgICAgaGVscCBmb3IgY3JlYXRlXG4vLyAgICAgICAtLW91dHB1dEJsb2NrIHN0cmluZyAgIFRoZSBwYXRoIHRvIHdyaXRlIHRoZSBnZW5lc2lzIGJsb2NrIGZvciB0aGUgY2hhbm5lbC4gKGRlZmF1bHQgLi88Y2hhbm5lbElEPi5ibG9jaylcbi8vICAgLXQsIC0tdGltZW91dCBkdXJhdGlvbiAgICAgQ2hhbm5lbCBjcmVhdGlvbiB0aW1lb3V0IChkZWZhdWx0IDEwcylcbi8vICAgICAgIC0tYmVzdEVmZm9ydCAgICAgICAgIFdoZXRoZXIgZmV0Y2ggcmVxdWVzdHMgc2hvdWxkIGlnbm9yZSBlcnJvcnMgYW5kIHJldHVybiBibG9ja3Mgb24gYSBiZXN0IGVmZm9ydCBiYXNpc1xuLy8gICAgICAgLS1zbmFwc2hvdHBhdGggc3RyaW5nICAgUGF0aCB0byB0aGUgc25hcHNob3QgZGlyZWN0b3J5XG4vLyAgIC1mLCAtLWZpbGUgc3RyaW5nICAgQ29uZmlndXJhdGlvbiB0cmFuc2FjdGlvbiBmaWxlIGdlbmVyYXRlZCBieSBhIHRvb2wgc3VjaCBhcyBjb25maWd0eGdlbiBmb3Igc3VibWl0dGluZyB0byBvcmRlcmVyXG4iXX0=