kebab-ify-files
kebab-ify-files copied to clipboard
Getting error when running the script
Getting this error after a while:
node:child_process:929
throw err;
^
<ref *1> Error: spawnSync /Users/jisuo/Code/pwa/git-rename-commands.sh Unknown system error -8
at Object.spawnSync (node:internal/child_process:1124:20)
at spawnSync (node:child_process:876:24)
at execFileSync (node:child_process:919:15)
at /Users/jisuo/.npm/_npx/faf6fa9f064ad02f/node_modules/kebab-ify-files/cli.js:152:19
at /Users/jisuo/.npm/_npx/faf6fa9f064ad02f/node_modules/recursive-readdir/index.js:81:22
at /Users/jisuo/.npm/_npx/faf6fa9f064ad02f/node_modules/recursive-readdir/index.js:81:22
at /Users/jisuo/.npm/_npx/faf6fa9f064ad02f/node_modules/recursive-readdir/index.js:81:22
at /Users/jisuo/.npm/_npx/faf6fa9f064ad02f/node_modules/recursive-readdir/index.js:81:22
at /Users/jisuo/.npm/_npx/faf6fa9f064ad02f/node_modules/recursive-readdir/index.js:81:22
at /Users/jisuo/.npm/_npx/faf6fa9f064ad02f/node_modules/recursive-readdir/index.js:81:22 {
errno: -8,
code: 'Unknown system error -8',
syscall: 'spawnSync /Users/jisuo/Code/pwa/git-rename-commands.sh',
path: '/Users/jisuo/Code/pwa/git-rename-commands.sh',
spawnargs: [],
error: [Circular *1],
status: null,
signal: null,
output: null,
pid: 0,
stdout: null,
stderr: null
}
Node.js v20.16.0
git-rename-commands.sh has been created with a bunch of git mv commands but no kebab-ify.log exist.
Any idea what could be the issue? Trying to search for these error messages.
So the first errors was that first line of git-rename-commands.sh was git #!/bin/bash which is an error. The code needs prepend that to gitcommands array after adding all the files.
After that the script ran but I encountered a lot of git mv problems and they happened because it tried to move files in a folder that was not renamed, but it tried to move them to the renamed folder.
I tried to hand over the task to chat gpt and after some trial and error I got something working where I go depth first. It is MUCH slower since it does not batch updates, instead doing them in a loop. I think I also got a bunch of other problems, but I did a lot of manual problem solving as well, so the script is not 100% working, but here it is:
import fs from "fs";
import path from "path";
import { execSync } from "child_process";
function toKebabCase(str: string): string {
return str
.replace(/([a-z])([A-Z])/g, "$1-$2") // Handle camelCase or PascalCase
.replace(/([A-Z])([A-Z][a-z])/g, "$1-$2") // Handle edge cases with two capitals
.toLowerCase();
}
function renameWithGitMv(oldPath: string, newPath: string): void {
try {
execSync(`git mv "${oldPath}" "${newPath}"`);
} catch (error) {
console.error(`Error: git mv failed for ${oldPath} -> ${newPath}`);
process.exit(1);
}
}
function processFolder(dir: string): void {
const entries = fs.readdirSync(dir, { withFileTypes: true });
const folders: fs.Dirent[] = [];
const files: fs.Dirent[] = [];
// Separate folders and files
for (const entry of entries) {
if (entry.name === ".DS_Store") continue; // Ignore .DS_Store
if (entry.isDirectory()) {
folders.push(entry);
} else {
files.push(entry);
}
}
// Process subfolders (deepest-first)
for (const folder of folders) {
const folderPath = path.join(dir, folder.name);
processFolder(folderPath); // Recurse into the folder
}
// Rename files in the current folder
for (const file of files) {
const oldFilePath = path.join(dir, file.name);
const kebabCaseName = toKebabCase(file.name);
const ext = path.extname(file.name);
const base = path.basename(file.name, ext);
const tempFilePath = path.join(dir, `${base}.temp${ext}`);
const finalFilePath = path.join(dir, kebabCaseName);
// Step 1: Rename to temp
renameWithGitMv(oldFilePath, tempFilePath);
// Step 2: Rename to final name
renameWithGitMv(tempFilePath, finalFilePath);
}
// Rename the current folder after processing its contents
const currentFolderName = path.basename(dir);
const parentDir = path.dirname(dir);
const kebabCaseName = toKebabCase(currentFolderName);
const tempFolderPath = path.join(parentDir, kebabCaseName + "-temp");
const finalFolderPath = path.join(parentDir, kebabCaseName);
if (currentFolderName !== kebabCaseName) {
// Step 1: Rename to temp
renameWithGitMv(dir, tempFolderPath);
// Step 2: Rename to final name
renameWithGitMv(tempFolderPath, finalFolderPath);
}
}
function updateImportsWithGit(dir: string): void {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.name === ".DS_Store") continue; // Ignore .DS_Store
if (entry.isDirectory()) {
updateImportsWithGit(fullPath);
} else if (entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx"))) {
let content = fs.readFileSync(fullPath, "utf-8");
// Regular `import` or `require`
const importRegex = /from\s+['"]([^'"]+)['"]/g;
// Lazy imports like `import(...)`, supports multiline
const lazyImportRegex = /import\s*\(\s*(['"])(.*?)\1\s*\)/gs;
let hasChanges = false;
// Update standard imports
content = content.replace(importRegex, (_, importPath) => {
const kebabCasePath = toKebabCase(importPath);
hasChanges = true;
return `from '${kebabCasePath}'`;
});
// Update lazy imports
content = content.replace(lazyImportRegex, (_, quote, importPath) => {
const kebabCasePath = toKebabCase(importPath);
hasChanges = true;
return `import(${quote}${kebabCasePath}${quote})`;
});
if (hasChanges) {
fs.writeFileSync(fullPath, content); // Apply changes locally
execSync(`git add "${fullPath}"`); // Stage changes in Git
}
}
}
}
function main() {
const targetDir = process.argv[2];
if (!targetDir) {
console.error("Usage: ts-node script.ts <target-directory>");
process.exit(1);
}
const absolutePath = path.resolve(targetDir);
processFolder(absolutePath);
updateImportsWithGit(absolutePath);
}
main();
The problem seems to be related to the Node.js version — v20.16.0 didn't work for me.
Switched to v14.18.0 and it worked. @jisuo
NVM fails to install node 14 for me now, but the kebabify script worked with node 16.
Note: I opened a PR addressing this