netconf-client
Version:
159 lines • 5.16 kB
JavaScript
import { tap } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { stringify as yamlStringify } from 'yaml';
import { MultipleEditError } from "../lib/index.js";
import { yellow } from "./output-colors.js";
import { Output } from "./output.js";
import { ResultFormat } from "./parse-args.js";
import { asTree } from 'object-as-tree';
/**
* A helper class to manage EPIPE when writing to stdout
*/
class Writer {
static write(data) {
const writer = Writer.getInstance();
if (writer.error) {
if (writer.error.hasOwnProperty('code') && writer.error.code === 'EPIPE') {
// Ignore EPIPE errors
}
else {
throw new Error(`Error writing to stdout: ${writer.error.message}`);
}
}
else {
writer.writeStdout(data);
}
}
static instance;
static getInstance() {
if (!Writer.instance) {
Writer.instance = new Writer();
}
return Writer.instance;
}
error;
constructor() {
process.stdout.on('error', (e) => {
const writer = Writer.getInstance();
writer.error = e;
if (e.hasOwnProperty('code') && e.code === 'EPIPE') {
// Ignore EPIPE errors
}
else {
// This error will not be caught by RxJS
throw new Error(`Error writing to stdout: ${e.message}`);
}
});
}
writeStdout(data) {
process.stdout.write(data);
}
}
function formatPrimitive(val) {
if (typeof val === 'string') {
if (val.includes('\n')) {
return `'${val.replace(/'/g, '\\\'')}'`;
}
return val;
}
return String(val);
}
function printKeyValue(prefix, obj) {
if (Array.isArray(obj)) {
// Array of objects: recurse into each item
obj.forEach((item, index) => {
// In XPath index starts at 1
const indexedPrefix = `${prefix}[${index + 1}]`;
printKeyValue(indexedPrefix, item);
});
}
else if (obj && typeof obj === 'object') {
for (const key of Object.keys(obj)) {
const keyPrefix = prefix === '/' ? `/${key}` : prefix.length > 0 ? `${prefix}/${key}` : key;
printKeyValue(keyPrefix, obj[key]);
}
}
else if (prefix.length > 0 && prefix !== '/') {
// Primitive: print the value
Writer.write(`${prefix}=${formatPrimitive(obj)}\n`);
}
}
/**
* RxJs operator - write the result to the console in the specified format
*
* @param data - The result to write
* @param format - The format to write the result in
*/
export function writeData(format) {
return tap(input => {
// If the input is an array, the first element is the result and the second is a boolean
// indicating if the result is the root result
const [data, isRootResult] = Array.isArray(input) && input.length === 2 && typeof input[1] === 'boolean'
? input
: [input, false];
switch (format) {
case ResultFormat.XML:
Writer.write(data.xml);
Writer.write('\n');
break;
case ResultFormat.JSON:
if (data.result === undefined) {
Writer.write(JSON.stringify(null));
}
else {
Writer.write(JSON.stringify(data.result, null, 2));
}
Writer.write('\n');
break;
case ResultFormat.YAML:
if (data.result === undefined) {
Writer.write(yamlStringify(null));
}
else {
Writer.write(yamlStringify(data.result));
}
break;
case ResultFormat.KEYVALUE:
printKeyValue(isRootResult ? '/' : '', data.result);
break;
case ResultFormat.TREE:
default:
Writer.write(data.result === '' ? yellow('no result') : asTree(data.result));
Writer.write('\n');
break;
}
});
}
/**
* RxJs operator - throw an error if the operation is not allowed to edit multiple schema branches
*/
export function catchMultipleEditError() {
return catchError(error => {
if (error instanceof MultipleEditError) {
Output.error('Editing multiple schema branches not allowed. Use --allow-multiple to override.');
throw new Error('Operation not performed');
}
throw error;
});
}
/**
* RxJs operator - set the resulting status of the edit-config
*/
export function setEditConfigStatus() {
return setStatus();
}
/**
* RxJs operator - set the resulting status of the RPC
*/
export function setRpcConfigStatus() {
return setStatus();
}
function setStatus() {
return map((data) => {
if (data.result?.ok !== undefined) {
data.result.ok = 'operation successful';
}
return data;
});
}
//# sourceMappingURL=output-operators.js.map