npm package: @scaleleap/utils
Description: Scale Leap Utils
Author: Roman Filippov
Latest version: 1.9.98

# Scale Leap Utils

## Glossary

* **Product**: the project that consumes or uses various tools and utilities described below. In
  other words, it is the final consumer of these utilities.
* **SL Utils**: this document describes the utils project that we are developing. It contains
  various tools and utilities for listing and formalizing Product Projects.
  * Example: a project  containing shared ESLint configuration, a project containing commitlint
    reusable configuration.
* **Utility Package**: An NPM package that provides functionality that we want to tap into.
  * Example: ESLint, stylelint
* **Monorepo**: A single CVS repository containing multiple projects.
* **IDE**: Code editor, in this case it is always VS Code.

## Motivation

Initializing (starting) new JavaScript projects is tiring and time consuming. A lot of boilerplate
needs to be created before a codebase can be ready for productive work.

Keeping existing projects updated is also challenging as dependencies get stale and they need to be
maintained.

## Goals

To create a single project (might be a monorepo) that contains useful tooling that helps with
project initialization and upkeep.

This project (package(s)) would help to minimize boilerplate in the Product project.

Ideally, it should be as simple as:

```sh
$> npx some-tool-name project-name
$> code project-name
```

Where `some-tool-name` is an initializer tool that:

* Creates a new project directory
* Calls `git setup` (from `git-extras`) inside it
* Scaffolds a project from a template

## Non Goals

We do not want to create any new major tools from scratch, but rather rely on existing tooling from
the NodeJS ecosystem. Creation of small helper scripts is ok.

## Requirements

Most of the work that we do at Scale Leap is TypeScript based. Only some legacy projects rely on
JavaScript (NodeJS). The focus of tooling should be primarily to support TypeScript workflows.

Configuration files should use  `.js` extension (syntax), where possible. E.g. `.eslint.js` is
preferred over `.eslint.json`, where it is possible. It is understood that not all Utility Packages
will offer this option.

The Product should not depend directly on Utility Packages. Utility Packages should be self
contained in the SL Utils package where possible. This might be also be achieved via shims in the
Product project that links to, or otherwise calls the binary from the Utils package.

* **Good**: `"lint:js": "node_modules/@scaleleap/utils/.bin/eslint --ext .js ."`
* **Bad**: `"lint:js": "eslint --ext .js ."`

We don't want to create copies of configurations or setting files, if we can avoid it. It is better
to just reference the config in SL Utils package insteaf, where possible.

* **Good**: (config loaded from Utils package): `commitlint --config
  node_modules/@scaleleap/utils/commitlint.config.js`
* **Bad**: (config loaded from Product project): `commitlint --config ./commitlint.config.js`

If it is not possible to *not* copy a config file, then the next best thing is to make a copy and
`require` the contents of the file from the Utils package. E.g.

```js
module.export = require('@scaleleap/utils/eslint-js')
```

## Linters

All linters should be setup to run, *where possible*, for these use cases:

* on git commits (via [lint-staged](https://github.com/okonet/lint-staged) and
  [husky](https://github.com/typicode/husky))
* manually
  * `npm run lint` -- runs all linters in parallel via `npm-run-all`
  * or `npm run lint:js` or `npm run lint:style` -- for specific linters
* IDE via extensions, either native support for the relevant linter, or via generic extension(s)
  that can run commands on-save automatically.

### ESLint

Need to make sure that all plugins are compatible with each other and imported in the right order.
This is pretty tricky and needs a good amount of attention.

#### Configs

* TypeScript
  * `typescript-eslint` is expecting a 2.0 release which should be really good, so we should
    probably start with that right away. Can use GitHub repo as a dependency for now until the final
    NPM package gets released.
* JavaScript
* Vue
* Nuxt
  * This project has their own eslint config bundled already, which we probably should use and
    extend as it might have some nuances. But if you think it is not needed, then we don't have to.

#### Plugins

* eslint-config-airbnb (*some rules will be overridden TBD*)
* eslint-plugin-prettier
  * printWidth: 120
  * semi: false
  * singleQuote: true
  * trailingComma: all
  * arrowParens: always
* eslint-plugin-eslint-comments
* eslint-plugin-import
* eslint-plugin-jest
* eslint-plugin-sonarjs
* eslint-plugin-unicorn
* eslint-plugin-vue-a11y (*only for vue & nuxt configs*)
* eslint-plugin-sql (*only for TypeScript and JavaScript configs*)
* eslint-plugin-graphql

#### Formatter

* eslint-formatter-github (*don't think this needs any implicit setup, just included as a
  dependency*)

#### Rules

Exact rules are TBD.

### [stylelint](https://github.com/stylelint/stylelint)

* For now recommended styles are acceptable for now

### [markdownlint](https://github.com/DavidAnson/markdownlint)

* Any default/recommended styles are acceptable for now

### ~~imagemin-lint-staged~~

* ~~Compress staged images before commit~~
* Replaced with GitHub Actions.

### [commitlint](https://github.com/conventional-changelog/commitlint)

* Setup to use Conventional Commit
  * Ideally without "scope" option
    * **Good**: `feat: implements foo`
    * **Bad**: `feat(some-scope): implements foo`

### [prettier-package-json](https://www.npmjs.com/package/prettier-package-json)

* Standardizes `package.json`

### [lockfile-lint](https://github.com/lirantal/lockfile-lint)

* Validates lockfiles to make sure they are not tampered with.

## Utilities

### [Commitizen](https://github.com/commitizen/cz-cli)

* Uses `cz-customizable` to customize the commit message prompts
  * Should set **askForBreakingChangeFirst** to `true`

### [husky](https://github.com/typicode/husky)

Set up Git hooks for various uses, such as commit message validation and `npm install` like in [the
example of ghooks](https://github.com/ghooks-org/ghooks).

## IDE

Our primary editor is VS Code.

### Extensions

Should provide a file with [Workspace recommended
extensions](https://code.visualstudio.com/docs/editor/extension-gallery#_workspace-recommended-extensions)
for all extensions that are required for the Utils to work with IDE.

### Settings

Should provide VS Code settings with all of the required settings to make Utils work with the IDE.

## Inspiration / Prior Art

The goal is to get to somethign similar to the following repos:

* [wemake-services/wemake-frontend-styleguide](https://github.com/wemake-services/wemake-frontend-styleguide/tree/master/packages)
* [adidas/js-linter-configs](https://github.com/adidas/js-linter-configs)
* [spotify/web-scripts](https://github.com/spotify/web-scripts)
* [@microsoft/eslint-config-scalable-ts](https://github.com/microsoft/web-build-tools/tree/master/libraries/eslint-config-scalable-ts),
  especially [this
  hack](https://github.com/microsoft/web-build-tools/blob/master/libraries/eslint-config-scalable-ts/patch-eslint6.js).

## Idea Dump

* Self contain all `npm run` scripts in the Utils package too
  * Just - MS package