Node.jsใฎใใกใคใซใๆไฝใใใจใใๅใใฟใคใใฎใณใผใใใใใใๆธใใฆใใใจๆใฃใฆใใ็งใฏ้ขใใพใใใใใกใคใซใใตใใใฃใฌใฏใใชใฎไฝๆใ่ชญใฟๅใใๆธใ่พผใฟใ็งปๅใๅ้คใใใคใในใชใฉใใใใใในใฆใไฟกใใใใชใใปใฉใฎ้ใฎๅฎๅๆใงๅคงใใใชใใใใฆใใใใขใธใฅใผใซใฎ้ขๆฐใฎๅฅๅฆใชๅๅใซใใฃใฆใใใซๆชๅใใฆใใพใfs
ใใใชใใฏใใใใในใฆใจไธ็ทใซๆฎใใใใจใใงใใพใใใใใฃใจไพฟๅฉใซไฝใใงใใใใจใใ่ใใฏ็งใ้ขใใพใใใงใใใใใจใใฐใใใญในใ๏ผใพใใฏjson๏ผใใใกใคใซใซ่ชญใฟๆธใใใใชใฉใๅบๆฌ็ใชใใจใ1่กใง่จ่ฟฐใใใใฃใใฎใงใใ
ใใใใฎๅ็ใฎ็ตๆใจใใฆใFSTBใฉใคใใฉใชใ็ปๅ ดใใใใกใคใซใทในใใ ใจใฎๅฏพ่ฉฑๆนๆณใๆนๅใใใใจใใพใใใใใฎ่จไบใ่ชญใใงใฉใคใใฉใชใๅฎ้ใซ่ฉฆใใฆใฟใใจใ็งใๆๅใใใใฉใใใๅคๆญใงใใพใใ
ใใใฏใฐใฉใฆใณใ
ใใผใๅ
ใฎใใกใคใซใฎๆไฝใฏใๆๅฆใๆใใไบคๆธใชใฉใใใใคใใฎๆฎต้ใง่กใใใพใใๆๅใซใใกใคใซใทในใใ ใชใใธใงใฏใใธใฎใในใๅๅพใใๆฌกใซใใฎๅญๅจใ็ขบ่ชใ๏ผๅฟ
่ฆใชๅ ดๅ๏ผใใใใๆไฝใใพใใใใผใๅ
ใฎใในใฎๆไฝใฏใ้ๅธธใๅฅใฎใขใธใฅใผใซใซ็งปๅใใใพใใใในใๆไฝใใใใใฎๆใใฏใผใซใช้ขๆฐใฏpath.join
ใงใใ็งใใใใไฝฟใๅงใใใจใใ็งใซใใใใใฎ็ฅ็ต็ดฐ่ใๆใฃใๆฌๅฝใซใฏใผใซใชใใจใ
ใใใใใในใซใฏๅ้กใใใใพใใใในใฏๆๅญๅใงใใใๅบๆฌ็ใซใฏ้ๅฑคๆง้ ๅ ใฎใชใใธใงใฏใใฎๅ ดๆใ่กจใใพใใใพใใใชใใธใงใฏใใๆฑใฃใฆใใใฎใงใ้ๅธธใฎJavaScriptใชใใธใงใฏใใๆฑใใจใใจๅใใกใซใใบใ ใไฝฟใฃใฆใชใใธใงใฏใใๆฑใฃใฆใฟใพใใใใ
ไธปใชๅ้กใฏใใใกใคใซใทในใใ ใชใใธใงใฏใใ่จฑๅฏใใใๆๅญใใไปปๆใฎๅๅใๆใคใใจใใงใใใจใใใใจใงใใใใฎใชใใธใงใฏใใๆไฝใใใใใฎใกใฝใใใไฝๆใใใจใใใจใใฐใๆฌกใฎใณใผใroot.home.mydir.unlink
ใฏใใใพใใซใชใใพใmydir
ใใใใฃใฌใฏใใชใซใใฃใฌใฏใใชใใใๅ ดๅใฏใฉใใชใunlink
ใพใใ๏ผใใใฆใไฝ๏ผๅ้คmydir
ใunlink
ใพใใใใใใจใๅ็
งใใพใใ๏ผ
Javascript Proxใ่ฉฆใใฆใฟใฆใ่ๅณๆทฑใๆง้ ใๆใใคใใใจใ๏ผ
const FSPath = function(path: string): FSPathType {
return new Proxy(() => path, {
get: (_, key: string) => FSPath(join(path, key)),
}) as FSPathType;
};
FSPath
โ , , , , Proxy
, FSPath
, . , , :
FSPath(__dirname).node_modules // path.join(__dirname, "node_modules")
FSPath(__dirname)["package.json"] // path.join(__dirname, "package.json")
FSPath(__dirname)["node_modules"]["fstb"]["package.json"] // path.join(__dirname, "node_modules", "fstb", "package.json")
, , . :
const package_json = FSPath(__dirname).node_modules.fstb["package.json"]
console.log(package_json()) // < >/node_modules/fstb/package.json
, , JS. โ , , :

