FSTB-็—›ใฟใ‚’ไผดใ‚ใšใซNode.jsใฎใƒ•ใ‚กใ‚คใƒซใ‚’ๆ“ไฝœใ™ใ‚‹

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/





ๆธ…่ดใ‚ใ‚ŠใŒใจใ†ใ”ใ–ใ„ใพใ—ใŸ๏ผ








All Articles