mirror of
https://github.com/n8n-io/n8n.git
synced 2026-06-01 17:27:14 +02:00
117 lines
3.2 KiB
TypeScript
117 lines
3.2 KiB
TypeScript
import { camelCase } from 'change-case';
|
|
import fs from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
|
|
import { isEnoentError } from './validation';
|
|
|
|
export async function folderExists(dir: string) {
|
|
try {
|
|
const stat = await fs.stat(dir);
|
|
return stat.isDirectory();
|
|
} catch (error: unknown) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export async function copyFolder({
|
|
source: source,
|
|
destination,
|
|
ignore = [],
|
|
}: { source: string; destination: string; ignore?: string[] }): Promise<void> {
|
|
const ignoreSet = new Set(ignore);
|
|
|
|
async function walkAndCopy(currentSrc: string, currentDest: string): Promise<void> {
|
|
const entries = await fs.readdir(currentSrc, { withFileTypes: true });
|
|
|
|
await Promise.all(
|
|
entries.map(async (entry) => {
|
|
if (ignoreSet.has(entry.name)) return;
|
|
|
|
const srcPath = path.join(currentSrc, entry.name);
|
|
const destPath = path.join(currentDest, entry.name);
|
|
|
|
if (entry.isDirectory()) {
|
|
await fs.mkdir(destPath, { recursive: true });
|
|
await walkAndCopy(srcPath, destPath);
|
|
} else {
|
|
await fs.copyFile(srcPath, destPath);
|
|
}
|
|
}),
|
|
);
|
|
}
|
|
|
|
await fs.mkdir(destination, { recursive: true });
|
|
await walkAndCopy(source, destination);
|
|
}
|
|
|
|
export async function delayAtLeast<T>(promise: Promise<T>, minMs: number): Promise<T> {
|
|
const delayPromise = new Promise((res) => setTimeout(res, minMs));
|
|
const [result] = await Promise.all([promise, delayPromise]);
|
|
return result;
|
|
}
|
|
|
|
export async function writeFileSafe(
|
|
filePath: string,
|
|
contents: string | Uint8Array,
|
|
): Promise<void> {
|
|
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
await fs.writeFile(filePath, contents);
|
|
}
|
|
|
|
export async function ensureFolder(dir: string) {
|
|
return await fs.mkdir(dir, { recursive: true });
|
|
}
|
|
|
|
export async function renameFilesInDirectory(
|
|
dirPath: string,
|
|
oldName: string,
|
|
newName: string,
|
|
): Promise<void> {
|
|
const files = await fs.readdir(dirPath);
|
|
|
|
for (const file of files) {
|
|
const oldPath = path.resolve(dirPath, file);
|
|
const oldFileName = path.basename(oldPath);
|
|
const newFileName = oldFileName
|
|
.replace(oldName, newName)
|
|
.replace(camelCase(oldName), camelCase(newName));
|
|
|
|
if (newFileName !== oldFileName) {
|
|
const newPath = path.resolve(dirPath, newFileName);
|
|
await fs.rename(oldPath, newPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function renameDirectory(oldDirPath: string, newDirName: string): Promise<string> {
|
|
const parentDir = path.dirname(oldDirPath);
|
|
const newDirPath = path.resolve(parentDir, newDirName);
|
|
await fs.rename(oldDirPath, newDirPath);
|
|
return newDirPath;
|
|
}
|
|
|
|
export async function createSymlink(target: string, linkPath: string): Promise<void> {
|
|
await fs.mkdir(path.dirname(linkPath), { recursive: true });
|
|
|
|
try {
|
|
const stats = await fs.lstat(linkPath);
|
|
if (stats.isSymbolicLink() || stats.isFile()) {
|
|
await fs.unlink(linkPath);
|
|
} else if (stats.isDirectory()) {
|
|
await fs.rm(linkPath, { recursive: true, force: true });
|
|
}
|
|
} catch (error) {
|
|
if (!isEnoentError(error)) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
try {
|
|
const targetStats = await fs.stat(target);
|
|
const type = targetStats.isDirectory() ? 'dir' : 'file';
|
|
await fs.symlink(target, linkPath, type);
|
|
} catch {
|
|
await fs.symlink(target, linkPath, 'junction');
|
|
}
|
|
}
|