@augment-vir/node
Version:
A collection of augments, helpers types, functions, and classes only for Node.js (backend) JavaScript environments.
122 lines (111 loc) • 3.62 kB
text/typescript
import {check} from '@augment-vir/assert';
import {getObjectTypedEntries} from '@augment-vir/common';
import {readdir, readFile, rm, stat} from 'node:fs/promises';
import {join} from 'node:path';
import {writeFileAndDir} from './write.js';
/**
* Nested contents read from a file system directory.
*
* @category Node : File
* @category Package : @augment-vir/node
* @package [`@augment-vir/node`](https://www.npmjs.com/package/@augment-vir/node)
*/
export type DirContents = {
[Path in string]: string | DirContents;
};
/**
* Read all contents within a directory and store them in an object. Optionally recursive.
*
* @category Node : File
* @category Package : @augment-vir/node
* @package [`@augment-vir/node`](https://www.npmjs.com/package/@augment-vir/node)
*/
export async function readAllDirContents(
dir: string,
{
recursive = false,
excludeList,
}: {
recursive?: boolean;
excludeList?: ReadonlyArray<string | RegExp> | undefined;
},
): Promise<DirContents> {
const fileNames = (await readdir(dir)).sort();
const allFileContents = await Promise.all(
fileNames.map(async (fileName) => {
const filePath = join(dir, fileName);
if (
excludeList?.some((excludeItem) => {
if (check.isString(excludeItem)) {
return filePath.includes(excludeItem);
} else {
return filePath.match(excludeItem);
}
})
) {
return undefined;
}
const isFile = (await stat(filePath)).isFile();
const contents = isFile
? (await readFile(filePath)).toString()
: recursive
? await readAllDirContents(filePath, {recursive, excludeList})
: undefined;
if (check.isObject(contents) && !Object.keys(contents).length) {
return undefined;
}
return contents;
}),
);
return fileNames.reduce((accum: DirContents, fileName, index) => {
if (allFileContents[index] != undefined) {
const fileContents = allFileContents[index];
accum[fileName] = fileContents;
}
return accum;
}, {});
}
/**
* Deletes and entire directory and resets it to the given contents.
*
* @category Node : File
* @category Package : @augment-vir/node
* @package [`@augment-vir/node`](https://www.npmjs.com/package/@augment-vir/node)
*/
export async function resetDirContents(
rootDir: string,
contents: Readonly<DirContents>,
): Promise<void> {
await rm(rootDir, {
force: true,
recursive: true,
});
await writeDirContents(rootDir, contents);
}
/**
* Write {@link DirContents} to a directory.
*
* @category Node : File
* @category Package : @augment-vir/node
* @package [`@augment-vir/node`](https://www.npmjs.com/package/@augment-vir/node)
*/
export async function writeDirContents(
rootDir: string,
contents: Readonly<DirContents>,
): Promise<void> {
await Promise.all(
getObjectTypedEntries(contents).map(
async ([
relativePath,
content,
]) => {
const fullPath = join(rootDir, relativePath);
if (check.isString(content)) {
await writeFileAndDir(fullPath, content);
} else {
await writeDirContents(fullPath, content);
}
},
),
);
}