summaryrefslogtreecommitdiff
path: root/file_utils.js
diff options
context:
space:
mode:
authorJules Laplace <julescarbon@gmail.com>2021-08-16 16:26:01 +0200
committerJules Laplace <julescarbon@gmail.com>2021-08-16 16:26:01 +0200
commitbf563861320cf207bb2d788f50b327e4eb37016a (patch)
tree7e775216592e1f935fd9a10a6cf59f84c789f7c9 /file_utils.js
parent9ae202820b698796f93b929b3e30cd499de796a1 (diff)
showing a graph
Diffstat (limited to 'file_utils.js')
-rw-r--r--file_utils.js152
1 files changed, 152 insertions, 0 deletions
diff --git a/file_utils.js b/file_utils.js
new file mode 100644
index 0000000..16b12cd
--- /dev/null
+++ b/file_utils.js
@@ -0,0 +1,152 @@
+/**
+ * File system utilities.
+ * @module app/utils/file_utils
+ */
+
+import filesystem from "fs";
+import parseCSV from "csv-parse";
+import stringifyCSVCallback from "csv-stringify";
+
+/**
+ * Helper function to load CSV from a file
+ * @param {string} inputFile path to the file
+ * @return {Promise} promise which will resolve with the parsed CSV
+ */
+
+const csvReadOptions = {
+ columns: true,
+};
+
+export const loadCSV = (inputFile, options = {}) =>
+ new Promise((resolve, reject) => {
+ if (!filesystem.existsSync(inputFile)) {
+ return reject("inputFile does not exist");
+ }
+ const csvOptions = {
+ ...csvReadOptions,
+ ...options,
+ };
+ filesystem.readFile(inputFile, "utf8", (error, text) => {
+ if (error) {
+ return reject(`Error reading file: ${error}`);
+ }
+ try {
+ parseCSV(text, csvOptions, function (err, data) {
+ if (err) {
+ return reject("Error parsing JSON");
+ }
+ resolve(data);
+ });
+ } catch {
+ reject("Error parsing JSON");
+ }
+ });
+ });
+
+/**
+ * Helper function to stringify an array-of-arrays to a CSV (with Promise interface)
+ * @param {Array[]} rows array of arrays
+ * @return {Promise} promise which will resolve with the stringified CSV
+ */
+
+export const stringifyCSV = (rows) =>
+ new Promise((resolve, reject) => {
+ stringifyCSVCallback(rows, (error, output) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve(output);
+ }
+ });
+ });
+
+/**
+ * Helper function to attempt to mitigate malicious CSV data
+ * @param {Array[]} rows array of arrays
+ * @return {Array[]} the sanitized input
+ */
+export const sanitizeCSV = (rows) =>
+ rows.map((row) =>
+ row.map((cell) => (cell && typeof cell === "string" ? "'" + cell : cell))
+ );
+
+/**
+ * Helper function to load JSON from a file
+ * @param {string} inputFile path to the file
+ * @return {Promise} promise which will resolve with the parsed JSON
+ */
+export const loadJSON = (inputFile) =>
+ new Promise((resolve, reject) => {
+ if (!filesystem.existsSync(inputFile)) {
+ return reject("inputFile does not exist");
+ }
+ filesystem.readFile(inputFile, "utf8", (error, text) => {
+ if (error) {
+ return reject(`Error reading file: ${error}`);
+ }
+ try {
+ const data = JSON.parse(text);
+ resolve(data);
+ } catch {
+ reject("Error parsing JSON");
+ }
+ });
+ });
+
+const writeFileOptions = {
+ replace: true,
+};
+
+/**
+ * Helper to write a string to a file
+ * @param {string} outputFile the file to write to
+ * @param {string|string[]} data the data to write
+ * @param {Object} options options, by default will overwrite the existing file
+ * @return {Promise} promise which will resolve when the file is saved
+ */
+export const writeFile = (outputFile, data, options = {}) => {
+ options = { ...writeFileOptions, ...options };
+ return new Promise((resolve, reject) => {
+ if (filesystem.existsSync(outputFile) && !options.replace) {
+ return reject("outputFile exists");
+ }
+ if (Array.isArray(data)) {
+ data = data.join("\n");
+ }
+ filesystem.writeFile(outputFile, data, { encoding: "utf8" }, (error) => {
+ if (error) {
+ return reject(`Error writing file: ${error}`);
+ }
+ resolve();
+ });
+ });
+};
+
+const writeJSONOptions = {
+ ...writeFileOptions,
+ indent: true,
+};
+
+/**
+ * Helper to write JSON data to a file
+ * @param {string} outputFile the file to write to
+ * @param {Object} data the data to write
+ * @param {Object} options options, by default will overwrite the existing file
+ * @return {Promise} promise which will resolve when the file is saved
+ */
+export const writeJSON = (outputFile, data, options = {}) => {
+ options = { ...writeJSONOptions, ...options };
+ return new Promise((resolve, reject) => {
+ let json;
+ try {
+ if (options.indent) {
+ json = JSON.stringify(data, false, 2);
+ } else {
+ json = JSON.stringify(data);
+ }
+ } catch {
+ return reject("couldn't stringify JSON");
+ }
+ return writeFile(outputFile, json, options);
+ });
+};