@controlplane/cli
Version:
Control Plane Corporation CLI
143 lines • 4.54 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.makePatch = void 0;
const UrlPattern = require("url-pattern");
const _ = require("lodash");
/*
{
path: 'spec.containers.<name>.memory',
},
{
path: 'spec.containers.<name>.env.<key>',
},
*/
function makePatch(paths, expr, ctx) {
const patch = {};
const matchers = paths.map((p) => {
const url = p.path
.replace(/\./g, '/')
.replace(/<name>/g, ':name')
.replace(/<key>/g, ':key');
return {
orig: p,
asUrl: url,
pattern: new UrlPattern(url),
};
});
for (let e of expr) {
let op = '';
let selector = '';
let value = '';
let parsed = false;
let i = e.indexOf('+=');
if (!parsed && i >= 0) {
parsed = true;
op = '+=';
selector = e.substring(0, i);
value = e.substring(i + 2);
}
i = e.indexOf('-=');
if (!parsed && i >= 0) {
parsed = true;
op = '-=';
selector = e.substring(0, i);
value = e.substring(i + 2);
}
i = e.indexOf('=');
if (!parsed && i >= 0) {
parsed = true;
op = '=';
selector = e.substring(0, i);
value = e.substring(i + 1);
if (value === 'null') {
value = null;
}
}
if (!parsed) {
throw new Error(`Cannot parse <${e}>: missing operator =, -= or +=`);
}
const asUrl = selector.replace(/\./g, '/');
let matched = false;
for (let m of matchers) {
if (!m.pattern.match(asUrl)) {
continue;
}
// resolve link
if (m.orig.itemLinkResolver) {
value = m.orig.itemLinkResolver.resourceLink(value, ctx);
}
if (!m.orig.array && op != '=') {
throw new Error(`Cannot parse <${e}>. ${op} is supported only for arrays and <${m.orig.path}> is not`);
}
accumulatePatch(patch, m.orig, selector, op, value);
matched = true;
// first match is ok as the paths are assumed unique
break;
}
if (!matched) {
throw new Error(`Cannot parse <${e}>. <${selector}> is not valid updatable path`);
}
}
return patch;
}
exports.makePatch = makePatch;
function accumulatePatch(res, p, selector, op, value) {
var _a, _b;
let current = res;
const templateSegments = p.path.split('.');
const selectorSegments = selector.split('.');
for (let i = 0; i < templateSegments.length; i++) {
const seg = templateSegments[i];
const isLast = i == templateSegments.length - 1;
const nextSeg = templateSegments[i + 1];
const nextSel = selectorSegments[i + 1];
if (nextSeg == '<name>') {
const key = '$patch/' + selectorSegments[i];
// navigate
current[key] = (_a = current[key]) !== null && _a !== void 0 ? _a : [];
let found = _.find(current[key], (x) => x.name === nextSel);
if (!found) {
found = {
name: nextSel,
};
current[key].push(found);
}
current = found;
}
else if (seg == '<key>') {
const key = selectorSegments[i];
// TODO key only at terminal position??
current[key] = value;
}
else if (seg == '<name>') {
if (isLast) {
throw new Error(`Bad updateble path detected: ${p.path}`);
}
continue;
}
else {
if (isLast) {
if (op == '+=') {
current['$append/' + seg] = [value];
}
else if (op == '-=') {
current['$drop/' + seg] = [value];
}
else {
if (p.array) {
current[seg] = value.split(',');
}
else {
current[seg] = value;
}
}
}
else {
// navigate
current[seg] = (_b = current[seg]) !== null && _b !== void 0 ? _b : {};
current = current[seg];
}
}
}
}
//# sourceMappingURL=update.js.map
;