UNPKG

sb-mig

Version:

CLI to rule the world. (and handle stuff related to Storyblok CMS)

216 lines (211 loc) 7.49 kB
import * as fs from "fs"; import { writeFile } from "fs"; import { createRequire } from "module"; import nodePath from "path"; import { pathToFileURL } from "url"; import pkg from "ncp"; import { generateDatestamp } from "./date-utils.js"; import Logger from "./logger.js"; const { ncp } = pkg; const resolveFromCwd = (filePath, pathApi = nodePath) => pathApi.isAbsolute(filePath) ? filePath : pathApi.resolve(process.cwd(), filePath); export const toImportSpecifier = (filePath, platform = process.platform) => { if (/^(file|data|node):/.test(filePath)) { return filePath; } const pathApi = platform === "win32" ? nodePath.win32 : nodePath; const resolvedPath = resolveFromCwd(filePath, pathApi); return platform === "win32" ? pathToFileURL(resolvedPath, { windows: true }).href : resolvedPath; }; // ============================================================================ // File Content Loading // ============================================================================ /** * Asynchronously load a file using dynamic import * Returns the default export of the module * * @param data - Object containing the file path * @returns The default export of the imported module */ export const getFileContent = (data) => { return import(/* @vite-ignore */ toImportSpecifier(data.file)) .then((res) => { return res.default; }) .catch((err) => { console.log(err); console.log("Cannot find requested file."); }); }; /** * Synchronously load a file using require * Handles both CommonJS and ES modules with default exports * * @param data - Object containing the file path * @returns The file content (default export if available) */ export const getFileContentWithRequire = (data) => { const require = createRequire(import.meta.url); const fileContent = require(data.file); if (fileContent.default) { return fileContent.default; } return fileContent; }; /** * Load multiple files using require * * @param data - Object containing array of file paths * @returns Array of file contents */ export const getFilesContentWithRequire = (data) => { return data.files.map((file) => getFileContentWithRequire({ file })); }; /** * Read and parse the package.json from current working directory * * @returns Parsed package.json object */ export const getPackageJson = () => { const packageJsonPath = nodePath.join(process.cwd(), "package.json"); const packageJsonContent = fs.readFileSync(packageJsonPath, "utf-8"); const packageJson = JSON.parse(packageJsonContent); return packageJson; }; export const isDirectoryExists = (path) => fs.existsSync(path); export const createDir = async (dirPath) => { await fs.promises.mkdir(resolveFromCwd(dirPath), { recursive: true, }); }; export const createJsonFile = async (content, pathWithFilename) => { await fs.promises.writeFile(pathWithFilename, content, { flag: "w" }); }; export const createJSAllComponentsFile = async (content, pathWithFilename, timestamp = false) => { const datestamp = new Date(); const finalContent = `/* Auto-generated file by sb-mig discovery ${timestamp ? `Generated on: ${generateDatestamp(datestamp)}` : ""} Do not edit manually (use yarn components:discover instead) */ export const componentList = ${content} as const; export type Components = typeof componentList[number]; `; await fs.promises.writeFile(pathWithFilename, finalContent, { flag: "w" }); }; export const copyFolder = async (src, dest) => { return new Promise((resolve, reject) => { ncp(src, dest, function (err) { if (err) { reject({ failed: true, message: `${src} copied unsuccessfully.`, }); } resolve({ failed: false, message: `${src} copied successfully.`, }); }); }); }; export const copyFile = async (src, dest) => { const directory = nodePath.dirname(dest); const fileName = nodePath.basename(src); if (!isDirectoryExists(directory)) { await createDir(directory); } fs.copyFile(src, dest, (err) => { if (err) { console.error(`There is no file to copy, named ${fileName}`); console.log(err); return false; } console.log(`${fileName} was copied to ${dest}`); return true; }); }; /* * * General function to create and save to file * the most used one for many different purposes * * */ export const createAndSaveToFile = async (args, config) => { const { sbmigWorkingDirectory } = config; const { ext = "json", datestamp = false, prefix = "", suffix = "", path = null, filename = "", folder = "default", res, } = args; if (!path) { const timestamp = generateDatestamp(new Date()); const finalFilename = `${prefix}${filename}${datestamp ? `__${timestamp}` : ""}`; const fullPath = `${sbmigWorkingDirectory}/${folder}/${finalFilename}${suffix}.${ext}`; await createDir(`${sbmigWorkingDirectory}/${folder}/`); if (ext === "json") { await createJsonFile(JSON.stringify(res, undefined, 2), fullPath); } else { await createJsonFile(JSON.stringify(res, undefined, 2), fullPath); } Logger.success(`All response written to a file: ${fullPath}`); } if (path) { const folderPath = nodePath.dirname(path); await createDir(folderPath); await createJsonFile(JSON.stringify(res, undefined, 2), path); Logger.success(`All response written to a file: ${path}`); } }; /* * * Specific function for saving component list to file * ef backpack related * * */ export const createAndSaveComponentListToFile = async ({ file, folder, res, timestamp = false }, config) => { const { sbmigWorkingDirectory } = config; const datestamp = new Date(); const filename = file ?? `all-components__${generateDatestamp(datestamp)}`; await createDir(folder ? `${sbmigWorkingDirectory}/${folder}/` : `${sbmigWorkingDirectory}/`); await createJSAllComponentsFile(JSON.stringify(res, null, 2), folder ? `${sbmigWorkingDirectory}/${folder}/${filename}.ts` : `${sbmigWorkingDirectory}/${filename}.ts`, timestamp); Logger.success(`All components written to a file: ${filename}`); }; export const readFile = async (pathToFile) => { const absolutePath = resolveFromCwd(pathToFile); try { const result = await fs.promises.readFile(absolutePath); return result.toString(); } catch (e) { console.log(e); console.error("Error happened while reading file."); return; } }; export const dumpToFile = async (path, content) => { writeFile(path, content, (err) => { if (err) { console.error("Error writing to file:", err); } else { console.log("Successfully wrote to file"); } }); }; export const getConsumerPackageJson = async () => { const consumerPkg = await getFileContentWithRequire({ file: nodePath.join(process.cwd(), "package.json"), }); return consumerPkg; }; export const getSbMigPackageJson = async () => { const sbMigPkg = await getFileContentWithRequire({ file: nodePath.join("..", "..", "package.json"), }); return sbMigPkg; };