appcenter-cli
Version:
Command line tool for Visual Studio App Center
104 lines (94 loc) • 2.42 kB
text/typescript
//
// Utility functions used to encode and decode values
// stored in the token cache as keys or values.
//
import * as _ from "lodash";
//
// Replace ':' chars with '\:' and
// replace '\' chars with '\\'
//
export function escape(s: string): string {
let result = "";
_.each(s, function (ch) {
switch (ch) {
case ":":
result += "\\:";
break;
case "\\":
result += "\\\\";
break;
default:
result += ch;
}
});
return result;
}
//
// Reverse of escape - converts \: and \\ back
// to their single character equivalents.
//
export function unescape(s: string): string {
let result = "";
let afterSlash = false;
_.each(s, function (ch) {
if (!afterSlash) {
if (ch === "\\") {
afterSlash = true;
} else {
result += ch;
}
} else {
result += ch;
afterSlash = false;
}
});
if (afterSlash) {
result += "\\";
}
return result;
}
export function encodeObject(obj: any): string {
return _.chain(obj)
.toPairs()
.sortBy(function (p) { return p[0]; })
.map(function (p) {
if (_.isBoolean(p[1])) {
return [p[0], p[1].toString()];
}
if (_.isDate(p[1])) {
return [p[0], (p[1] as Date).toISOString()];
}
return [p[0], p[1] ? p[1].toString() : ""];
})
.map(function (p) { return p.map(escape); })
.map(function (p) { return p.join(":"); })
.value()
.join("::");
}
function endsWith(s: string, ending: string): boolean {
return s.substring(s.length - ending.length) === ending;
}
function partToKeyValue(part: string): string[] {
const parts: string[] = part.split(":");
const value: string[] = parts.reduce(
(accumulator: string[], value: string, index: number, array: string[]): string[] => {
if (accumulator[1] !== null && endsWith(accumulator[1], "\\")) {
accumulator[1] += ":" + value;
} else if (accumulator[0] === null) {
accumulator[0] = value;
} else if (endsWith(accumulator[0], "\\")) {
accumulator[0] += ":" + value;
} else {
accumulator[1] = value;
}
return accumulator;
}, [null, null]);
return value;
}
export function decodeObject(key: string): any {
return _.chain(key.split("::"))
.map(partToKeyValue)
.map(function (pairs) { return pairs.map(unescape); })
.fromPairs()
.value();
}