Node.js ライブラリ開発環境をつくる Babel+flow+jest

Node.js モジュール・プロジェクトについては、毎回スクラッチから作っています。
しかし構築までの手順が多く、調べるにも時間が掛かります。
もしかするとワンコマンドで出来るのかもしれませんが…

今回は古典的な方法を使い、自分用にまとめをしました。

プロジェクトの初期化

```bat
yarn init
yarn add flow-bin -D
yarn flow init
REM https://babeljs.io/setup#installation
npm install --save-dev @babel/core @babel/cli
yarn add @babel/preset-env -D
yarn add @babel/plugin-transform-flow-strip-types -D
yarn add @babel/plugin-transform-modules-commonjs -D
REM https://www.npmjs.com/package/babel-plugin-add-module-exports
yarn add babel-plugin-add-module-exports -D
yarn add jest babel-jest -D
REM https://stackoverflow.com/a/50805762
npx flow-typed install jest@24
```

.flowconfig

```.flowconfig
[ignore]
.*/node_modules/.*
./lib

[include]

[libs]
flow-typed

[lints]

[options]

[strict]

```

.babelrc

```.babelrc
{
    "presets": [
        [
            "@babel/env",
            {
                "modules": "commonjs"
            }
        ]
    ],
    "plugins": [
        "@babel/plugin-transform-flow-strip-types",
        [
            "@babel/plugin-transform-modules-commonjs",
            {
                "loose": true
            }
        ],
        [
            "babel-plugin-add-module-exports",
            {
                "addDefaultProperty": true
            }
        ]
    ]
}
```

**Note:** `"loose": true` は IE 8 (ES3) 対策です。IE 8 以下の ES3 では `Object.defineProperty` が使用できません。これは冒頭の `__esModule` 定義で問題になります: `Object.defineProperty(exports, "__esModule", { value: true });` → `exports.__esModule = true;`

**Note:** `"addDefaultProperty": true` は、このモジュールをインポートする TypeScript コンパイラ用の投薬です。

.eslintrc.json

```.eslintrc.json
{
    "env": {
        "jest": true
    }
}
```
- [What's the right way to write Jest tests verified with Flow?](https://stackoverflow.com/questions/35898251/whats-the-right-way-to-write-jest-tests-verified-with-flow)

package.json より

```json
{
  "scripts": {
    "build": "babel src -d lib",
    "generate": "npm run build && node lib/generator",
    "test": "jest --rootDir src",
    "prepare": "npm run build && npm run test"
  }
}
```

.editorconfig

```.editorconfig
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf

charset = utf-8

[*.js]
indent_style = space
indent_size = 4
```

`.gitignore` につきましては https://gitignore.io/api/node,visualstudiocode

VSCode では

- <kbd>Ctrl+Shift+P</kbd> と <kbd>Open Workspace Settings</kbd>
- さらに <kbd>JavaScript validate</kbd>
- `JavaScript > Validate: Enable` → オフ

.npmignore

```.npmignore
/src/
/lib/*.test.js
/.babelrc
/.editorconfig
/.eslintrc.json
/.flowconfig
/flow-typed
/.vscode
```

index.js

```index.js
/** @flow */

export default {
    like
};

export function like() {
    ...
}
```

**Note:** TypeScript 利用者のために export default / export と、2 回も export しています。

index.test.js

```index.test.js
/** @flow */
const myPackage = require('./index');

test('test', () => {
    expect(myPackage.like()).toBeFalsy();
});
```

lib/index.d.ts

```lib/index.d.ts
declare module 'myPackage' {
    interface Index {
        like(): void;
    }

    const index: Index;
    export default index;
}
```