UNPKG

@miyagi/core

Version:

miyagi is a component development tool for JavaScript template engines.

208 lines (190 loc) 5.72 kB
/** * Module for getting the content of all relevant files * @module stateFilecontents */ import { readFile as readFileFs } from "node:fs/promises"; import path from "path"; import anymatch from "anymatch"; import yaml from "js-yaml"; import { marked as Markdown } from "marked"; import * as helpers from "../helpers.js"; import log from "../logger.js"; /** * Checks if a given array of file paths includes a given file path * @param {string} file - file path string * @param {Array} fileNames - array of file path string * @returns {boolean} is true if given array includes given file path */ function checkIfFileNamesIncludeFile(file, fileNames) { return fileNames.includes(path.basename(file)); } /** * Returns all component and docs file from components.folder * @param {object} sourceTree * @returns {Promise<string[]>} */ async function getFilePaths(sourceTree) { const { assets, components, files } = global.config; const paths = [...assets.customProperties.files]; if (sourceTree.components) { (function getPaths(entry) { if (!anymatch(components.ignores, entry.path)) { if (entry.type === "file") { if ( checkIfFileNamesIncludeFile(entry.path, [ `${helpers.getResolvedFileName( files.templates.name, path.basename(entry.path, `.${files.templates.extension}`), )}.${files.templates.extension}`, `${files.mocks.name}.${files.mocks.extension[0]}`, `${files.mocks.name}.${files.mocks.extension[1]}`, `${files.schema.name}.${files.schema.extension}`, ]) || helpers.fileIsDocumentationFile(entry.path) ) { paths.push(entry.path); } } else if (entry.type === "directory") { entry.children.forEach((item) => getPaths(item)); } } })(sourceTree.components); } if (sourceTree.docs) { (function getPaths(entry) { if (entry.type === "file") { paths.push(entry.path); } else if (entry.type === "directory") { entry.children.forEach((item) => getPaths(item)); } })(sourceTree.docs); } return paths; } /** * Calls the default export of an ES module and returns its return value * or returns the return value directly if it is not a function * @param {string} fileName - file path string * @returns {Promise<string>} - the default export of the ES module */ async function getJsFileContent(fileName) { const file = await import(path.resolve(`${fileName}?time=${Date.now()}`)); return file.default(); } /** * Returns the content of a YAML file parsed as JSON object * @param {string} fileName - path to a yaml file * @returns {Promise<object>} the content of the given file as an object */ async function getYamlFileContent(fileName) { try { const result = await readFileFs(fileName, "utf8"); return yaml.load(result); } catch (err) { return Promise.reject(err); } } /** * Returns the parsed content of a JSON file. * @param {string} fileName - path to a json file * @returns {Promise<object>} the parsed content of the given file */ async function getParsedJsonFileContent(fileName) { try { const result = await readFileFs(fileName, "utf8"); return JSON.parse(result); } catch (err) { return Promise.reject(err); } } /** * Returns the as HTML rendered content of markdown files. * @param {string} fileName - path to a markdown file * @returns {Promise<string>} the markdown of the given file converted into HTML */ async function getConvertedMarkdownFileContent(fileName) { try { const result = await readFileFs(fileName, "utf8"); return Markdown.parse(result); } catch (err) { return Promise.reject(err); } } /** * Calls different functions getting the file's content based on its type * and returns the (converted) file content. * @param {string} fileName - path to a file of any type * @returns {Promise<string|object|Array>} content of the given file based on its type */ export const readFile = async function (fileName) { switch (true) { case [".yaml", ".yml"].includes(path.extname(fileName)): { try { return await getYamlFileContent(fileName); } catch (err) { log("error", `Error when reading file ${fileName}`, err); } } break; case helpers.fileIsDocumentationFile(fileName): { try { return await getConvertedMarkdownFileContent(fileName); } catch (err) { log("error", `Error when reading file ${fileName}`, err); } } break; case helpers.fileIsDataFile(fileName) && [".js", ".mjs"].includes(path.extname(fileName)): { try { return await getJsFileContent(fileName); } catch (err) { log("error", `Error when reading file ${fileName}`, err); } } break; case fileName.endsWith(".json"): { try { return await getParsedJsonFileContent(fileName); } catch (err) { log("error", `Error when reading file ${fileName}`, err); } } break; default: { try { return await readFileFs(fileName, { encoding: "utf8" }); } catch (err) { log("error", `Error when reading file ${fileName}`, err); } } } }; /** * Returns a promise which will be resolved with an object, * including all component files (except for template files) * and their content. * @param {object} sourceTree * @returns {Promise} gets resolved with the content of all docs, mocks, schema files */ export const getFileContents = async function (sourceTree) { const fileContents = {}; const paths = await getFilePaths(sourceTree); if (paths) { await Promise.all( paths.map(async (fullPath) => { try { fileContents[fullPath] = await readFile(fullPath.replace(/\0/g, "")); } catch (err) { return err; } }), ); return fileContents; } return {}; };