@axway-api-builder-ext/api-builder-plugin-fn-file
Version:
File Flow-Node to read/write files as part of an API-Builder flow.
167 lines (155 loc) • 4.72 kB
JavaScript
const fs = require('fs').promises;
const util = require('util');
const path = require('path');
/**
* Action method.
*
* @param {object} params - A map of all the parameters passed from the flow.
* @param {object} options - The additional options provided from the flow
* engine.
* @param {object} options.pluginConfig - The service configuration for this
* plugin from API Builder config.pluginConfig['api-builder-plugin-pluginName']
* @param {object} options.logger - The API Builder logger which can be used
* to log messages to the console. When run in unit-tests, the messages are
* not logged. If you wish to test logging, you will need to create a
* mocked logger (e.g. using `simple-mock`) and override in
* `MockRuntime.loadPlugin`. For more information about the logger, see:
* https://docs.axway.com/bundle/api-builder/page/docs/developer_guide/project/logging/index.html
* @example
* Log errors with logger.error('Your error message');
* @param {*} [options.pluginContext] - The data provided by passing the
* context to `sdk.load(file, actions, { pluginContext })` in `getPlugin`
* in `index.js`.
* @return {*} The response value (resolves to "next" output, or if the method
* does not define "next", the first defined output).
*/
async function writeFile(params, options) {
var { filename, data, stringify, overwrite } = params;
const logger = options.logger;
let dataEncoding = 'utf8';
let flag = 'wx';
if (!filename) {
throw new Error('Missing required parameter: filename');
}
if (!data) {
throw new Error('Missing required parameter: data');
}
if(params.dataEncoding) {
dataEncoding = params.dataEncoding;
}
if(typeof(stringify) == "undefined") {
stringify = true;
}
if(params.overwrite) {
flag = 'w';
}
if(data instanceof Object && stringify) {
data = JSON.stringify(data);
}
options.logger.debug(`Going to write to filename: '${filename}'`);
try {
await fs.writeFile(filename, data, {encoding: dataEncoding, flag: flag});
} catch(ex) {
throw new Error(`Error writing file: ${filename}. Message: ${ex.message}`, ex)
};
return filename;
}
async function readFile(params, options) {
var { filename, encoding, parseJson, data, limit } = params;
const { logger } = options;
if (!filename) {
throw new Error('Missing required parameter: filename');
}
if(!encoding) {
encoding = "utf8";
}
var notFoundFails = false;
if(params.notFoundFails) {
notFoundFails = params.notFoundFails;
}
if(data) {
filename = await interpolate(filename, data, logger);
}
options.logger.debug(`Trying to read file: '${filename}'`);
const chunkSize = 8192;
let bytesRead = 0;
let buffer = Buffer.alloc(chunkSize);
let content = "";
let fd;
try {
fd = await fs.open(filename, 'r');
const fileInfo = await fd.stat();
while (true) {
let data = await fd.read(buffer, 0, chunkSize, null);
if(limit && (bytesRead + data.bytesRead) > limit) {
content += buffer.toString(encoding, 0, limit - bytesRead);
break;
} else {
content += buffer.toString(encoding, 0, data.bytesRead);
}
if (bytesRead >= fileInfo.size) {
break;
}
bytesRead += chunkSize;
}
} catch(ex) {
if(notFoundFails) {
throw new Error(`Error reading file: ${filename}. ${ex}`);
} else {
return options.setOutput('notFound', `File: ${filename} not found.`);
}
} finally {
if(fd) {
await fd.close();
}
}
/*
try {
var content = await fs.readFile(filename, {encoding: encoding});
} catch(ex) {
if(notFoundFails) {
throw new Error(`Error reading file: ${filename}. ${ex}`);
} else {
return options.setOutput('notFound', `File: ${filename} not found.`);
}
} */
if(parseJson) {
content = JSON.parse(content);
}
return content;
}
async function interpolate(string, data, logger) {
if(string) {
string = JSON.stringify(string);
} else {
return;
}
logger.debug(`Got string: ${string}`);
var result = string.replace(/\${([^}]+)}/g, (_, target) => {
let keys = target.split(".");
return keys.reduce((prev, curr) => {
if (curr.search(/\[/g) > -1) {
//if element/key in target array is array, get the value and return
let m_curr = curr.replace(/\]/g, "");
let arr = m_curr.split("[");
return arr.reduce((pr, cu) => {
if(pr[cu] == undefined) {
throw new Error(`Missing data for selector: \$\{${curr}\}`);
}
return pr && pr[cu];
}, prev);
} else {
//else it is a object, get the value and return
if(prev[curr] == undefined) {
throw new Error(`Missing data for selector: \$\{${curr}\}`);
}
return prev && prev[curr];
}
}, data);
});
return JSON.parse(result);
};
module.exports = {
writeFile,
readFile
};