UNPKG

ask-cli-x

Version:

Alexa Skills Kit (ASK) Command Line Interfaces

124 lines (123 loc) 4.11 kB
"use strict"; const R = require("ramda"); const fs = require("fs-extra"); const path = require("path"); const CliFileNotFoundError = require("../exceptions/cli-file-not-found-error"); const jsonView = require("../view/json-view"); const yaml = require("./yaml-parser"); const FILE_EXTNAME_JSON = ".json"; const FILE_EXTNAME_YAML = ".yaml"; const FILE_EXTNAME_YML = ".yml"; const FILE_TYPE_JSON = "JSON"; const FILE_TYPE_YAML = "YAML"; const READ_METHOD_BY_FILE_TYPE = { JSON: (filePath) => { try { return JSON.parse(fs.readFileSync(filePath, "utf-8")); } catch (error) { throw new Error(`Failed to parse JSON file ${filePath}.\n${error}`); } }, YAML: (filePath) => { try { return yaml.load(filePath); } catch (error) { throw new Error(`Failed to parse YAML file ${filePath}.\n${error}`); } }, }; const WRITE_METHOD_BY_FILE_TYPE = { JSON: (filePath, content) => { fs.writeFileSync(filePath, jsonView.toString(content), "utf-8"); }, YAML: (filePath, content) => { yaml.dump(filePath, content); }, }; module.exports = class ConfigFile { /** * Constructor function for ConfigFile. Current support JSON and YAML. * @param {string} filePath * @throws {Error} */ constructor(filePath) { this.path = filePath; this.content = null; this.fileType = null; this.fileNotFoundHintMessage = ""; } /** * Write content to file path using ConfigFile's WRITE_METHODs * @param {String} filePath * @param {Object} content */ static withContent(filePath, content) { // ensure file exits with content if (fs.existsSync(filePath)) { throw new Error(`Failed to create file ${filePath} as it already exists.`); } fs.ensureDirSync(path.dirname(filePath)); const fileType = _resolveFileType(filePath); WRITE_METHOD_BY_FILE_TYPE[fileType](filePath, content); } /** * Get property based on the property array. * Return undefined if not found. * @param {string} pathArray e.g. ['path', 'to', 'the', '3rd', 'object', 2, 'done'] */ getProperty(pathArray) { return R.view(R.lensPath(pathArray), this.content); } /** * Set property to the runtime object based on the property array. * Create field if path does not exist. * @param {string} pathArray * @param {string} newValue */ setProperty(pathArray, newValue) { this.content = R.set(R.lensPath(pathArray), newValue, this.content); } /** * Write file according to the file path and serialize it based on file extname */ write() { WRITE_METHOD_BY_FILE_TYPE[this.fileType](this.path, this.content); } /** * Read from file path and deserialize it based on file extname */ read() { this._validateFilePath(); this.fileType = _resolveFileType(this.path); this.content = READ_METHOD_BY_FILE_TYPE[this.fileType](this.path); } _validateFilePath() { // check existence if (!fs.existsSync(this.path)) { throw new CliFileNotFoundError(`File ${this.path} not exists.${this.fileNotFoundHintMessage}`); } // check access permission try { fs.accessSync(this.path, fs.constants.R_OK | fs.constants.W_OK); } catch (error) { throw new Error(`No access to read/write file ${this.path}.`); } } }; function _resolveFileType(filePath) { if (path.basename(filePath) === "cli_config") { return FILE_TYPE_JSON; } // check file extension const fileExtension = path.extname(filePath).toLowerCase(); if (fileExtension === FILE_EXTNAME_JSON) { return FILE_TYPE_JSON; } if (fileExtension === FILE_EXTNAME_YAML || fileExtension === FILE_EXTNAME_YML) { return FILE_TYPE_YAML; } throw new Error(`File type for ${filePath} is not supported. Only JSON and YAML files are supported.`); }