@mikezimm/fps-core-v7
Version:
Library of reusable core interfaces, types and constants migrated from fps-library-v2
169 lines • 7.4 kB
JavaScript
/**
* This utility script helps to:
* 1. Identify local changes to specific npm packages.
* 2. Back up only the locally changed files to a backup folder for reference or debugging.
*
* Usage in 'Backup' mode:
* ts-node backup-node-mods.ts --backup
*
* Usage in 'Identify' mode (just highlights changes):
* ts-node backup-node-mods.ts
*/
const fs = require('fs');
const path = require('path');
const readline = require('readline');
// Configuration constants
// const NODE_MODULES_DIR = path.resolve('node_modules');
// const MODS_DIR = path.resolve('node_modules_mods');
// Use process.cwd() for the root directory instead of __dirname
const rootDir = path.resolve(process.cwd(), ''); // Or your desired directory relative to the project root
// Configuration constants
const NODE_MODULES_DIR = path.join(rootDir, 'node_modules');
const MODS_DIR = path.resolve(rootDir, 'node_modules_mods');
const MODS_DIR_Clear = path.resolve(rootDir, 'node_modules_mods/@mikezimm');
const PACKAGE_FOLDERS = [
'@mikezimm/fps-library-v2',
'@mikezimm/fps-core-v7',
'@mikezimm/fps-styles',
'@mikezimm/fps-Pnp2',
];
const TIME_DIFFERENCE_THRESHOLD = 5 * 60 * 1000; // 5 minutes in milliseconds
// Default mode: 'identify'
let OPERATION_MODE = (process.argv.includes('--backup') ? 'backup' : 'identify');
// Function to log messages with optional color
function logMessage(message, color) {
const colorCodes = {
red: '\x1b[31m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
green: '\x1b[32m',
};
console.log(colorCodes[color] || '', message, '\x1b[0m');
}
// Function to prompt the user for backup confirmation
async function promptForBackupConfirmation() {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
return new Promise((resolve) => {
rl.question('Are you sure you want to back up the changes? (yes/no) ', (answer) => {
rl.close();
resolve(answer.trim().toLowerCase() === 'yes');
});
});
}
// Get the last modified time of a file
function getModifiedTime(filePath) {
return fs.statSync(filePath).mtimeMs;
}
// Copy a file to the destination, creating directories as needed
function copyFileWithMinimalStructure(src, dest) {
const destDir = path.dirname(dest);
fs.mkdirSync(destDir, { recursive: true });
fs.copyFileSync(src, dest);
}
// Append a message to the log file
function appendToLogFile(filePath, content) {
fs.appendFileSync(filePath, content + '\n');
}
function make2DigitNum(str) {
return !str ? '--' : `${str.length === 1 ? '0' : ''}${str}`;
}
// Function to format the current date and time in a sortable format
function getFormattedDate() {
const now = new Date();
const year = now.getFullYear();
const month = (now.getMonth() + 1).toString();
const day = make2DigitNum(now.getDate().toString());
const hours = make2DigitNum(now.getHours().toString());
const minutes = make2DigitNum(now.getMinutes().toString());
const seconds = make2DigitNum(now.getSeconds().toString());
return `${year}-${month}-${day} ${hours}_${minutes}_${seconds}`;
}
// Function to remove all files and subdirectories in a directory
function clearBackupFolder(dir) {
if (fs.existsSync(dir)) {
fs.readdirSync(dir).forEach((file) => {
const fullPath = path.join(dir, file);
if (fs.lstatSync(fullPath).isDirectory()) {
clearBackupFolder(fullPath); // Recursive delete for subdirectories
fs.rmdirSync(fullPath); // Remove empty directory
}
else {
fs.unlinkSync(fullPath); // Delete file
}
});
}
}
// Function to find and handle modified files
async function findModifiedFiles() {
if (OPERATION_MODE === 'backup') {
const confirmed = await promptForBackupConfirmation();
if (!confirmed) {
logMessage('Backup operation canceled.', 'yellow');
return;
}
else {
// Clear the backup folder at the beginning of the run (but not the log folder)
if (fs.existsSync(MODS_DIR_Clear)) {
clearBackupFolder(MODS_DIR_Clear);
}
}
}
logMessage(`Starting in ${OPERATION_MODE.toUpperCase()} mode...\n`, 'blue');
if (!fs.existsSync(MODS_DIR)) {
fs.mkdirSync(MODS_DIR);
}
const logFileName = `modified-files-${getFormattedDate()}.log`;
const logFilePath = path.join(MODS_DIR, logFileName);
fs.writeFileSync(logFilePath, 'Modified files log:\n');
let iP = 0;
PACKAGE_FOLDERS.forEach((packageName) => {
const packagePath = path.join(NODE_MODULES_DIR, packageName);
const packageJsonPath = path.join(packagePath, 'package.json');
if (!fs.existsSync(packageJsonPath)) {
logMessage(`\n\npackage.json not found for ${packageName}\n\n`, 'yellow');
return;
}
const packageModifiedTime = getModifiedTime(packageJsonPath);
// if ( iP > 0 ) appendToLogFile(logFilePath, `\n===== ${packageName} =====\n`);
logMessage(`${iP > 0 ? '\n\n' : ''}Checking package: ${packageName}\n`, 'blue');
appendToLogFile(logFilePath, `\n===== ${packageName} =====\n`);
const collectFiles = (dir, baseDir) => {
fs.readdirSync(dir, { withFileTypes: true }).forEach((entry) => {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
// Ensure we're not traversing into unwanted directories like `@types`
if (!fullPath.includes('@types')) {
collectFiles(fullPath, baseDir);
}
}
else if (entry.isFile()) {
const fileModifiedTime = getModifiedTime(fullPath);
if (fileModifiedTime > packageModifiedTime + TIME_DIFFERENCE_THRESHOLD) {
const relativePath = path.relative(baseDir, fullPath);
if (OPERATION_MODE === 'identify') {
logMessage(`Identified changed file: ${packageName}\\${relativePath}`, 'yellow');
appendToLogFile(logFilePath, `Identified changes: ${packageName}\\${relativePath}`);
}
else if (OPERATION_MODE === 'backup') {
const destPath = path.join(MODS_DIR, packageName, relativePath);
copyFileWithMinimalStructure(fullPath, destPath);
appendToLogFile(logFilePath, `Backed up changes: ${packageName}\\${relativePath}`);
logMessage(`Backed up changed file: ${relativePath}`, 'red');
}
}
}
});
};
collectFiles(packagePath, packagePath);
iP++;
});
logMessage(`Log file of changed files created at: ${logFilePath}`, 'green');
}
// Run the main function
findModifiedFiles().catch((error) => {
logMessage(`Error: ${error.message}`, 'red');
});
//# sourceMappingURL=backup-node-mods.js.map