[
  {
    "path": ".eslintignore",
    "content": "dist/\n*.d.ts\n"
  },
  {
    "path": ".eslintrc.js",
    "content": "module.exports = {\n  env: {\n    node: true,\n    browser: true,\n    jest: true,\n  },\n  parser: '@typescript-eslint/parser', // Specifies the ESLint parser\n  extends: [\n    'eslint:recommended',\n    'plugin:react/recommended',\n    'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin\n    'prettier/@typescript-eslint',\n    'plugin:prettier/recommended',\n    'plugin:import/errors',\n    'plugin:import/warnings',\n    'plugin:import/typescript',\n  ],\n  parserOptions: {\n    ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features\n    sourceType: 'module', // Allows for the use of imports\n    ecmaFeatures: {\n      jsx: true, // Allows for the parsing of JSX\n    },\n  },\n  settings: {\n    react: {\n      version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use\n    },\n  },\n  rules: {\n    'react/prop-types': 'off',\n    'no-console': ['warn'],\n    'import/no-extraneous-dependencies': ['error'],\n  },\n  overrides: [\n    {\n      files: ['*.{test,spec,story}.ts{,x}'],\n      rules: {\n        'import/no-extraneous-dependencies': ['error', { packageDir: './' }],\n      },\n    },\n  ],\n};\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\ndist\n*.log\n.vscode\n.idea\ncoverage"
  },
  {
    "path": ".npmrc",
    "content": "registry=http://localhost:4873\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"printWidth\": 80,\n  \"tabWidth\": 2,\n  \"singleQuote\": true,\n  \"trailingComma\": \"all\",\n  \"arrowParens\": \"always\"\n}\n"
  },
  {
    "path": ".storybook/addons.js",
    "content": "import '@storybook/addon-actions/register';\nimport '@storybook/addon-links/register';\nimport '@storybook/addon-knobs/register';\n"
  },
  {
    "path": ".storybook/config.js",
    "content": "import { configure, addDecorator } from '@storybook/react';\nimport { withKnobs } from '@storybook/addon-knobs';\n\nconst req = require.context('../packages', true, /.story.tsx?$/);\nfunction loadStories() {\n  addDecorator(withKnobs);\n  req.keys().forEach((filename) => req(filename));\n}\n\nconfigure(loadStories, module);\n"
  },
  {
    "path": ".storybook/webpack.config.js",
    "content": "const path = require('path');\nconst { lstatSync, readdirSync } = require('fs');\n\nconst basePath = path.resolve(__dirname, '../', 'packages');\nconst packages = readdirSync(basePath).filter((name) =>\n  lstatSync(path.join(basePath, name)).isDirectory(),\n);\n\nmodule.exports = async ({ config }) => {\n  config.module.rules.push({\n    test: /\\.(ts|tsx)$/,\n    loader: require.resolve('awesome-typescript-loader'),\n  });\n  config.resolve.extensions.push('.ts', '.tsx');\n\n  Object.assign(config.resolve.alias, {\n    ...packages.reduce(\n      (acc, name) => ({\n        ...acc,\n        [`@taxi/${name}`]: path.join(basePath, name, 'src'),\n      }),\n      {},\n    ),\n  });\n\n  return config;\n};\n"
  },
  {
    "path": ".stylelintrc",
    "content": "{\n  \"extends\": [\n    \"stylelint-config-standard\"\n  ]\n}\n"
  },
  {
    "path": "README.MD",
    "content": "# Monorepo\n\n- [Monorepo](#monorepo)\n  - [The goal](#the-goal)\n  - [Pre-requirements](#pre-requirements)\n    - [Local NPM registry](#local-npm-registry)\n  - [Getting started](#getting-started)\n    - [Repository initialization](#repository-initialization)\n    - [Setting up package manager](#setting-up-package-manager)\n    - [TypeScript](#typescript)\n      - [Installation](#installation)\n      - [Configuration](#configuration)\n      - [Building packages](#building-packages)\n      - [Checking types](#checking-types)\n    - [Peer dependencies](#peer-dependencies)\n    - [Static code analyser](#static-code-analyser)\n      - [@typescript-eslint](#@typescript-eslint)\n      - ~~[Tslint](#tslint)~~\n      - [Stylelint](#stylelint)\n      - [All together](#all-together)\n    - [Code formatting](#code-formatting)\n    - [Testing](#testing)\n    - [Storybook](#storybook)\n      - [Installation](#installation-1)\n      - [Typescript](#typescript)\n      - [@typescript-eslint](#@typescript-eslint-1)\n      - ~~[Tslint](#tslint-1)~~\n      - [Addons](#addons)\n    - [Final build](#final-build)\n    - [Committing your work](#committing-your-work)\n    - [Package publishing](#package-publishing)\n  - [First package](#first-package)\n    - [Development](#development)\n    - [Storybook](#storybook-1)\n    - [Testing](#testing-1)\n    - [Build](#build)\n    - [Publish](#publish)\n  - [Multiple packages](#multiple-packages)\n    - [Development](#development-1)\n      - [Declarations generation](#declarations-generation)\n      - [@typescript-eslint](#@typescript-eslint-2)\n      - ~~[Tslint](#tslint-2)~~\n      - [Drawbacks](#drawbacks)\n    - [Typescript](#typescript-1)\n    - [Storybook](#storybook-2)\n    - [Jest](#jest)\n  - [Final words](#final-words)\n\nEveryone is tired with creating templates for each type of NPM package with pre-configured skeletons, managing different dependencies across own packages, linking packages for local development with instant packages rebuilding which is \"wasting developers time\", writing proper configuration for linters, `babel`, `typescript`, etc, and adds a lot of repeatable steps for developers. The worst part appears when one of the key dependencies is getting breaking change upgrade, for instance `babel` - it produces plenty of duplicated changes in each of the package, massive amount of merge request to be reviewed and introduces high change to make a mistake (or even worse - forget about change) in one of the packages. Hopefully, it's year 2018 and JavaScript world has a solution for managing group of the packages in the one repository. This approach calls `monorepo`.\n\nThere are many of approaches how to implement monorepo - `yarn workspaces`, `buck`, `pants`, `lerna`, and others. In this article we'll cover `lerna` approach with `yarn` as package manager. Moreover, `lerna` integrates so greatly with `yarn workspaces` as it allows to use workspaces commands directly in the repository even without `lerna`.\n\n## The goal\n\nThe goal of this article is to create monorepo starter with Babel for building packages, TypeScript for having benefits of statically typed languages in the JavaScript world, static code analyzing tools (Tslint, Stylelint), Prettier for having automatically formated code (no more tabs or spaces holly wars), Storybook for developing components, and last, but not least - Lerna for publishing. All components will be written with React and StyledComponents for CSS-in-JS styling.\n\nLet's not waste time on long talks about what are those tools and why they are so important, and proceed to the real configuration and will see how everyone will benefit from each in the future.\n\nFor those who are impatient, [here is the link to the repository](https://github.com/serhii-havrylenko/monorepo-babel-ts-lerna-starter) which contains whole set of results form this article - configured monorepo, ready to go and use.\n\n## Pre-requirements\n\nPackages:\n\n- NodeJS LTS\n- [yarn v1.5+](https://yarnpkg.com/)\n- [Lerna v3+](https://lernajs.io/)\n\n### Local NPM registry\n\nLocal NPM registry will be used in whole article to avoid publishing to global registry plenty of test packages. There are plenty of ways how to set up private NPM repository. In this example [Verdaccio](https://github.com/verdaccio/verdaccio) will be used for such purpose.\n\nConfiguration is simple tnd trivial:\n\n```bash\n$ yarn global add verdaccio\n$ verdaccio &\n\n$ npm set registry http://localhost:4873/\n$ npm adduser --registry http://localhost:4873\nUsername: test\nPassword: ***\nEmail: ***\n```\n\nNow we could test how it works:\n\n```\nyarn info @babel/cli\n```\n\nshould still show package details and in console where we started `verdaccio` we should see incoming request\n\n```\n http --> 200, req: 'GET https://registry.npmjs.org/@babel%2Fcli' (streaming)\n http --> 200, req: 'GET https://registry.npmjs.org/@babel%2Fcli', bytes: 0/85596\n```\n\nMoreover, you could open [`http://localhost:4873/`](http://localhost:4873/) for searching published packages.\n\n## Getting started\n\nTime to start our configuration.\n\n### Repository initialization\n\n<p align=\"center\">\n  <a href=\"https://lernajs.io/\">\n    <img alt=\"Lerna\" src=\"https://cloud.githubusercontent.com/assets/952783/15271604/6da94f96-1a06-11e6-8b04-dc3171f79a90.png\" width=\"150\">\n  </a>\n</p>\n\n```bash\n$ lerna init\n```\n\nAnd you have initial structure of the monorepo created by Lerna.\n\nA little bit of important theory about packages Versioning. This step is the most important one on the repository creation stage as it would impact how do we publish/tags our packages.\n\nLerna supports two types of packages versioning:\n\n1.  Independent\n2.  Exact\n\nWhen **exact** type is chosen, Lerna will use the same version for all packages in monorepo. In case when **independent** version is selected, Lerna will release each package with independent version. More details about versioning is on [official Lerna page](https://github.com/lerna/lerna#how-it-works)\n\nThis article will consider only independent versioning for all packages as on the initial stage of packages development of some packages would have much more releases then others, and with independent versioning we would have only required packages released.\n\nGoing back to the real examples:\n\n```\n$ lerna init --independent\nlerna info version 3.4.0\nlerna info Updating package.json\nlerna info Creating lerna.json\nlerna info Creating packages directory\nlerna success Initialized Lerna files\n```\n\nand new repository for packages with independent versioning is ready.\n\n### Setting up package manager\n\nBy default lerna is using NPM, however, it's quite simple to set Yarn as package manager:\n\n```json\n{\n  \"packages\": [\"packages/*\"],\n  \"version\": \"independent\",\n  \"useWorkspaces\": true,\n  \"npmClient\": \"yarn\"\n}\n```\n\nMoreover, with `\"useWorkspaces\": true` we allow `lerna` to support `yarn workspaces` and with `\"packages\": [\"packages/*\"]` we specify in which folder(s) we would have all our packages.\n\n### TypeScript\n\n<p align=\"center\">\n  <a href=\"https://www.typescriptlang.org/\">\n    <img alt=\"typescript\" src=\"https://www.vectorlogo.zone/logos/typescriptlang/typescriptlang-card.png\" width=\"150\">\n  </a>\n</p>\n\nTypeScript could be used in two ways:\n\n- native TypeScript with `tsc`\n- [@babel/preset-typescript](https://babeljs.io/docs/en/babel-preset-typescript)\n\nImplementation from `babel` does not have all features from latest TypeScript (like `const enum`), however, in case of usage `babel` we do not miss all cool plugins and integration with all tools looks much easier.\n\nIn this article we would use only `babel` with `typescript` preset.\n\n#### Installation\n\nJust hit next command to install all required plugins and presets:\n\n```bash\n$ yarn add -DW @babel/cli @babel/core @babel/preset-typescript @babel/preset-env babel-core@7.0.0-bridge.0 @babel/preset-react typescript @types/node\n```\n\n`babel-core@7.0.0-bridge.0` should be noticed separately as it's needed for properly resolving `babel-core` packages for all libs which requires old version of babel and for avoiding duplicated packages installed and possible misusage of `babel` configuration. Next line have to be added to the root `package.json`:\n\n```json\n{\n  \"resolutions\": {\n    \"babel-core\": \"^7.0.0-bridge.0\"\n  }\n}\n```\n\n#### Configuration\n\n<p align=\"center\">\n  <a href=\"https://babeljs.io/\">\n    <img alt=\"babel\" src=\"https://raw.githubusercontent.com/babel/logo/master/babel.png\" width=\"150\">\n  </a>\n</p>\n\nConfiguration is quite simple and trivial - [@babel/preset-react](https://babeljs.io/docs/en/babel-preset-react) and [@babel/preset-typescript](https://babeljs.io/docs/en/babel-preset-typescript) plus simple config for [@babel/preset-env](https://babeljs.io/docs/en/babel-preset-env).\n\nIn Release candidate version, Babel team has removed support for `stage-*` and `preset-201*` packages, so it means that all actually used plugins should be set by users manually.\n\nApart from removing `stage-*` packages, Babel has changed approach for looking up config files - it looks for config in `cwd` till the first `package.json`. More details could be found in [official Babel documentation](https://babeljs.io/docs/en/config-files)\n\nLet's configure `babel.config.js` with next data:\n\n```javascript\nmodule.exports = (api) => {\n  api.cache(true);\n\n  return {\n    presets: [\n      [\n        '@babel/env',\n        {\n          targets: {\n            browsers: 'Last 2 Chrome versions, Firefox ESR',\n            node: '8.9',\n          },\n        },\n      ],\n      [\n        '@babel/preset-react',\n        {\n          development: process.env.BABEL_ENV !== 'build',\n        },\n      ],\n      '@babel/preset-typescript',\n    ],\n    env: {\n      build: {\n        ignore: [\n          '**/*.test.tsx',\n          '**/*.test.ts',\n          '**/*.story.tsx',\n          '__snapshots__',\n          '__tests__',\n          '__stories__',\n        ],\n      },\n    },\n    ignore: ['node_modules'],\n  };\n};\n```\n\n#### Building packages\n\nDue to changes for config lookup, build command in monorepo should have path to `.babelrc` or `babel.config.js` specified, or as [--root-mode option](https://babeljs.io/docs/en/options#rootmode). It could be done directly in build commands:\n\n1.  In root package.json:\n\n```json\n{\n  \"scripts\": {\n    \"build\": \"lerna exec --parallel 'BABEL_ENV=build babel src --out-dir dist --source-maps --extensions .ts,.tsx --config-file ../../babel.config.js --delete-dir-on-start --no-comments'\"\n  }\n}\n```\n\n2.  `build` command in each package. In this case each of packages could be built independently without `lerna`. In this case `build` command is a little bit different:\n\n```json\n{\n  \"scripts\": {\n    \"build\": \"BABEL_ENV=build babel src --out-dir dist --source-maps --extensions .ts,.tsx --delete-dir-on-start --config-file ../../babel.config.js --no-comments\"\n  }\n}\n```\n\n3. Another way how to treat parent babel config is `extends` option provided by latest babel. The easiest approach for that is setting next lines in `package.json` on package level:\n\n```json\n{\n  \"extends\": \"../../babel.config.js\"\n}\n```\n\n- In this case build command doesn't require passing path to babel config and will be simplified:\n\n```json\n{\n  \"scripts\": {\n    \"build\": \"lerna exec --parallel 'BABEL_ENV=build babel src --out-dir dist --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments'\"\n  }\n}\n```\n\n4. Last and easiest option is just add `--root-mode=upward` option to the build command which allows to resolve babel config upward from the current root. In this case build command looks like:\n\n```json\n{\n  \"scripts\": {\n    \"build\": \"lerna exec --parallel 'BABEL_ENV=build babel --root-mode upward src --out-dir dist --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments'\"\n  }\n}\n```\n\n#### Checking types\n\n[@babel/plugin-transform-typescript](https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-typescript) does not perform type-check for it's input. However, it could be checked with native `typescript` compiler (`tsc`). It should be run with option `noEmit` for checking types only without emitting any code.\n\nLet's create minimal required `tsconfig.json` in the root of monorepo:\n\n```json\n{\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"strict\": true,\n    \"jsx\": \"react\",\n    \"target\": \"esnext\",\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"esModuleInterop\": true,\n    \"rootDir\": \"./\",\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"*\": [\"node_modules\", \"packages\"]\n    }\n  },\n  \"include\": [\"packages\"],\n  \"exclude\": [\"node_modules\"]\n}\n```\n\nand put it in `prebuild` step to run type checks automatically prior each build\n\n```json\n{\n  \"scripts\": {\n    \"prebuild\": \"tsc\"\n  }\n}\n```\n\n### Peer dependencies\n\nLerna does not have ability to add peer dependency for packages. Nevertheless, it can be done with yarn workspaces - all we need is just add workspaces definition to the root `package.json`\n\n```json\n{\n  \"workspaces\": [\"packages/*\"]\n}\n```\n\nIn our case `react`, as well as `styled-components`, are defined as peerDependencies as all our packages will have them, however we don't want to have plenty of dependencies on each package installed separately.\n\nAs we decided to set `react` and `styled-components` as peer dependency, we still should have them, and associated types definitions for typescript, installed in our `node_modules`. So let's add them as `devDependency` to the root of monorepo:\n\n```bash\nyarn add -DW react @types/react styled-components\n```\n\n### Static code analyser\n\nHaving typescript for types checking could protect us from creating plenty of mistakes and save a lot of time for writing basic unit tests related to incorrect input data. However, it won't protect us from writing over-complicated, unreadable, or even hacky code. Even more, it won't protect us from using incorrect or unsupported CSS rules, would it be CSS, SCSS or CSS-in-JS.\n\n#### @typescript-eslint\n\n<p align=\"center\">\n  <a href=\"https://github.com/typescript-eslint/typescript-eslint\">\n    <img alt=\"tslint\" src=\"https://eslint.org/assets/img/logo.svg\" width=\"150\">\n  </a>\n</p>\n\nDue to tslint deprecation plan in 2019, `@typescript-eslint` is going to be used as standard stacic code analyzer.\n\nLet's add all required packages as devDependency in the root of our monorepo:\n\n```bash\nyarn add -DW eslint eslint-plugin-react @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-import\n```\n\nand create simple config file for it `.eslintrc.js`:\n\n```javascript\nmodule.exports = {\n  env: {\n    node: true,\n    browser: true,\n    jest: true,\n  },\n  parser: '@typescript-eslint/parser',\n  extends: [\n    'eslint:recommended',\n    'plugin:react/recommended',\n    'plugin:@typescript-eslint/recommended',\n    'prettier/@typescript-eslint',\n    'plugin:import/errors',\n    'plugin:import/warnings',\n    'plugin:import/typescript',\n  ],\n  parserOptions: {\n    ecmaVersion: 2018,\n    sourceType: 'module',\n    ecmaFeatures: {\n      jsx: true,\n    },\n  },\n  settings: {\n    react: {\n      version: 'detect',\n    },\n  },\n  rules: {\n    'react/prop-types': 'off',\n    'import/no-extraneous-dependencies': ['error'],\n  },\n};\n```\n\nand new script in package.json for linting `*.ts` files:\n\n```json\n{\n  \"scripts\": {\n    \"lint:ts\": \"eslint 'packages/**/*.ts{,x}'\"\n  }\n}\n```\n\nNow static code analyzer could be run with simple yarn lint:ts command.\n\n#### ~~Tslint~~\n\n<p align=\"center\">\n  <a href=\"https://palantir.github.io/tslint/\">\n    <img alt=\"tslint\" src=\"https://www.feram.io/images/modules/tslint.svg\" width=\"150\">\n  </a>\n</p>\n\n~~The easiest solution for automating such checks is using `tslint` for static code analyzing.~~\n\n~~Let's install it as devDependency in the root of our monorepo:~~\n\n```bash\nyarn add -DW tslint tslint-react\n```\n\n~~and create simple config file for it `tslint.json`:~~\n\n```json\n{\n  \"extends\": [\"tslint:latest\", \"tslint-react\"],\n  \"rules\": {\n    \"semicolon\": \"single\"\n  }\n}\n```\n\n~~and new script in package.json for linting `*.ts` files:~~\n\n```json\n{\n  \"scripts\": {\n    \"lint:ts\": \"tslint 'packages/**/*.ts{,x}'\"\n  }\n}\n```\n\n~~Now static code analyzer could be run with simple `yarn lint:ts` command.~~\n\n#### Stylelint\n\n<p align=\"center\">\n  <a href=\"https://stylelint.io/\">\n    <img alt=\"stylelint\" src=\"https://stylelint.io/_/src/components/DefaultHeadMeta/favicon.7f672624abe02127db4972965ea73002.ico\" width=\"150\">\n  </a>\n</p>\n\nLet's use `stylelint` for improving our CSS styles quality and readability. It could be easily used for analyzing CSS-in-JS as well as with simple CSS or SCSS files.\n\nInstallation and configuration process as simple as with `tslint`:\n\n```bash\nyarn add -DW stylelint stylelint-processor-styled-components stylelint-config-styled-components stylelint-config-standard\n```\n\nCreate simple config file for it `tslint.json`:\n\n```json\n{\n  \"processors\": [\"stylelint-processor-styled-components\"],\n  \"extends\": [\"stylelint-config-standard\", \"stylelint-config-styled-components\"]\n}\n```\n\nand new script in package.json for linting `*.ts` files:\n\n```json\n{\n  \"scripts\": {\n    \"lint:css\": \"stylelint 'packages/**/*.ts{,x}'\"\n  }\n}\n```\n\nNow static code analyzer could be run with simple `yarn lint:css` command.\n\n#### All together\n\nFor now we have `lint:ts` for checking typescript code quality and `lint:css` for CSS, however, they are still separated commands and it would be uncomfortable to run them separately all the time. Let's group them in one unified `lint` command and run it with `npm-run-al`:\n\n```bash\nyarn add -DW npm-run-all\n```\n\nand new script in the root `package.json`:\n\n```json\n{\n  \"scripts\": {\n    \"lint\": \"run-p -c lint:*\",\n    \"lint:ts\": \"tslint 'packages/**/*.ts{,x}'\",\n    \"lint:css\": \"stylelint 'packages/**/*.ts{,x}'\"\n  }\n}\n```\n\n**Note:** `run-p -c` allows to run all `lint:*` commands even if one of them failed. It's useful in case of separated static code analyzer steps, as after one run we have output from `tslint` and `stylelint`, instead of only first failed.\n\n### Code formatting\n\n<p align=\"center\">\n  <a href=\"https://palantir.github.io/tslint/\">\n    <img alt=\"prettier\" src=\"https://raw.githubusercontent.com/prettier/prettier-logo/master/images/prettier-banner-light.png\" width=\"150\">\n  </a>\n</p>\n\nFor now we have `typescript` for static types checking, `eslint` and `stylelint` for static code analyzing. Still, we could write unreadable or not well formatted code. We could avoid all issues relate to code formatting with `prettier`. It will automatically format our code according to predefined standards. Moreover, it will fix some issues reported by `eslint`.\n\nAs usual, installation and configuration is very simple:\n\n```bash\nyarn add -DW prettier eslint-plugin-prettier eslint-config-prettier\n```\n\nNext is needed is `.prettierrc`:\n\n```json\n{\n  \"printWidth\": 80,\n  \"tabWidth\": 2,\n  \"singleQuote\": true,\n  \"trailingComma\": \"all\",\n  \"arrowParens\": \"always\"\n}\n```\n\nand integration with `eslint`, as both of the tools have common rules (like tabWidth, trailingComma, etc). Next lines should be changed in the `.eslintrc.js` to make it work with prettier:\n\n```javascript\nmodule.exports = {\n  // existing eslint configuration\n  extends: [\n    'eslint:recommended',\n    'plugin:react/recommended',\n    'plugin:@typescript-eslint/recommended',\n    'prettier/@typescript-eslint',\n    'plugin:prettier/recommended',\n    'plugin:import/errors',\n    'plugin:import/warnings',\n    'plugin:import/typescript',\n  ],\n  // existing eslint configuration\n};\n```\n\nImportant note is `quotemark` rule. Because of `jsx` usage we have to override default recommended rules which requires to have single quotemark everywhere.\n\nLast but not least, let's add script to the root `package.json` for automatic code formatting based on defined above rules:\n\n```json\n{\n  \"scripts\": {\n    \"fix\": \"yarn lint:ts --fix\"\n  }\n}\n```\n\n### Testing\n\n<p align=\"center\">\n  <a href=\"https://jestjs.io/\">\n    <img alt=\"jest\" src=\"https://camo.githubusercontent.com/f6414ee20933d5fb8b06dc32ed38c8aa175da559/687474703a2f2f64702e68616e6c6f6e2e696f2f3331337933753244307033382f6a6573742e706e67\" width=\"150\">\n  </a>\n</p>\n\nFor now we have TypeScript for checking types, `tslint` and `stylelint` for static code quality analyzing. Last, but not least part is testing. Let's use `jest` as test runner and test assertion tool. It has the best support for `react`, including snapshot testing, extensive mocking library, build-in coverage reporting and ability to run tests in different processes. `ts-jest` should be used for running `typescript` code. Installation is also quite simple:\n\n```bash\nyarn add -DW jest ts-jest @types/jest\n```\n\n`jest` could be configured in two ways:\n\n- `yarn jest --init` and answer for all questions\n- manually create config file with minimum required configuration\n\nHere is basic setup from `jest.config.js` in the root of the monorepo\n\n```javascript\nmodule.exports = {\n  clearMocks: true,\n  coverageDirectory: 'coverage',\n  coverageReporters: ['text', 'clover'],\n  coverageThreshold: {\n    global: {\n      branches: 80,\n      functions: 80,\n      lines: 80,\n      statements: 80,\n    },\n  },\n  globals: {\n    'ts-jest': {\n      extends: './babel.config.js',\n    },\n  },\n  moduleFileExtensions: ['ts', 'tsx', 'js'],\n  notify: true,\n  notifyMode: 'always',\n  roots: ['<rootDir>packages'],\n  testMatch: ['**/__tests__/*.+(ts|tsx|js)', '**/*.test.+(ts|tsx|js)'],\n  transform: {\n    '^.+\\\\.(ts|tsx)$': 'ts-jest',\n  },\n};\n```\n\nNotes:\n\n- `ts-jest` could use babel config or pure typescript compiler. In our case we have babel configured, so it could be used with just 1 line in config:\n\n```\n  globals: {\n    'ts-jest': {\n      extends: './babel.config.js',\n    },\n  },\n```\n\n- `coverageThreshold` is protecting us from writing not enough tests and having poor test coverage.\n\nAs soon as we have basic config, it's time to install `enzyme` (and all related libraries) which is extending support for `react`:\n\n```bash\nyarn add -DW enzyme enzyme-adapter-react-16 @types/enzyme @types/enzyme-adapter-react-16\n```\n\nAdd `setupTestFrameworkScriptFile: '<rootDir>jest/setupTests.ts'` into `jest.config.js` file and proper setup for `enzyme` into `jest/setupTests.ts`:\n\n```typescript\nimport Enzyme from 'enzyme';\nimport Adapter from 'enzyme-adapter-react-16';\n\nEnzyme.configure({ adapter: new Adapter() });\n```\n\nNow `jest` is able to render `react` components, however, it will serialize snapshots as pure objects and we want to have it serialized as HTML markup. We could achieve it with proper serializer:\n\n```bash\nyarn add -DW  enzyme-to-json@next\n```\n\nand `snapshotSerializers: ['enzyme-to-json/serializer']` in `jest.config.js.`\n\nWe are almost there, we are able to run tests and create proper snapshots. Nevertheless, we still have issues with `styled-components` - on each change in styles, `styled-components` is creating different class name. Based on it we'll have plenty of false negative tests fails just because of class name is changed. Let's fix it with proper tool\n\n```bash\nyarn add -DW jest-styled-components\n```\n\n`import 'jest-styled-components'` should be added to the `jest/setupTests.ts`.\n\nJust to sum up, `jest.config.js`:\n\n```javascript\nmodule.exports = {\n  clearMocks: true,\n  coverageDirectory: 'coverage',\n  coverageReporters: ['text', 'clover'],\n  coverageThreshold: {\n    global: {\n      branches: 80,\n      functions: 80,\n      lines: 80,\n      statements: 80,\n    },\n  },\n  globals: {\n    'ts-jest': {\n      extends: './babel.config.js',\n    },\n  },\n  moduleFileExtensions: ['ts', 'tsx', 'js'],\n  notify: true,\n  notifyMode: 'always',\n  roots: ['<rootDir>packages'],\n  testMatch: ['**/__tests__/*.+(ts|tsx|js)', '**/*.test.+(ts|tsx|js)'],\n  transform: {\n    '^.+\\\\.(ts|tsx)$': 'ts-jest',\n  },\n  setupTestFrameworkScriptFile: '<rootDir>jest/setupTests.ts',\n  snapshotSerializers: ['enzyme-to-json/serializer'],\n};\n```\n\nThat's it, `jest` is configured and could be run. Let's add `test` to the root `package.json` scripts:\n\n```json\n{\n  \"scripts\": {\n    \"test\": \"jest\"\n  }\n}\n```\n\n### Storybook\n\n<p align=\"center\">\n  <a href=\"https://storybook.js.org/\">\n    <img alt=\"storybook\" src=\"https://camo.githubusercontent.com/34ab12e06afbf839047bf3c19ed3e76082921f85/68747470733a2f2f64337676366c703535716a6171632e636c6f756466726f6e742e6e65742f6974656d732f33783051313531343431317a336c314f326131512f73746f7279626f6f6b732d6f6c642e706e673f582d436c6f75644170702d56697369746f722d49643d643430373439383635383733643762356162333263383038353231353066373426763d6530643332303332\" width=\"150\">\n  </a>\n</p>\n\nWe already able to write code in monorepo with `typescript`, analyze it with `tslint` and `stylelint`, test it with `jest`. However, we still cannot see how our components will look like and we cannot even debug it properly.\n\nThere are plenty of ways how to present react component. Let's go with most famous one - `storybook`. It allows to present separate components and/or group of them as well as testing it in real browsers, and having documentation close to it.\n\n#### Installation\n\nLatest stable version of `storybook@3.4.10` works with `webpack@3`, `babel@^6` and `typescript@^2.7`. As we have latest `@babel@^7` and `typescript@^3` it's better to use `next` version of storybook which has the same set of dependencies as our monorepo, even if it's bleeding edge version.\n\nIf you do it for the first time, you should have `@storybook@cli` installed globally on your machine and init:\n\n```bash\nyarn global add @storybook/cli@next\ngetstorybook\n```\n\nIt will automatically detect project type (react), installs all required packages and create basic configuration folder.\n\n#### Typescript\n\nStill, as we use typescript, we have to install typings for those packages, loader for wepback and needed peerDependencies:\n\n```bash\nyarn add -DW @types/storybook__react @types/storybook__addon-actions @types/storybook__addon-links react-dom webpack awesome-typescript-loader\n```\n\nStorybook inits application as it is javascript based, as we have typescript everywhere, we have to change path resolution for stories in `storybook/config.js` file:\n\n```typescript\nconst req = require.context('../packages', true, /.story.tsx?$/);\n```\n\nLast but not least part is `webpack.config.js` inside `storybook` folder, just create it with next content:\n\n```javascript\nmodule.exports = (baseConfig, env, config) => {\n  config.module.rules.push({\n    test: /\\.(ts|tsx)$/,\n    loader: require.resolve('awesome-typescript-loader'),\n  });\n  config.resolve.extensions.push('.ts', '.tsx');\n  return config;\n};\n```\n\nand associated configuration part in `tsconfig.json` for `awesome-typescript-loader`:\n\n```json\n{\n  \"awesomeTypescriptLoaderOptions\": {\n    \"useBabel\": true,\n    \"babelCore\": \"@babel/core\"\n  }\n}\n```\n\nConfiguration part is ready, we could start storybook with `yarn storybook` command.\n\n#### @typescript-eslint\n\nAs soon as we add `storybook` to our devDependencies and run `yarn lint:ts` we will get an error from `eslint`:\n\n```bash\n{path_to_repository}/monorepo/packages/input/src/Input.story.tsx\n  1:1  error  '@storybook/addon-knobs' should be listed in the project's dependencies. Run 'npm i -S @storybook/addon-knobs' to add it  import/no-extraneous-dependencies\n  2:1  error  '@storybook/react' should be listed in the project's dependencies. Run 'npm i -S @storybook/react' to add it              import/no-extraneous-dependencies\n```\n\nThis means that we need to configure `import/no-extraneous-dependencies` to be able to work with development dependecies which are provided in `package.json` in root of monorepository.\n\nLet's add override to `.eslintrc.js`:\n\n```javascript\n// .eslintrc.js\nmodeule.exports = {\n  // existing eslint configuration\n  overrides: [\n    {\n      files: ['*.{test,spec,story}.ts{,x}'],\n      rules: {\n        'import/no-extraneous-dependencies': ['error', { packageDir: './' }],\n      },\n    },\n  ],\n};\n```\n\nThis allow linter to check `story`, `test` and `spec` files with extended list of development dependencies, which is provided by package.json in root of monorepository.\n\n#### ~~Tslint~~\n\n~~As soon as we add `storybook` to our devDependencies and run `yarn lint:ts` we will get an error from `tslint`:~~\n\n```\nERROR: Module '@storybook/react' is not listed as dependency in package.json\n```\n\n~~The reason is obvious, we use package which is installed as devDependency in our source code (in the story file). Unfortunately there is no options like override for specific path or files. It could be done by splitting `lint-ts` command into two separated for production code (which will be shipped as packages) and for test code (storybook, tests, etc).~~\n\n~~Let's create config for `tslint` for production phase, called `tslint.prod.json`:~~\n\n```json\n{\n  \"extends\": [\"./tslint.json\"],\n  \"rules\": {\n    \"no-implicit-dependencies\": true\n  }\n}\n```\n\n~~Another config for the test phase called `tslint.test.json`:~~\n\n```json\n{\n  \"extends\": [\"./tslint.json\"],\n  \"rules\": {\n    \"no-implicit-dependencies\": [false, \"dev\"]\n  }\n}\n```\n\n~~`\"no-implicit-dependencies\": false` into `tslint.json` to disable this rule by default. This one is need to fix issues with IDEs as by default they use `tslint.json` for all files, whether it test or production code.~~\n\n~~Last, but not least, scripts in the root `package.json` have to be adjusted:~~\n\n```json\n{\n  \"scripts\": {\n    \"fix\": \"run-p -c lint:ts-* --fix\",\n    \"lint:ts\": \"run-p -c lint:ts-*\",\n    \"lint:ts-prod\": \"tslint --config tslint.prod.json 'packages/**/*.ts{,x}' --exclude '**/*.{test,story}.ts{,x}'\",\n    \"lint:ts-test\": \"tslint --config tslint.test.json 'packages/**/*.{test,story}.ts{,x}'\"\n  }\n}\n```\n\n#### Addons\n\nStorybook allows to pass any props to the react component without rebuilding stories, just through UI interface. To do it, we have to add one more addons - [`@storybook/addon-knobs`](https://github.com/storybooks/storybook/tree/master/addons/knobs)\n\n```bash\nyarn add -DW @storybook/addon-knobs@next @types/storybook__addon-knobs moment\n```\n\n**NOTE**: moment has to be installed because of wrong peerDependencies management on `storybook` and `react-datetime` level.\n\nNext step is to add `import '@storybook/addon-knobs/register';` to the `storybook/addons.js` and modify `storybook/config.js` to have global decorator for each story:\n\n```javascript\nimport { configure, addDecorator } from '@storybook/react';\nimport { withKnobs } from '@storybook/addon-knobs';\n\nconst req = require.context('../packages', true, /.story.tsx?$/);\nfunction loadStories() {\n  addDecorator(withKnobs);\n  req.keys().forEach((filename) => req(filename));\n}\n\nconfigure(loadStories, module);\n```\n\nNow `knobs` could be used in the stories.\n\n### Final build\n\nAs we already have build command as well as code formatting and static code analyzing tools in place, it's time to use them all together in the build process:\n\n```json\n{\n  \"scripts\": {\n    \"prebuild\": \"run-p tsc lint test\",\n    \"build\": \"lerna exec --parallel 'BABEL_ENV=build babel src --root-mode upward --out-dir dist --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments'\",\n    \"lint:css\": \"stylelint 'packages/**/*.ts{,x}'\",\n    \"lint:ts\": \"run-p -c lint:ts-*\",\n    \"lint:ts-prod\": \"tslint --config tslint.prod.json 'packages/**/*.ts{,x}' --exclude '**/*.{test,story}.ts{,x}'\",\n    \"lint:ts-test\": \"tslint --config tslint.test.json 'packages/**/*.{test,story}.ts{,x}'\",\n    \"lint\": \"run-p -c lint:*\",\n    \"test\": \"jest\",\n    \"tsc\": \"tsc\"\n  }\n}\n```\n\nAs soon as we run `yarn build` command, `yarn` automatically will run `tsc` for type checks, `tslint` for code quality analyzing and `test` on each of packages in the monorepo.\n\nIf they succeed, `build` will proceed and prepare all packages for publishing.\n\n### Committing your work\n\nLet's use conventional commit for committing our work for having consistent commit messages across the monorepo and as a benefit, proper version creation per package basing on [conventional-commit](https://github.com/lerna/lerna/tree/master/commands/version#--conventional-commits) approach.\n\nLet's install required packages:\n\n```bash\nyarn add -DW commitizen cz-lerna-changelog@^2.0.0\n```\n\n[cz-lerna-changelog](https://github.com/atlassian/cz-lerna-changelog) should be installed with version `^2.0.0` as it supports latest `lerna`\n\nConfiguration is quite simple, just add next line to the root `package.json` file:\n\n```json\n{\n  \"config\": {\n    \"commitizen\": {\n      \"path\": \"./node_modules/cz-lerna-changelog\"\n    }\n  }\n}\n```\n\nand simple alias for commit command:\n\n```json\n{\n  \"scripts\": {\n    \"commit\": \"git-cz\"\n  }\n}\n```\n\nNow it's time to test it, just change something in one of the packages, stage changes with git and run `yarn commit`:\n\n```bash\n? Select the type of change that you're committing:\n❯ feat:     ✨  A new feature (note: this will indicate a release)\n  fix:      🛠  A bug fix (note: this will indicate a release)\n  docs:     Documentation only changes\n  style:    Changes that do not affect the meaning of the code\n            (white-space, formatting, missing semi-colons, etc)\n  refactor: A code change that neither fixes a bug nor adds a feature\n  perf:     A code change that improves performance\n```\n\n### Package publishing\n\nAs described earlier, `lerna` is used for publishing packages. It could be configured quite easily with next lines in the `lerna.json`:\n\n```json\n{\n  \"command\": {\n    \"publish\": {\n      \"conventionalCommits\": true,\n      \"registry\": \"http://localhost:4873\",\n      \"access\": \"public\",\n      \"npmClient\": \"yarn\",\n      \"allowBranch\": [\"master\", \"feature/*\"]\n    }\n  }\n}\n```\n\nThe config is self descriptive, however, the most important parts are:\n\n- `registry` - specifies where do we want to publish our packages\n- `conventionalCommits` - allows us to use conventional commits for determining new versions\n\nAll other options could be found on the official `lerna` documentation.\n\nNow we could add simple alias to the our scripts for having `release` command there:\n\n```json\n{\n  \"scripts\": {\n    \"prerelease\": \"yarn build\",\n    \"release\": \"lerna publish\"\n  }\n}\n```\n\nThat's it. The key part is configured and ready to be used. Time to test it with real packages.\n\n## First package\n\nLet's init first simple package which will be just Input with optional label for it:\n\n```\n$ mkdir packages/input && cd packages/input\n$ yarn init\nyarn init v1.7.0\nquestion name (input): @taxi/input\nquestion version (1.0.0): 0.0.0\nquestion description: Input component\nquestion entry point (index.js): /dist/index.ts\nquestion repository url:\nquestion author: chef\nquestion license (MIT):\nquestion private: true\nsuccess Saved package.json\nDone in 85.84s.\n```\n\nand add `react` and `styled-components` as peerDependencies:\n\n```bash\nyarn workspace @taxi/input add -P react styled-components\n```\n\n### Development\n\nLet's create simple input with optional label:\n\n```typescript\nimport * as React from 'react';\nimport styled from 'styled-components';\n\nexport interface LabelProps {\n  labelWidth?: number;\n}\n\nexport interface InputWithLabelProps extends LabelProps {\n  id?: string;\n  label?: string;\n}\n\nexport interface InputWithoutLabelProps extends LabelProps {\n  id: string;\n  label: string;\n}\n\nexport type InputLabelProps = InputWithLabelProps | InputWithoutLabelProps;\n\nexport interface InputProps {\n  name?: string;\n  type?: string;\n}\n\nconst Wrapper = styled.div`\n  display: flex;\n  margin: 10px;\n`;\n\nconst Label = styled<LabelProps, 'label'>('label')`\n  margin-right: 10px;\n  font-weight: bold;\n  width: ${({ labelWidth = 100 }) => labelWidth}px;\n`;\n\nconst NativeInput = styled.input`\n  width: 100%;\n`;\n\nexport const Input: React.SFC<InputProps & InputLabelProps> = ({\n  label,\n  id,\n  labelWidth,\n  ...rest\n}) => (\n  <Wrapper>\n    {label && (\n      <Label labelWidth={labelWidth} htmlFor={id}>\n        {label}:\n      </Label>\n    )}\n    <NativeInput id={id} {...rest} />\n  </Wrapper>\n);\n\nInput.defaultProps = {\n  type: 'text',\n};\n```\n\n### Storybook\n\n`storybook` is configured, so it's time to create first story and test first package as well as `storybook` and `typescript` integration. Just create `Input.story.tsx` inside `input` package.\n\n```typescript\nimport { text } from '@storybook/addon-knobs';\nimport { storiesOf } from '@storybook/react';\nimport * as React from 'react';\n\nimport { Input } from './Input';\n\nstoriesOf('Input', module)\n  .add('default', () => <Input />)\n  .add('with label', () => (\n    <Input id=\"test\" label={text('Label', 'Username')} />\n  ))\n  .add('with label and type', () => (\n    <Input\n      id=\"test\"\n      label={text('Label', 'Username')}\n      type={text('Type', 'text')}\n    />\n  ));\n```\n\nand run `yarn storybook`. When the build process is finished, storybook will be accessible under http://localhost:6006\n\n### Testing\n\n`jest` is configured and ready to be used. Let's create simple snapshot tests for our package:\n\n```typescript\nimport { mount } from 'enzyme';\nimport * as React from 'react';\n\nimport { Input } from './Input';\n\ndescribe('Input', () => {\n  test('should match snapshot and styles for default props', () => {\n    expect(mount(<Input />)).toMatchSnapshot();\n  });\n\n  test('should match snapshot with label', () => {\n    expect(mount(<Input id=\"test\" label=\"Name\" />)).toMatchSnapshot();\n  });\n});\n```\n\nAll tests could be run with simple command:\n\n```bash\nyarn test\n```\n\nNow we have a chance to check how our integration of `jest` and `jest-styled-components` works. Just open created snapshot and check that classnames are replaced with `c0`, `c1`, etc:\n\n```\nexports[`Input should match snapshot and styles for default props 1`] = `\n.c0 {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  margin: 10px;\n}\n\n.c1 {\n  width: 100%;\n}\n```\n\n### Build\n\nIt's time to build our package. Simply run\n\n```bash\nyarn build\n```\n\nand we should have `packages/input/dist` folder with all compiled files. The most important one is `packages/input/dist/Input.js` which has:\n\n```javascript\nconst Input = ({ label, id, labelWidth, ...rest }) =>\n  React.createElement(\n    Wrapper,\n    null,\n    label &&\n      React.createElement(\n        Label,\n        {\n          labelWidth: labelWidth,\n          htmlFor: id,\n        },\n        label,\n        ':',\n      ),\n    React.createElement(\n      NativeInput,\n      _extends(\n        {\n          id: id,\n        },\n        rest,\n      ),\n    ),\n  );\n```\n\n### Publish\n\nIt's time to publish our first package, just hit `yarn release` and answer `Yes` for publishing question. The result should be like:\n\n```bash\n$ lerna publish\nlerna notice cli v3.4.0\nlerna info versioning independent\nlerna info Verifying npm credentials\nlerna info Looking for changed packages since initial commit.\n\nChanges:\n - @taxi/input: 0.0.0 => 0.1.0\n\n? Are you sure you want to publish these packages? Yes\nlerna info git Pushing tags...\nlerna info publish Publishing packages to npm...\nlerna WARN EREGISTRY Registry \"http://localhost:4873\" does not support `npm access ls-packages`, skipping permission checks...\nlerna WARN ENOLICENSE Packages @taxi/input, @taxi/login-form are missing a license\nlerna notice\nlerna notice 📦  @taxi/input@0.1.0\nlerna notice === Tarball Contents ===\nlerna notice 640B  package.json\nlerna notice 358B  CHANGELOG.md\nlerna notice 389B  dist/index.js\nlerna notice 176B  dist/index.js.map\nlerna notice 1.8kB dist/Input.js\nlerna notice 1.9kB dist/Input.js.map\nlerna notice === Tarball Details ===\nlerna notice name:          @taxi/input\nlerna notice version:       0.1.0\nlerna notice filename:      taxi-input-0.1.0.tgz\nlerna notice package size:  2.3 kB\nlerna notice unpacked size: 5.3 kB\nlerna notice shasum:        8685cb61ee263c3af0b73d1daa2295f35eaa04d8\nlerna notice integrity:     sha512-y5o/D+DevV5oS[...]P2S2XqeRi89jA==\nlerna notice total files:   6\nlerna info published @taxi/input 0.1.0\nSuccessfully published:\n - @taxi/input@0.1.0\nlerna success published 1 package\n```\n\n`Lerna` says that package was published successfully. Now we could check it with `yarn info` or through web interface for our local npm registry (`http://localhost:4873`):\n\n```bash\n$ yarn info @taxi/input\nyarn info v1.10.1\n{ name: '@taxi/input',\n  versions:\n   [ '0.1.0' ],\n  'dist-tags':\n   { latest: '0.1.0' },\n  version: '0.1.0',\n  description: 'Input component',\n  ...\n  }\nDone in 1.33s.\n```\n\nMoreover, `lerna` should create proper tags in our repository associated with released packages and versions:\n\n```bash\n$ git tag\n@taxi/input@0.1.0\n```\n\nLast, but not least, let's check that proper `Changelog` was created for our package:\n\n```bash\n$ cat packages/input/CHANGELOG.md\n# Change Log\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n<a name=\"0.1.0\"></a>\n# 0.1.0 (2018-10-14)\n\n\n### Features\n\n* **Input:** add default labelWidth ([8302608](https://github.com/serhii-havrylenko/monorepo-babel-ts-lerna-starter/commit/8302608))\n```\n\nNow we have first package successfully released, what's left? Second package which is dependant on our `@taxi/input` package is left. Integration with `lerna` would stay the same, simple as it is, however, it would requires some magic for making `storybook`, `jest` and `tslint` works with dependent packages and proper modules resolutions without rebuilding them all the time. Plus, as a bonus we'll generate types declarations for our packages and include them as a part of final build.\n\nMore details will be in the next article.\n\n## Multiple packages\n\nAs everyone knows, the main goal of the monorepo is to have multiple packages inside one repository for easily solving dependencies between them and simple release process.\n\nLet's create second package which is dependant on our `@taxi/input` and check how our tools works with it.\n\n### Development\n\nJust create second package in the same way as the first one. In our example it would be `@taxi/login-form` with next content:\n\n```typescript\nimport { Input } from '@taxi/input';\nimport * as React from 'react';\nimport styled from 'styled-components';\n\nconst Wrapper = styled.div`\n  display: flex;\n  flex-direction: column;\n  margin: 10px;\n`;\n\nconst ButtonsWrapper = styled.div`\n  text-align: right;\n`;\n\nexport interface LoginFormProps {\n  onClick?: () => void;\n}\n\nexport const LoginForm: React.SFC<LoginFormProps> = ({ onClick }) => (\n  <Wrapper>\n    <Input id=\"name\" label=\"Name\" />\n    <Input id=\"password\" label=\"Password\" />\n\n    <ButtonsWrapper>\n      <button onClick={onClick}>Log in</button>\n    </ButtonsWrapper>\n  </Wrapper>\n);\n```\n\nNow we could add `@taxi/input` to the list of dependencies. This could be achieved easily with next command:\n\n```bash\nyarn lerna add @taxi/input --scope=@taxi/login-form\n```\n\nAs soon as we have it, it's time to run `tsc` and check what `typescript` thinks about our code:\n\n```bash\n$ yarn tsc\nyarn run v1.10.1\n$ tsc\npackages/login-form/src/LoginForm.tsx:1:23 - error TS2307: Cannot find module '@taxi/input'.\n\n1 import { Input } from '@taxi/input';\n                        ~~~~~~~~~~~~~\nerror Command failed with exit code 1.\n```\n\nIt happens because in the `package.json` file for `@taxi/input` package we have `\"main\": \"dist/index.js\"` which is pointing to the build version of the package and we have not run `build` command. So, let's build our packages and check `tsc` again:\n\n```bash\n$ yarn tsc\nyarn run v1.10.1\n$ tsc\npackages/login-form/src/LoginForm.tsx:1:23 - error TS7016: Could not find a declaration file for module '@taxi/input'. 'monorepo-babel-ts/packages/input/dist/index.js' implicitly has an 'any' type.\n  Try `npm install @types/taxi__input` if it exists or add a new declaration (.d.ts) file containing `declare module '@taxi/input';`\n\n1 import { Input } from '@taxi/input';\n                        ~~~~~~~~~~~~~\nerror Command failed with exit code 1.\n```\n\nNow `typescript` could find our package, however it doesn't know anything about typings for that module. It happens because we built our package with `babel` and it cannot create declaration files.\n\n#### Declarations generation\n\nLet's configure `tsc` to generate types declarations for our modules. As a first step, we have to move `login-form` package to the different folder (we would need to have only compilable with `tsc` packages in the `packages` directory).\n\nWe would need:\n\n`tsconfig.build.json` in the root of monorepo with:\n\n```json\n{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": false,\n    \"emitDeclarationOnly\": true,\n    \"declaration\": true\n  },\n  \"include\": [],\n  \"exclude\": [\"**/*.story.*\", \"**/*.test.*\", \"dist\"]\n}\n```\n\nWhere we specify that we need to emit declarations only and exclude test, stories and dist folder.\n\nNext we would need `tsconfig.build.json` inside the each of our packages with:\n\n```json\n{\n  \"extends\": \"../../tsconfig.build.json\",\n  \"compilerOptions\": {\n    \"declarationDir\": \"./dist\",\n    \"rootDir\": \"./src\",\n    \"baseUrl\": \"./\"\n  },\n  \"include\": [\"./src\"]\n}\n```\n\nHere we would specify from where we would like to take files for generating declarations and where we would like to put them.\n\nNow we would need script inside the root of monorepo for generating declarations:\n\n```json\n{\n  \"scripts\": {\n    \"build:declarations\": \"lerna exec --parallel 'tsc --project ./tsconfig.build.json'\",\n    \"postbuild\": \"yarn build:declarations\"\n  }\n}\n```\n\nTime to test it:\n\n```bash\n$ yarn build:declarations\nyarn run v1.10.1\n$ lerna exec --parallel 'tsc --project ./tsconfig.build.json'\nlerna notice cli v3.4.0\nlerna info versioning independent\nlerna info Executing command in 1 package: \"tsc --project ./tsconfig.build.json\"\nlerna success exec Executed command in 1 package: \"tsc --project ./tsconfig.build.json\"\n```\n\nAs the result we should have `*.d.ts` files generated in the dist folder:\n\n```bash\n$ find packages/input/dist/ -name '*.d.ts'\npackages/input/dist/Input.d.ts\npackages/input/dist/index.d.ts\n```\n\nNow we could check that `@taxi/login-form` works as well, just return it back to the `packages` directory and check that `tsc` works now.\n\n```bash\n$ yarn tsc\nyarn run v1.10.1\n$ tsc\nDone in 4.22s.\n```\n\n#### @typescript-eslint\n\nAs soon as we generate declarations and run `eslitn` we would have errors like:\n\n```bash\n{path_to_repository}/monorepo/packages/input/dist/Input.d.ts\n   3:3   error  Delete `··`                                                                     prettier/prettier\n   6:3   error  Delete `··`                                                                     prettier/prettier\n   7:1   error  Delete `··`                                                                     prettier/prettier\n  10:3   error  Delete `··`                                                                     prettier/prettier\n  11:1   error  Delete `··`                                                                     prettier/prettier\n  13:38  error  Replace `·InputWithLabelProps` with `⏎··|·InputWithLabelProps⏎·`                prettier/prettier\n  15:1   error  Delete `··`                                                                     prettier/prettier\n  16:3   error  Delete `··`                                                                     prettier/prettier\n  18:53  error  Replace `InputProps·&·InputLabelProps` with `⏎··InputProps·&·InputLabelProps⏎`  prettier/prettier\n```\n\nIt happens because `eslitn` tries to validate `*d.ts` files as well.\n\nLet's add `.eslintignore` configuration with list of files and directories which should be never linted:\n\n```\ndist/\n*.d.ts\n```\n\nNow if we run `yarn lint:ts` we won't have any errors related to `.d.ts` files.\n\n#### ~~Tslint~~\n\n~~As soon as we generate declarations and run `tslint` we would have errors like:~~\n\n```\nERROR: packages/input/dist/Input.d.ts[13, 38]: Replace `·InputWithLabelProps` with `⏎··|·InputWithLabelProps⏎·`\nERROR: packages/input/dist/Input.d.ts[15, 3]: Delete `··`\nERROR: packages/input/dist/Input.d.ts[16, 1]: Delete `··`\n```\n\n~~It happens because `tslint` tries to validate `*d.ts` files as well. Let's add the to the ignore. With latest version of `tslint` we could do it in configuration file, so:~~\n\n~~1. `tslint.prod.json`~~\n\n```json\n{\n  \"linterOptions\": {\n    \"exclude\": [\"**/*.d.ts\", \"**/*.{test,story}.ts{,x}\"]\n  }\n}\n```\n\n~~2. `tslint.test.json`~~\n\n```json\n{\n  \"linterOptions\": {\n    \"exclude\": [\"**/*.d.ts\"]\n  }\n}\n```\n\n~~Now if we run `yarn lint:ts` we won't have any errors related to `.d.ts` files.~~\n\n#### Drawbacks\n\nWe are able to generate declarations for all packages, run `storybook` and `tests`, however, as soon as we change `@taxi/input` we would not see any changes in the `storybook` for `@taxi/login-form` because we still would use previously built version. To see these changes we would need to rebuild packages one more time. The same applies to the `jest` runs.\n\nThis approach looks not so cool if each change in one of the packages would require constant rebuild. Lucky we have better option how to fix this issues. More details in the next paragraphs.\n\n### Typescript\n\nFirstly, let's remove all `dist` folders inside our packages to have clean code only. On this stage `tsc` should still fail. Now we could extend `tsconfig.json` with:\n\n```json\n{\n  \"compilerOptions\": {\n    \"paths\": {\n      \"@taxi/*\": [\"packages/*/src\"],\n      \"*\": [\"node_modules\", \"packages\"]\n    }\n  }\n}\n```\n\n`\"@taxi/*\": [\"packages/*/src\"]` tells to `tsc` where to search for `@taxi/` packages. In our case we would like to search them in `packages/*/src` folders as there we have our source code.\n\nNow we could run `tsc` and it would finish successfully without any errors like we had earlier.\n\n### Storybook\n\nAs `storybook` is using `webpack` with `awesome-typescript-loader` and `babel` integration, as soon as we start storybook we would get next errors:\n\n```bash\nERROR in ./packages/login-form/src/LoginForm.tsx\nModule not found: Error: Can't resolve '@taxi/input' in 'monorepo-babel-ts/packages/login-form/src'\n@ ./packages/login-form/src/LoginForm.tsx 8:13-35\n```\n\nIt happens even when `tsc` could find those modules. The reason of this is simple: `tsc` checks files, `babel` transforms them and tries to execute, and it doesn't know anything about `@taxi/input` as `main` still points to the `dist` folder.\n\nHowever, we could override it with aliases for `webpack`. It could be done in two ways:\n\n1. Manual one, in this case we'll have to define each package which we would like to have in `webpack.config.resolve.alias`. This approach is simple, but it introduces potential issues in the future when someone could forget about aliases or introduces wrong one.\n2. Automated one with next info in the `storybook/webpack.config.js`\n\n```javascript\nconst path = require('path');\nconst { lstatSync, readdirSync } = require('fs');\n\nconst basePath = path.resolve(__dirname, '../', 'packages');\nconst packages = readdirSync(basePath).filter((name) =>\n  lstatSync(path.join(basePath, name)).isDirectory(),\n);\n\nmodule.exports = (baseConfig, env, config) => {\n  config.module.rules.push({\n    test: /\\.(ts|tsx)$/,\n    loader: require.resolve('awesome-typescript-loader'),\n  });\n  config.resolve.extensions.push('.ts', '.tsx');\n  Object.assign(config.resolve.alias, {\n    ...packages.reduce(\n      (acc, name) => ({\n        ...acc,\n        [`@taxi/${name}`]: path.join(basePath, name, 'src'),\n      }),\n      {},\n    ),\n  });\n\n  return config;\n};\n```\n\nThis code is rather simple and self explanatory. The most important part is in reducer for building aliases:\n\n```javascript\npackages.reduce(\n  (acc, name) => ({\n    ...acc,\n    [`@taxi/${name}`]: path.join(basePath, name, 'src'),\n  }),\n  {},\n);\n```\n\nWith this reducer we would have automatically generated list of our packages from `packages` directory.\n\nNow we could start storybook and check that it works, moreover, if we change `@taxi/input` and check stories for `@taxi/login-form` they would have changes immediately without even building packages.\n\n### Jest\n\nWe have `tsc` and `storybook` working, however, if we run `jest` it would fail with:\n\n```bash\n FAIL  packages/login-form/src/LoginForm.test.tsx\n  ● Test suite failed to run\n\n    Cannot find module '@taxi/input' from 'LoginForm.test.tsx'\n```\n\nIt happens because `jest` doesn't tolerate `tsconfig.json`, `webpack` aliases or even `babel-webpack-aliases`. However, this problem could be solved with simple line in `jest.config.js`:\n\n```javascript\n{\n  moduleNameMapper: {\n    '@taxi/(.+)$': '<rootDir>packages/$1/src',\n  },\n}\n```\n\n`'@taxi/(.+)$': '<rootDir>packages/$1/src` will tell jest where to find source code for `@taxi/` packages and again it points to the `src` instead of `dist`.\n\nNow we could run `yarn test` and it will work as expected without even building packages.\n\n## Final words\n\nThe goal of the article was to configure monorepo with `lerna`, `typescript`, `babel`, `tslint`, `stylelint`, `jest` and `semantic-release` and it was achieved. We do have monorepo with all those tools in place and it's ready for real usage. Packages could be created, developed, tested, presented and published easily with one commands in the root of monorepo.\n\nFor those who doesn't want to use `babel`, but pure `typescript`, changes would be extremely simple - just drop `babel.config.js`, change `awesome-typescript-loader` for using `tsconfig.json` instead of `babel`, `ts-jest` to use it as well and `build` command from `babel` to `tsc` (just replace `emitDeclarationOnly` to `false` in `tsconfig.build.json`) and that's it, `typescript` could be used without `babel`.\n"
  },
  {
    "path": "babel.config.js",
    "content": "module.exports = (api) => {\n  api.cache(true);\n\n  return {\n    presets: [\n      [\n        '@babel/env',\n        {\n          useBuiltIns: 'usage',\n          corejs: 3,\n          targets: {\n            browsers: 'Last 2 Chrome versions, Firefox ESR',\n            node: 'current',\n          },\n        },\n      ],\n      [\n        '@babel/preset-react',\n        {\n          development: process.env.BABEL_ENV !== 'build',\n        },\n      ],\n      '@babel/preset-typescript',\n    ],\n    env: {\n      build: {\n        ignore: [\n          '**/*.test.tsx',\n          '**/*.test.ts',\n          '**/*.story.tsx',\n          '__snapshots__',\n          '__tests__',\n          '__stories__',\n        ],\n      },\n    },\n    ignore: ['node_modules'],\n  };\n};\n"
  },
  {
    "path": "jest/setupTests.ts",
    "content": "import '@testing-library/jest-dom/extend-expect';\n"
  },
  {
    "path": "jest.config.js",
    "content": "module.exports = {\n  clearMocks: true,\n  coverageDirectory: 'coverage',\n  coverageReporters: ['text', 'clover'],\n  coverageThreshold: {\n    global: {\n      branches: 80,\n      functions: 80,\n      lines: 80,\n      statements: 80,\n    },\n  },\n  globals: {\n    'ts-jest': {\n      extends: './babel.config.js',\n    },\n  },\n  moduleFileExtensions: ['ts', 'tsx', 'js'],\n  modulePathIgnorePatterns: ['dist'],\n  moduleNameMapper: {\n    '@taxi/(.+)$': '<rootDir>packages/$1/src',\n  },\n  notify: true,\n  notifyMode: 'always',\n  roots: ['<rootDir>packages'],\n  testMatch: ['**/__tests__/*.+(ts|tsx|js)', '**/*.test.+(ts|tsx|js)'],\n  transform: {\n    '^.+\\\\.(ts|tsx)$': 'ts-jest',\n  },\n  setupFilesAfterEnv: ['<rootDir>jest/setupTests.ts'],\n};\n"
  },
  {
    "path": "lerna.json",
    "content": "{\n  \"packages\": [\"packages/*\"],\n  \"version\": \"independent\",\n  \"useWorkspaces\": true,\n  \"npmClient\": \"yarn\",\n  \"command\": {\n    \"publish\": {\n      \"conventionalCommits\": true,\n      \"registry\": \"http://localhost:4873\",\n      \"access\": \"public\",\n      \"npmClient\": \"yarn\",\n      \"allowBranch\": [\"master\", \"feature/*\"]\n    }\n  }\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"monorepo-ts-babel-lerna\",\n  \"version\": \"0.0.0\",\n  \"workspaces\": [\n    \"packages/*\"\n  ],\n  \"private\": true,\n  \"description\": \"Test monorepo with ts and lerna\",\n  \"scripts\": {\n    \"postinstall\": \"lerna link\",\n    \"build-storybook\": \"build-storybook\",\n    \"prebuild\": \"run-p tsc lint\",\n    \"build\": \"lerna run --parallel 'build:es'\",\n    \"build:old\": \"lerna exec --parallel 'BABEL_ENV=build babel src --root-mode upward --out-dir dist --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments'\",\n    \"postbuild\": \"yarn build:declarations\",\n    \"commit\": \"git-cz\",\n    \"fix\": \"run-p -c 'lint:* --fix'\",\n    \"lint:css\": \"stylelint 'packages/**/*.ts{,x}'\",\n    \"lint:ts\": \"eslint 'packages/**/*.ts{,x}'\",\n    \"lint\": \"run-p -c lint:*\",\n    \"prerelease\": \"yarn build\",\n    \"release\": \"lerna publish\",\n    \"storybook\": \"start-storybook -p 6006\",\n    \"test\": \"jest\",\n    \"tsc\": \"tsc\",\n    \"build:declarations\": \"lerna run --parallel 'build:declaration'\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"test\"\n  },\n  \"author\": \"Serhii Havrylenko\",\n  \"license\": \"ISC\",\n  \"resolutions\": {\n    \"babel-core\": \"^7.0.0-bridge.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/cli\": \"^7.6.0\",\n    \"@babel/core\": \"^7.6.0\",\n    \"@babel/preset-env\": \"^7.6.0\",\n    \"@babel/preset-react\": \"^7.0.0\",\n    \"@babel/preset-typescript\": \"^7.6.0\",\n    \"@babel/runtime-corejs3\": \"^7.6.0\",\n    \"@material-ui/styles\": \"^4.4.1\",\n    \"@storybook/addon-actions\": \"^5.1.11\",\n    \"@storybook/addon-knobs\": \"^5.1.11\",\n    \"@storybook/addon-links\": \"^5.1.11\",\n    \"@storybook/addons\": \"^5.1.11\",\n    \"@storybook/react\": \"^5.1.11\",\n    \"@testing-library/jest-dom\": \"^4.1.0\",\n    \"@testing-library/react\": \"^9.1.4\",\n    \"@types/enzyme\": \"^3.1.14\",\n    \"@types/enzyme-adapter-react-16\": \"^1.0.3\",\n    \"@types/jest\": \"^24.0.18\",\n    \"@types/react\": \"^16.4.6\",\n    \"@types/storybook__addon-actions\": \"^3.4.3\",\n    \"@types/storybook__addon-knobs\": \"^5.0.3\",\n    \"@types/storybook__addon-links\": \"^3.3.5\",\n    \"@types/storybook__react\": \"^4.0.2\",\n    \"@typescript-eslint/eslint-plugin\": \"^2.2.0\",\n    \"@typescript-eslint/parser\": \"^2.2.0\",\n    \"awesome-typescript-loader\": \"^5.2.1\",\n    \"babel-core\": \"7.0.0-bridge.0\",\n    \"babel-loader\": \"^8.0.2\",\n    \"commitizen\": \"^3.0.2\",\n    \"cz-lerna-changelog\": \"^2.0.0\",\n    \"eslint\": \"^6.3.0\",\n    \"eslint-config-prettier\": \"^6.3.0\",\n    \"eslint-plugin-import\": \"^2.18.2\",\n    \"eslint-plugin-prettier\": \"^3.1.0\",\n    \"eslint-plugin-react\": \"^7.14.3\",\n    \"jest\": \"^24.9.0\",\n    \"lerna\": \"^3.4.0\",\n    \"moment\": \"^2.22.2\",\n    \"npm-run-all\": \"^4.1.3\",\n    \"prettier\": \"^1.18.2\",\n    \"react\": \"^16.9.0\",\n    \"react-dom\": \"^16.9.0\",\n    \"stylelint\": \"^9.5.0\",\n    \"stylelint-config-recommended\": \"^2.1.0\",\n    \"stylelint-config-standard\": \"^18.2.0\",\n    \"ts-jest\": \"^24.0.2\",\n    \"typescript\": \"^3.0.3\",\n    \"webpack\": \"^4.39.3\"\n  },\n  \"config\": {\n    \"commitizen\": {\n      \"path\": \"./node_modules/cz-lerna-changelog\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/input/CHANGELOG.md",
    "content": "# Change Log\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n<a name=\"0.1.0\"></a>\n# 0.1.0 (2018-10-14)\n\n\n### Features\n\n* **Input:** add default labelWidth ([8302608](https://github.com/serhii-havrylenko/monorepo-babel-ts-lerna-starter/commit/8302608))\n"
  },
  {
    "path": "packages/input/package.json",
    "content": "{\n  \"name\": \"@taxi/input\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Input component\",\n  \"author\": \"chef <serhii.havrylenko@gmail.com>\",\n  \"homepage\": \"https://github.com/serhii-havrylenko/monorepo-babel-ts-lerna-starter\",\n  \"license\": \"MIT\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build:declaration\": \"tsc --project tsconfig.build.json\",\n    \"build:es\": \"BABEL_ENV=build babel src --root-mode upward --out-dir dist --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/serhii-havrylenko/monorepo-babel-ts-lerna-starter.git\"\n  },\n  \"peerDependencies\": {\n    \"@material-ui/styles\": \"^4.4.1\",\n    \"react\": \"^16.9.0\"\n  },\n  \"publishConfig\": {\n    \"registry\": \"http://localhost:4873\"\n  }\n}\n"
  },
  {
    "path": "packages/input/src/Input.story.tsx",
    "content": "import { text } from '@storybook/addon-knobs';\nimport { storiesOf } from '@storybook/react';\nimport * as React from 'react';\n\nimport { Input } from './Input';\n\nstoriesOf('Input', module)\n  .add('default', () => <Input />)\n  .add('with label', () => (\n    <Input id=\"test\" label={text('Label', 'Username')} />\n  ))\n  .add('with label and type', () => (\n    <Input\n      id=\"test\"\n      label={text('Label', 'Username')}\n      type={text('Type', 'text')}\n    />\n  ));\n"
  },
  {
    "path": "packages/input/src/Input.test.tsx",
    "content": "import * as React from 'react';\nimport { render } from '@testing-library/react';\n\nimport { Input } from './Input';\n\ndescribe('Input', () => {\n  test('should match snapshot and styles for default props', () => {\n    expect(render(<Input />).asFragment()).toMatchSnapshot();\n  });\n\n  test('should match snapshot with label', () => {\n    const wrapper = render(<Input id=\"test\" label=\"Name\" />);\n    expect(wrapper.asFragment()).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "packages/input/src/Input.tsx",
    "content": "import React from 'react';\nimport { makeStyles } from '@material-ui/styles';\n\nexport interface LabelProps {\n  labelWidth?: number;\n}\n\nexport interface InputWithLabelProps extends LabelProps {\n  id?: string;\n  label?: string;\n}\n\nexport interface InputWithoutLabelProps extends LabelProps {\n  id: string;\n  label: string;\n}\n\nexport type InputLabelProps = InputWithLabelProps | InputWithoutLabelProps;\n\nexport interface InputProps {\n  name?: string;\n  type?: string;\n}\n\nconst useStyles = makeStyles({\n  root: {\n    display: 'flex',\n    margin: '10px',\n  },\n  label: {\n    marginRight: '10px',\n    fontWeight: 'bold',\n  },\n  input: {\n    width: '100%',\n  },\n});\n\nexport const Input: React.FunctionComponent<InputProps & InputLabelProps> = ({\n  label,\n  id,\n  labelWidth,\n  ...rest\n}) => {\n  const classes = useStyles({ labelWidth });\n\n  return (\n    <div className={classes.root}>\n      {label && (\n        <label className={classes.label} htmlFor={id}>\n          {label}:\n        </label>\n      )}\n      <input className={classes.input} id={id} {...rest} />\n    </div>\n  );\n};\n\nInput.defaultProps = {\n  type: 'text',\n};\n"
  },
  {
    "path": "packages/input/src/__snapshots__/Input.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`Input should match snapshot and styles for default props 1`] = `\n<DocumentFragment>\n  <div\n    class=\"makeStyles-root-1\"\n  >\n    <input\n      class=\"makeStyles-input-3\"\n      type=\"text\"\n    />\n  </div>\n</DocumentFragment>\n`;\n\nexports[`Input should match snapshot with label 1`] = `\n<DocumentFragment>\n  <div\n    class=\"makeStyles-root-4\"\n  >\n    <label\n      class=\"makeStyles-label-5\"\n      for=\"test\"\n    >\n      Name:\n    </label>\n    <input\n      class=\"makeStyles-input-6\"\n      id=\"test\"\n      type=\"text\"\n    />\n  </div>\n</DocumentFragment>\n`;\n"
  },
  {
    "path": "packages/input/src/index.ts",
    "content": "export { Input, InputProps } from './Input';\n"
  },
  {
    "path": "packages/input/tsconfig.build.json",
    "content": "{\n  \"extends\": \"../../tsconfig.build.json\",\n  \"compilerOptions\": {\n    \"skipLibCheck\": true,\n    \"declarationDir\": \"./dist\",\n    \"rootDir\": \"./src\",\n    \"baseUrl\": \"./\"\n  },\n  \"include\": [\"./src\"]\n}\n"
  },
  {
    "path": "packages/login-form/CHANGELOG.md",
    "content": "# Change Log\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n<a name=\"0.0.1\"></a>\n## 0.0.1 (2018-10-14)\n\n**Note:** Version bump only for package @taxi/login-form\n"
  },
  {
    "path": "packages/login-form/package.json",
    "content": "{\n  \"name\": \"@taxi/login-form\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Login form component\",\n  \"main\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"author\": \"chef\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/serhii-havrylenko/monorepo-babel-ts-lerna-starter.git\"\n  },\n  \"peerDependencies\": {\n    \"@material-ui/styles\": \"^4.4.1\",\n    \"react\": \"^16.9.0\"\n  },\n  \"scripts\": {\n    \"build:declaration\": \"tsc --project tsconfig.build.json\",\n    \"build:es\": \"BABEL_ENV=build babel src --root-mode upward --out-dir dist --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments\"\n  },\n  \"files\": [\n    \"dist\"\n  ],\n  \"dependencies\": {\n    \"@taxi/input\": \"^0.1.0\"\n  },\n  \"publishConfig\": {\n    \"registry\": \"http://localhost:4873\"\n  }\n}\n"
  },
  {
    "path": "packages/login-form/src/LoginForm.story.tsx",
    "content": "import { action } from '@storybook/addon-actions';\nimport { storiesOf } from '@storybook/react';\nimport * as React from 'react';\nimport { LoginForm } from './LoginForm';\n\nstoriesOf('LoginForm', module).add('default', () => {\n  const onClick = action('logIn clicked');\n  return <LoginForm onClick={onClick} />;\n});\n"
  },
  {
    "path": "packages/login-form/src/LoginForm.test.tsx",
    "content": "import React from 'react';\nimport { render } from '@testing-library/react';\n\nimport { LoginForm } from './LoginForm';\n\njest.mock('@taxi/input', () => ({ Input: 'input' }));\n\ndescribe('LoginForm', () => {\n  test('should match snapshot and styles', () => {\n    expect(render(<LoginForm />).container).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "packages/login-form/src/LoginForm.tsx",
    "content": "import { Input } from '@taxi/input';\nimport * as React from 'react';\nimport { makeStyles } from '@material-ui/styles';\n\nconst useStyles = makeStyles({\n  root: {\n    display: 'flex',\n    flexDirection: 'column',\n    margin: '10px',\n  },\n  wrapper: {\n    textAlign: 'right',\n  },\n});\n\nexport interface LoginFormProps {\n  onClick?: () => void;\n}\n\nexport const LoginForm: React.FunctionComponent<LoginFormProps> = ({\n  onClick,\n}) => {\n  const classes = useStyles();\n\n  return (\n    <div className={classes.root}>\n      <Input id=\"name\" label=\"Name\" />\n      <Input id=\"password\" label=\"Password\" />\n\n      <div className={classes.wrapper}>\n        <button onClick={onClick}>Log in</button>\n      </div>\n    </div>\n  );\n};\n"
  },
  {
    "path": "packages/login-form/src/__snapshots__/LoginForm.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`LoginForm should match snapshot and styles 1`] = `\n<div>\n  <div\n    class=\"makeStyles-root-1\"\n  >\n    <input\n      id=\"name\"\n      label=\"Name\"\n    />\n    <input\n      id=\"password\"\n      label=\"Password\"\n    />\n    <div\n      class=\"makeStyles-wrapper-2\"\n    >\n      <button>\n        Log in\n      </button>\n    </div>\n  </div>\n</div>\n`;\n"
  },
  {
    "path": "packages/login-form/src/index.ts",
    "content": "export * from './LoginForm';\n"
  },
  {
    "path": "packages/login-form/tsconfig.build.json",
    "content": "{\n  \"extends\": \"../../tsconfig.build.json\",\n  \"compilerOptions\": {\n    \"declarationDir\": \"./dist\",\n    \"rootDir\": \"./src\",\n    \"baseUrl\": \"./\"\n  },\n  \"include\": [\"./src\"]\n}\n"
  },
  {
    "path": "tsconfig.build.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": false,\n    \"emitDeclarationOnly\": true,\n    \"declaration\": true,\n    \"paths\": {\n      \"@taxi/*\": [\"./node_modules/@taxi/*/src\"]\n    }\n  },\n  \"exclude\": [\"**/*.story.*\", \"**/*.test.*\", \"dist\"],\n  \"include\": []\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"strict\": true,\n    \"jsx\": \"react\",\n    \"target\": \"esnext\",\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"esModuleInterop\": true,\n    \"removeComments\": true,\n    \"rootDir\": \".\",\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@taxi/*\": [\"packages/*/src\"],\n      \"*\": [\"node_modules\", \"packages\"]\n    }\n  },\n  \"awesomeTypescriptLoaderOptions\": {\n    \"useBabel\": true,\n    \"babelCore\": \"@babel/core\"\n  },\n  \"include\": [\"packages\", \"jest-dom/extend-expect\"],\n  \"exclude\": [\"node_modules\", \"dist\"]\n}\n"
  }
]