no such file or directory, open の理由を知る

fsを使用して、上のディレクトリのファイルを取得しようとするとError: ENOENT: no such file or directory, open が出て、喚いていたが解決したので残しておく。
~~既知の事実と言ってはいけない。~~

#ファイル内容
先に記しておくが、後の説明を読みながら解釈することを勧める。


```:ディレクトリ構成
test(親ディレクトリ)
   ├── src
   │   └── fileManeger.js
   ├── config ←(ここに出力)
   │     
   └── main.js

```

```js:main.js
const fs = require('fs'); //nodeモジュール読みこみ
const fileManegerClass = require('./src/fileManeger.js') //クラスファイル読みこみ
const fileManeger = new fileManegerClass();  //インスタンス化

const content = {"name" : "taro" , "age" : 30};

//fsを引数から受け取る　相対パスをmain.jsがあるディレクトリからに
    fileManeger.write1(content, fs);

//fsをメソッド内でインポート　相対パスをmain.jsがあるディレクトリからに
    fileManeger.write2(content);

//fsを引数から受け取る　相対パスをfileManeger.jsがあるディレクトリからに
    fileManeger.write3(content, fs);

//fsをメソッド内でインポート　相対パスをfileManeger.jsがあるディレクトリからに
    fileManeger.write4(content);
```
```js:fileManeger.js
class fileManeger {
    
    //fsを引数から受け取る　相対パスをmain.jsがあるディレクトリからに
    async write1 (content,fs){
        try{
            fs.writeFileSync('./config/write-1.json', JSON.stringify(content, null, "\t"),'utf8');
            console.log(`write1 complete`);
        }catch(e){
            console.log(`write1 fail\n${e}\n-------------------------------\n`);
        };
    };

    //fsをメソッド内でインポート　相対パスをmain.jsがあるディレクトリからに
    async write2 (content) {
        const fs = require('fs');
        try{
            fs.writeFileSync('./config/write-2.json', JSON.stringify(content, null, "\t"),'utf8');
            console.log(`write2 complete`);
        }catch(e){
            console.log(`write2 fail\n${e}\n-------------------------------\n`);
        };
    };

    //fsを引数から受け取る　相対パスをfileManeger.jsがあるディレクトリからに
    async write3 (content,fs) {
        try{
            fs.writeFileSync('../config/write-3.json', JSON.stringify(content, null, "\t"),'utf8');
            console.log(`write3 complete`);
        }catch(e){
            console.log(`write3 fail\n${e}\n-------------------------------\n`);
        };
    };
    //fsをメソッド内でインポート　相対パスをfileManeger.jsがあるディレクトリからに
    async write4 (content) {
        const fs = require('fs');
        try{
            fs.writeFileSync('../config/write-4.json', JSON.stringify(content, null, "\t"),'utf8');
            console.log(`write4 complete`);
        }catch(e){
            console.log(`write4 fail\n${e}\n-------------------------------\n`);
        };
    };
};
module.exports = fileManeger; //クラス出力
```
# やりたいこと

main.jsから`./src/fileManeger.js`(クラス)を読み込み、configディレクトリ内にファイルを出力する。


#はまった理由
結論から言うと、fsのパスの指定の仕方が悪かった。私は最初、fileManeger.jsでfsは呼び出されるのだからパスはそのファイルからたどるのだろうと勝手に推測して`../config/write.json`と指定していた。
しかしながら、fsはパスを作業ディレクトリからたどる。ここでいう作業ディレクトリとは**nodeで実行したファイルがあるディレクトリのこと**、つまりtestディレクトリである。
ということは私が指定したディレクトリはtestディレクトリの上層にあることになってしまっていたのだ。

```

│
├──config(???? 幻のディレクトリ)
│
└──test(ここから ../config/write.json)
      ├── src
      │   └── fileManeger.js
      ├── config ←(ここを指定したはずが...)
      │     
      └── main.js
```

#試してみた
testディレクトリでmain.jsを実行する。
比較のため、fsモジュールの読み込み箇所と出力ファイル名、パスを変えている。
一応、モジュールをインポートする場所は関係ないことを示すために4つのパターンを用意した。

| メソッド名 | パス | モジュールの読み込み |出力ファイル名|
|:-:|:-:|:-:|:-:|
|write1|./config/write-1.json|引数から|write-1.json|
|write2|./config/write-2.json|メソッド内で|write-2.json|
|write3|../config/write-3.json|引数から|write-3.json|
|write4|../config/write-4.json|メソッド内で|write-4.json|
# 実行結果
![console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/767205/803c062f-e2a2-927a-055a-7c07a7d3c0ae.png)

`./config/write-〇.json`のパスであるwrite1メソッドとwrite2メソッドは成功している。
一方、`../config/write-〇.json`のパスであるwrite3メソッドとwrite4メソッドは読み込めないとエラーが出ている。

ファイルも`write-1.json`と`write-2.json`のみ出力されている。
![output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/767205/349ba9b1-d333-3ffa-9037-90f7b843844a.png)

#結論
以上のことから、**fsのファイルパスの起点はnode.jsで実行しているファイルがあるディレクトリであることがわかった**。

よって、fsを使用したコードのエラーでError: ENOENT: no such file or directory, openが出た際は、**ファイルのパスがnode.jsで実行しているファイルがあるディレクトリからの相対パスになっているか確認しよう**。

#参考
公式ドキュメントにファイルパスの話が出ているのでその部分のリンクを記載しておく。
[Node.js v14.13.1 Documentation](https://nodejs.org/api/fs.html#fs_file_paths)

検証に使用したソースコード
[github huda0209/qiita_fs-sample](https://github.com/huda0209/qiita_fs-sample)