sb-mig
Version:
CLI to rule the world. (and handle stuff related to Storyblok CMS)
216 lines (211 loc) • 7.49 kB
JavaScript
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;
};