FSTB โ FileSystem ToolBox.
FSTB:
npm i fstb
:
const fstb = require('fstb');
FSPath
, : cwd
, dirname
, home
tmp
( ). envPath
.
:
fstb.cwd["README.md"]().asFile().read.txt().then(txt=>console.log(txt));
FSTB , async/await:
(async function() {
const package_json = await fstb.cwd["package.json"]().asFile().read.json();
console.log(package_json);
})();
json . , , , .
, - :
const fs = require("fs/promises");
const path = require("path");
(async function() {
const package_json_path = path.join(process.cwd(), "package.json");
const file_content = await fs.readFile(package_json_path, "utf8");
const result = JSON.parse(file_content);
console.log(result);
})();
, , , .
. . , Node.js:
const fs = require('fs');
const readline = require('readline');
async function processLineByLine() {
const fileStream = fs.createReadStream('input.txt');
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
console.log(`Line from file: ${line}`);
}
}
processLineByLine();
FSTB:
(async function() {
await fstb.cwd['package.json']()
.asFile()
.read.lineByLine()
.forEach(line => console.log(`Line from file: ${line}`));
})();
, . , . , , filter
, map
, reduce
.. , , , csv, .map(line => line.split(','))
.
, . . :
(async function() {
const string_to_write = ' !';
await fstb.cwd['habr.txt']()
.asFile()
.write.txt(string_to_write);
})();
:
await fstb.cwd['habr.txt']()
.asFile()
.write.appendFile(string_to_write, {encoding:"utf8"});
json:
(async function() {
const object_to_write = { header: ' !', question: ' ', answer: 42 };
await fstb.cwd['habr.txt']()
.asFile()
.write.json(object_to_write);
})();
:
(async function() {
const file = fstb.cwd['million_of_randoms.txt']().asFile();
//
const stream = file.write.createWriteStream();
stream.on('open', () => {
for (let index = 0; index < 1_000_000; index++) {
stream.write(Math.random() + '\n');
}
stream.end();
});
await stream;
//
const lines = await file.read.lineByLine().reduce(acc => ++acc, 0);
console.log(`${lines} lines count`);
})();
, ? :
await stream; // <= WTF?!!
, WriteStream
, . , , , await
. , await
.
, , . FSTB? , fs.
:
const stat = await file.stat()
console.log(stat);
:
Stats {
dev: 1243191443,
mode: 33206,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
blksize: 4096,
ino: 26740122787869450,
size: 19269750,
blocks: 37640,
atimeMs: 1618579566188.5884,
mtimeMs: 1618579566033.8242,
ctimeMs: 1618579566033.8242,
birthtimeMs: 1618579561341.9297,
atime: 2021-04-16T13:26:06.189Z,
mtime: 2021-04-16T13:26:06.034Z,
ctime: 2021-04-16T13:26:06.034Z,
birthtime: 2021-04-16T13:26:01.342Z
}
-:
const fileHash = await file.hash.md5();
console.log("File md5 hash:", fileHash);
// File md5 hash: 5a0a221c0d24154b850635606e9a5da3
:
const renamedFile = await file.rename(`${fileHash}.txt`);
:
// ,
// "temp"
const targetDir = renamedFile.fsdir.fspath.temp().asDir()
if(!(await targetDir.isExists())) await targetDir.mkdir()
//
const fileCopy = await renamedFile.copyTo(targetDir)
const fileCopyHash = await fileCopy.hash.md5();
console.log("File copy md5 hash:", fileCopyHash);
// File md5 hash: 5a0a221c0d24154b850635606e9a5da3
:
await renamedFile.unlink();
, , :
console.log({
isExists: await file.isExists(),
isReadable: await file.isReadable(),
isWritable: await file.isWritable() });
, , , .
:
, โ . , . , FSTB . FSDir
, :
// FSDir node_modules:
const node_modules = fstb.cwd.node_modules().asDir();
? -, :
//
await node_modules.subdirs().forEach(async dir => console.log(dir.name));
filter, map, reduce, forEach, toArray. , , ยซ@ยป .
const ileSizes = await node_modules
.subdirs()
.filter(async dir => dir.name.startsWith('@'))
.map(async dir => ({ name: dir.name, size: await dir.totalSize() })).toArray();
fileSizes.sort((a,b)=>b.size-a.size);
console.table(fileSizes);
- :
โโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโ
โ (index) โ name โ size โ
โโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโค
โ 0 โ '@babel' โ 6616759 โ
โ 1 โ '@typescript-eslint' โ 2546010 โ
โ 2 โ '@jest' โ 1299423 โ
โ 3 โ '@types' โ 1289380 โ
โ 4 โ '@webassemblyjs' โ 710238 โ
โ 5 โ '@nodelib' โ 512000 โ
โ 6 โ '@rollup' โ 496226 โ
โ 7 โ '@bcoe' โ 276877 โ
โ 8 โ '@xtuc' โ 198883 โ
โ 9 โ '@istanbuljs' โ 70704 โ
โ 10 โ '@sinonjs' โ 37264 โ
โ 11 โ '@cnakazawa' โ 25057 โ
โ 12 โ '@size-limit' โ 14831 โ
โ 13 โ '@polka' โ 6953 โ
โโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโ
, , ))
. , typescript . , :
const ts_versions = await node_modules
.subdirs()
.map(async dir => ({
dir,
package_json: dir.fspath['package.json']().asFile(),
}))
// package.json
.filter(async ({ package_json }) => await package_json.isExists())
// package.json
.map(async ({ dir, package_json }) => ({
dir,
content: await package_json.read.json(),
}))
// devDependencies.typescript package.json
.filter(async ({ content }) => content.devDependencies?.typescript)
// typescript
.map(async ({ dir, content }) => ({
name: dir.name,
ts_version: content.devDependencies.typescript,
}))
.toArray();
console.table(ts_versions);
:
โโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโ
โ (index) โ name โ ts_version โ
โโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโค
โ 0 โ 'ajv' โ '^3.9.5' โ
โ 1 โ 'ast-types' โ '3.9.7' โ
โ 2 โ 'axe-core' โ '^3.5.3' โ
โ 3 โ 'bs-logger' โ '3.x' โ
โ 4 โ 'chalk' โ '^2.5.3' โ
โ 5 โ 'chrome-trace-event' โ '^2.8.1' โ
โ 6 โ 'commander' โ '^3.6.3' โ
โ 7 โ 'constantinople' โ '^2.7.1' โ
โ 8 โ 'css-what' โ '^4.0.2' โ
โ 9 โ 'deepmerge' โ '=2.2.2' โ
โ 10 โ 'enquirer' โ '^3.1.6' โ
...
?
. fspath:
// FSDir node_modules:
const node_modules = fstb.cwd.node_modules().asDir();
// "package.json" "fstb"
const package_json = node_modules.fspath.fstb["package.json"]().asFile()
, temp . FSTB mkdtemp
.
mkdir
. copyTo
moveTo
. - rmdir
( ) rimraf
( ).
:
//
const temp_dir = await fstb.mkdtemp("fstb-");
if(await temp_dir.isExists()) console.log(" ")
// : src, target1 target2
const src = await temp_dir.fspath.src().asDir().mkdir();
const target1 = await temp_dir.fspath.target1().asDir().mkdir();
const target2 = await temp_dir.fspath.target2().asDir().mkdir();
// src :
const test_txt = src.fspath["test.txt"]().asFile();
await test_txt.write.txt(", !");
// src target1
const src_copied = await src.copyTo(target1);
// src target2
const src_movied = await src.moveTo(target2);
//
// subdirs(true) โ
await temp_dir.subdirs(true).forEach(async dir=>{
await dir.files().forEach(async file=>console.log(file.path))
})
// ,
console.log(await src_copied.fspath["test.txt"]().asFile().read.txt())
console.log(await src_movied.fspath["test.txt"]().asFile().read.txt())
//
await temp_dir.rimraf()
if(!(await temp_dir.isExists())) console.log(" ")
:
C:\Users\debgger\AppData\Local\Temp\fstb-KHT0zv\target1\src\test.txt C:\Users\debgger\AppData\Local\Temp\fstb-KHT0zv\target2\src\test.txt , ! , !
, , . , joinโ , .
, Node.js. , . FSTB . , , , , .
, FSTB, :
.
, IDE .
,
Node.js 10- ,
, , , FSPath, , , . .
, , . , . , , .
GitHub: https://github.com/debagger/fstb
: https://debagger.github.io/fstb/
ๆธ ่ดใใใใจใใใใใพใใ๏ผ