Compare commits

..

1 Commits

Author SHA1 Message Date
Caroline
5cd19fa7cd feat: accessability section 2021-09-07 16:32:05 +01:00
26 changed files with 4902 additions and 2080 deletions

View File

@ -1,35 +0,0 @@
kind: pipeline
type: docker
steps:
# - name: markdownlint-cli
# image: node:current-alpine
# commands:
# - npm install -g markdownlint-cli
# - markdownlint **/*.md
# - name: semantic-release
# image: cenk1cenk2/drone-semantic-release
# settings:
# mode: predict
# add_modules: "@saithodev/semantic-release-sharedconf-npm"
# semantic_release: true
# update_readme_toc: true
# use_local_rc: true
# git_method: cr
# git_user_name:
# from_secret: user_gitea
# git_user_email:
# from_secret: email_gitea
# git_login:
# from_secret: user_gitea
# git_password:
# from_secret: gitea_token
# update_docker_readme: false
- name: semver
image: node:current-alpine
commands:
- npm install semver
- semver

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
.git/
### Node ###
# Logs

View File

@ -1,227 +0,0 @@
# Example markdownlint YAML configuration with all properties set to their default value
# Default state for all rules
default: true
# Path to configuration file to extend
extends: null
# MD001/heading-increment/header-increment - Heading levels should only increment by one level at a time
MD001: false
# MD002/first-heading-h1/first-header-h1 - First heading should be a top-level heading
MD002:
# Heading level
level: 1
# MD003/heading-style/header-style - Heading style
MD003:
# Heading style
style: "consistent"
# MD004/ul-style - Unordered list style
MD004:
# List style
style: "consistent"
# MD005/list-indent - Inconsistent indentation for list items at the same level
MD005: true
# MD006/ul-start-left - Consider starting bulleted lists at the beginning of the line
MD006: true
# MD007/ul-indent - Unordered list indentation
MD007:
# Spaces for indent
indent: 2
# Whether to indent the first level of the list
start_indented: false
# MD009/no-trailing-spaces - Trailing spaces
MD009:
# Spaces for line break
br_spaces: 2
# Allow spaces for empty lines in list items
list_item_empty_lines: false
# Include unnecessary breaks
strict: false
# MD010/no-hard-tabs - Hard tabs
MD010:
# Include code blocks
code_blocks: true
# Number of spaces for each hard tab
spaces_per_tab: 1
# MD011/no-reversed-links - Reversed link syntax
MD011: true
# MD012/no-multiple-blanks - Multiple consecutive blank lines
MD012:
# Consecutive blank lines
maximum: 1
# MD013/line-length - Line length
MD013:
# Number of characters
line_length: 900
# Number of characters for headings
heading_line_length: 300
# Number of characters for code blocks
code_block_line_length: 80
# Include code blocks
code_blocks: true
# Include tables
tables: true
# Include headings
headings: true
# Include headings
headers: true
# Strict length checking
strict: false
# Stern length checking
stern: false
# MD014/commands-show-output - Dollar signs used before commands without showing output
MD014: true
# MD018/no-missing-space-atx - No space after hash on atx style heading
MD018: true
# MD019/no-multiple-space-atx - Multiple spaces after hash on atx style heading
MD019: true
# MD020/no-missing-space-closed-atx - No space inside hashes on closed atx style heading
MD020: true
# MD021/no-multiple-space-closed-atx - Multiple spaces inside hashes on closed atx style heading
MD021: true
# MD022/blanks-around-headings/blanks-around-headers - Headings should be surrounded by blank lines
MD022:
# Blank lines above heading
lines_above: 1
# Blank lines below heading
lines_below: 1
# MD023/heading-start-left/header-start-left - Headings must start at the beginning of the line
MD023: true
# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content
MD024:
# Only check sibling headings
allow_different_nesting: false
# Only check sibling headings
siblings_only: false
# MD025/single-title/single-h1 - Multiple top-level headings in the same document
MD025:
# Heading level
level: 1
# RegExp for matching title in front matter
front_matter_title: "^\\s*title\\s*[:=]"
# MD026/no-trailing-punctuation - Trailing punctuation in heading
MD026:
# Punctuation characters
punctuation: ".,;:!。,;:!"
# MD027/no-multiple-space-blockquote - Multiple spaces after blockquote symbol
MD027: true
# MD028/no-blanks-blockquote - Blank line inside blockquote
MD028: true
# MD029/ol-prefix - Ordered list item prefix
MD029:
# List style
style: "one_or_ordered"
# MD030/list-marker-space - Spaces after list markers
MD030:
# Spaces for single-line unordered list items
ul_single: 1
# Spaces for single-line ordered list items
ol_single: 1
# Spaces for multi-line unordered list items
ul_multi: 1
# Spaces for multi-line ordered list items
ol_multi: 1
# MD031/blanks-around-fences - Fenced code blocks should be surrounded by blank lines
MD031:
# Include list items
list_items: true
# MD032/blanks-around-lists - Lists should be surrounded by blank lines
MD032: true
# MD033/no-inline-html - Inline HTML
MD033:
# Allowed elements
# allowed_elements: ["br", "img"]
# MD034/no-bare-urls - Bare URL used
MD034: true
# MD035/hr-style - Horizontal rule style
MD035:
# Horizontal rule style
style: "consistent"
# MD036/no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading
MD036:
# Punctuation characters
punctuation: ".,;:!?。,;:!?"
# MD037/no-space-in-emphasis - Spaces inside emphasis markers
MD037: true
# MD038/no-space-in-code - Spaces inside code span elements
MD038: true
# MD039/no-space-in-links - Spaces inside link text
MD039: true
# MD040/fenced-code-language - Fenced code blocks should have a language specified
MD040: true
# MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading
MD041:
# # Heading level
# level: 1
# # RegExp for matching title in front matter
# front_matter_title: "^\\s*title\\s*[:=]"
# MD042/no-empty-links - No empty links
MD042: true
# MD043/required-headings/required-headers - Required heading structure
MD043:
# # List of headings
# headings: []
# # List of headings
# headers: []
# MD044/proper-names - Proper names should have the correct capitalization
MD044:
# List of proper names
names: []
# Include code blocks
code_blocks: true
# MD045/no-alt-text - Images should have alternate text (alt text)
MD045: true
# MD046/code-block-style - Code block style
MD046:
# Block style
style: "consistent"
# MD047/single-trailing-newline - Files should end with a single newline character
MD047: true
# MD048/code-fence-style - Code fence style
MD048:
# Code fence style
style: "consistent"

View File

@ -1,24 +0,0 @@
{
"extends": "@saithodev/semantic-release-sharedconf-npm",
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
[
"@semantic-release/npm",
{"tarballDir": "release"}
],
[
"@semantic-release/git",
{"assets": ["package.json", "CHANGELOG.md"]}
],
[
"@semantic-release/github",
{"assets": "release/*.tgz"}
]
],
"branches": [
"master"
]
}

View File

@ -1,28 +0,0 @@
## [1.0.3](https://git.sthope.dev/sthope/gitea_templates/compare/v1.0.2...v1.0.3) (2021-09-12)
### Performance Improvements
* testing sv ([2b9b099](https://git.sthope.dev/sthope/gitea_templates/commit/2b9b0992aab0ce6b0d2a0cd7a274a906d9df579c))
* testing sv ([b22c8ae](https://git.sthope.dev/sthope/gitea_templates/commit/b22c8ae06067832c8901583e27a41216b2ebaf79))
## [1.0.2](https://git.sthope.dev/sthope/gitea_templates/compare/v1.0.1...v1.0.2) (2021-09-11)
### Performance Improvements
* testing semantic release ([51ce62a](https://git.sthope.dev/sthope/gitea_templates/commit/51ce62ab1464367aa2e728326c8eed9505423194))
* testing semantic release ([6549aaa](https://git.sthope.dev/sthope/gitea_templates/commit/6549aaa0d202ff24f4e98a2c2ddbee29c17ffa18))
## [1.0.1](https://git.sthope.dev/sthope/gitea_templates/compare/v1.0.0...v1.0.1) (2021-09-11)
### Performance Improvements
* testing semantic release ([dc6ae97](https://git.sthope.dev/sthope/gitea_templates/commit/dc6ae97ca9bea3cf690826161159512c0cec641f))
# 1.0.0 (2021-09-11)
### Features
* **translation:** adds russian translation ([#142](https://git.sthope.dev/sthope/gitea_templates/issues/142)) ([1f572e8](https://git.sthope.dev/sthope/gitea_templates/commit/1f572e8aebd0610a1554c84c3db12b7fbfeed0df))

View File

@ -2,7 +2,7 @@
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
@ -30,16 +30,17 @@ Project maintainers have the right and responsibility to remove, edit, or reject
## Scope
This Code of Conduct applies within all project spaces, and it also applies when an individual is representing the project or its community in public spaces. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project maintainer using any of the [private contact addresses](https://github.com/dec0dOS/amazing-github-template#support). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at vahid@elsewhen.co. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, available at <https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
For answers to common questions about this code of conduct, see <https://www.contributor-covenant.org/faq>
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@ -1,5 +1,4 @@
# Contributing to Project Guidelines
### No guidelines here :D, hit us with your PR
**Working on your first Pull Request?** You can learn how from this *free* series [How to Contribute to an Open Source Project on GitHub](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github)
### No guidelines here :D, hit us with your PR.
**Working on your first Pull Request?** You can learn how from this *free* series [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github)

26
LICENSE
View File

@ -1,21 +1,5 @@
The MIT License (MIT)
Copyright (c) 2021 Sthope https://www.sthope.dev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
The MIT License (MIT)
Copyright (c) 2018 Elsewhen https://www.elsewhen.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

780
README-ja.md Normal file
View File

@ -0,0 +1,780 @@
[中文版](./README-zh.md)
| [ENGLISH](./README.md)
| [한국어](./README-ko.md)
| [РУССКИЙ](./README-ru.md)
| [Português](./README-pt-BR.md)
[<img src="./images/elsewhen-logo.png" width="180" height="180">](https://www.elsewhen.com/)
# プロジェクトガイドライン[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
> 開発中の新たなプロジェクトは草原のようですが、メンテナンスは誰にとっても悪夢になります。
ここには私たちが見つけ記載し、集め考えたガイドラインがあります。 このガイドラインはほとんどの[elsewhen](https://www.elsewhen.com)のJavaScriptのプロジェクトで機能しています。
もしもベストプラクティスを我々と共有したかったり、このガイドラインの項目は削除した方が良いと思ったら[気軽に私たちに報告してください](http://makeapullrequest.com)。
- [Git](#git)
- [Gitのルール](#some-git-rules)
- [Git workflow](#git-workflow)
- [良いコミットメッセージの書き方](#writing-good-commit-messages)
- [ドキュメント](#documentation)
- [開発環境](#environments)
- [統一された開発環境](#consistent-dev-environments)
- [一貫した依存性](#consistent-dependencies)
- [依存関係](#dependencies)
- [テスト](#testing)
- [プロジェクトの構造と名前付け](#structure-and-naming)
- [コードスタイル](#code-style)
- [コードスタイルガイドライン](#code-style-check)
- [標準的なコードスタイルの強制](#enforcing-code-style-standards)
- [ログ](#logging)
- [API](#api)
- [APIデザイン](#api-design)
- [APIセキュリティ](#api-security)
- [APIドキュメント](#api-documentation)
- [ライセンス](#licensing)
<a name="git"></a>
## 1. Git
![Git](/images/branching.png)
<a name="some-git-rules"></a>
### 1.1 Gitのルール
いくつかのGitのルールを覚えておきましょう。
* featureブランチで作業しましょう。
_Why:_
>全作業がメインブランチではなくて独立した作業専用のブランチで完結するからです。そうすることによって混乱をきたすことなく複数のプルリクエストを作成することができます。作業途中のコードや不安定なコードをmasterブランチを気にすることなく繰り返し作れます。[もっと読む...](https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow)
* `develop`ブランチからブランチを切りましょう
_Why:_
>こうすることでmasterのコードを問題なくビルドできることができ、masterはリリース用にほとんどそのまま利用できます。(プロジェクトによってはやりすぎかもしれません。)
* `develop``master`ブランチに直接Pushするのはやめましょう。プルリクエストを作成しましょう。
_Why:_
>`develop``master`ブランチが更新されるということはチームメンバーにその機能を実装し終わったと伝えることと同義です。直接Pushさえしなければ、コードレビューや新たな機能の議論がしやすくなります。
* featureブランチをPushしてプルリクエストを作成する前にローカルの`develop` ブランチを最新にして、featureブランチをインタラクティブリベースしましょう。
_Why:_
>リベースはブランチ(`master``develop`をマージします。またlocalに作ったコミットをマージコミットを作成せずにGitのヒストリーのトップに並べ替えます。コンフリクトがなければ。そうすることで綺麗で素晴らしいヒストリーが残ります。[もっと読む...](https://www.atlassian.com/git/tutorials/merging-vs-rebasing)
* リベースする間やプルリクエストを作る前にコンフリクトを解消しましょう。
* マージした後のブランチはlocal、remote共に削除しましょう。
_Why:_
>不要になったブランチをが含まれることで自身localのブランチのリストが乱雑になるでしょう。またマージする時にのみ一回だけブランチ`master``develop`に戻ることを保証します。feature ブランチは作業中だけ存在すべきです。
* プルリクエストを前に、featureブランチのビルドの成功を確認して全てのテストを通しましょう。(コードのスタイルも含めて確認しましょう。)
_Why:_
> 安定的なコードを追加しようとする時、もしfeatureブランチのテストが失敗したとすると、最終的なマージ後のテストも失敗する可能性が高いです。加えてプルリクエストを作成する前に、スタイルチェックを行う必要があります。スタイルチェックを行うことで可読性が上がり、実際のコードと一緒にフォーマットによる修正を減らすことに繋がります。
* [こちらの](./.gitignore)`.gitignore`ファイルを使いましょう。
_Why:_
> この.gitignoreファイルにはremoteのリポジトリに含めたくないシステムファイルのリストを列挙しています。またユーザーが多くの人が使うエディタ用のフォルダやファイル(依存フォルダも同じように)も含めてます。
* `develop``master`ブランチを保護しましょう。
_Why:_
> プロダクションに備えているブランチに予期しない破壊的なコミットがPushされることを防ぎます。
<a name="git-workflow"></a>
### 1.2 Git workflow
上記の理由のために、私達は[Feature-branch-workflow](https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow)と[Interactive Rebasing](https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing)、[Gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows#gitflow-workflow) の要素のいくつか(名前付とdevelopブランチを持つこと)を使います。主なステップは以下の通りです。
* 新しいプロジェクトにとっては初期のgitの設定。__features/changesブランチの作成は の次のステップなので無視しましょう。__
```sh
cd <project directory>
git init
```
* feature/bug-fix ブランチを作成する。
```sh
git checkout -b <branchname>
```
* コードを変更する。
```sh
git add
git commit -a
```
_Why:_
> `git commit -a`を使うと本文から主題を切り離して始めることができます。詳しくは*section 1.3*を読みましょう。
* 取り込まれていない変更を取得する為にリモートのリボジトリと同期しましょう。
```sh
git checkout develop
git pull
```
_Why:_
>こうすることでコンフリクトを含めながらプルリクエストを作成するのではなくてリベース(のちに)しつつ、コンフリクトに対処できる可能性が高まります。
* featureブランチにインタラクティブリベースをすることで常にdevelopの変更を取り込みましょう。
```sh
git checkout <branchname>
git rebase -i --autosquash develop
```
_Why:_
> --autosquashは全てのコミットを一つにまとめることができます。一つのfeatureに対して複数のコミットがある状態は望ましくありません。[もっと読む...](https://robots.thoughtbot.com/autosquashing-git-commits)
* もしコンフリクトしてなかったらこの章は飛ばして大丈夫です。ただしもしコンフリクトが起きてたら[解決しましょう](https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/)。そしてリベースを続けましょう。
```sh
git add <file1> <file2> ...
git rebase --continue
```
* 自分のブランチをPushしましょう。リベースはヒストリーを改変しますので、リモートにPushする際は`-f` のオプションをつけてPushする必要があります。もし他の人が同じブランチで作業をしていたらより破壊的でない`--force-with-lease`を使いましょう。
```sh
git push -f
```
_Why:_
> リベースをすると、作業ブランチのコミットヒストリーを変えることになります。結果としてGitに普通の`git push`は拒否されるので代わりに -f や--force フラグを使えば大丈夫です。[もっと読む...](https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/)
* プルリクエストを作りましょう。
* プルリクエストが受け入れられたら、レビュワーによってマージされて課題が閉じられます。
* マージが完了したらローカルのブランチを消しましょう。
```sh
git branch -d <branchname>
```
必要のないリモートブランチを全て削除するコマンド。
```sh
git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done
```
<a name="writing-good-commit-messages"></a>
### 1.3 良いコミットメッセージの書き方
コミットを作成して維持するための良い指針を持つと、Gitをうまく使うことができ他の開発者との共同作業をとても簡単にします。ここにいくつかの経験則があります。([ソース](https://chris.beams.io/posts/git-commit/#seven-rules))
* 本文を改行することで主題と切り離しましょう。
_Why:_
> Gitは最初の行をそのコミットのサマリとして区別します。実際`git log`の代わりに`git shortlog`を使うと、コミットIDとサマリーのみで構成される長いコミットメッセージのリストを見ることができます。
* 主題は50文字以内、本文を含めても72文字以内に制限しましょう。
_why_
> コミットはできる限りきめ細やかで完結あるべきで、コミットメッセージを冗長にすることは避けましょう。[詳しく読む](https://medium.com/@preslavrachev/what-s-with-the-50-72-rule-8a906f61f09c)
* 主題の先頭は大文字にしましょう。
* ピリオドで終わるのをやめましょう。
* 主題部分では[命令法](https://en.wikipedia.org/wiki/Imperative_mood) を使いましょう。
_Why:_
> コミッタが何を行ったかわかりやすいメッセージを書きましょう。コミットがマージされた後にそのコミットが何をしたのかをうまく説明できるように考えるといいでしょう。[もっと読む...](https://news.ycombinator.com/item?id=2079612)
* 本文は **How** ではなくて **What** と **Why**を説明しましょう。
<a name="documentation"></a>
## 2. ドキュメント
![ドキュメント](/images/documentation.png)
* こちらの[テンプレート](./README.sample.md)を使って`README.md`を作成しましょう。空白のセクションがあっても気にしなくても大丈夫です。
* 一つ以上のGitリポジトリがあるようなプロジェクトでは、各々の`README.md`ファイルをリンクさせてあげましょう。
* プロジェクトの成長に合わせて`README.md`の情報を最新に保ちましょう。
* コードにはコメントを書きましょう。その際には自分の意図をできる限り簡潔に書くように心がけましょう。
* もしコードや試みているアプローチについてgithubやstackoverllowでオープンな議論があれば、そのリンクもコメントに含めましょう。
* ダメなコードに対する言い訳を書くのはやめましょう。コードを綺麗に保ちましょう。
* 綺麗なコードを全くコメントがないことに対する言い訳にするのはやめましょう。
* コードの成長に合わせてコメントを最新に保ちましょう。
<a name="environments"></a>
## 3. 開発環境
![開発環境](/images/laptop.png)
* 必要なら`development`, `test``production`の環境を分けて定義しましょう。
_Why:_
> データやトークンやAPI、ポートなど環境によって必要とされるものは様々です。。。テストの自動化と手動のテストを簡単にさせるために、`development`モードは予測可能なデータを返すフェイクのAPIが欲しいかもしれません。もしくはGoogle Analyticsは`production`でだけ有効にしたかったり様々でしょう。[もっと読む...](https://stackoverflow.com/questions/8332333/node-js-setting-up-environment-specific-configs-to-be-used-with-everyauth)
* 環境別のConfigファイルを環境毎に適用するようにして、コードベースに定数として決して書き込まないでください。[サンプル](./config.sample.js)
_Why:_
> トークン、パスワードなど様々な重要な個人情報を持っています。 その情報はコードベースがいつ公開されてもいいように、コードベースとは切り離さないといけません。
_How:_
> `.env`ファイルを情報を保持するために使いましょう。そのファイルは`.gitignore`に加えて、Gitリポジトリからは除外されるようにします。その代わりに`.env.example`のようなサンプルを他の開発者向けのガイドとしてコミットしておきましょう。production環境用に、環境設定は標準的なやり方で設定するようにしましょう。
[もっと読む...](https://medium.com/@rafaelvidaurre/managing-environment-variables-in-node-js-2cb45a55195f)
* アプリケーションを開始する前に環境変数をvalidateすることをオススメします。[サンプルを参照](./configWithTest.sample.js) 変数をValidateするために`joi`を使っています。
_Why:_
>トラブルシューティングに費やす時間を節約することに繋がります。
<a name="consistent-dev-environments"></a>
### 3.1 統一された開発環境
* nodeのバージョンを`package.json`の中の`engines`に設定しましょう。
_Why:_
> どのバージョンのnodeをそのプロジェクトで使うべきかを示すことができます。[もっと読む...](https://docs.npmjs.com/files/package.json#engines)
* さらに`nvm` を使って`.nvmrc`をプロジェクトルートに作成しましょう。ドキュメント内に記述を残すことを忘れないようにしましょう。
_Why:_
> `nvm`を使う人は誰でも誰でも`nvm use`を使うことでnodeのバージョンを切り替えることができます。[もっと読む...](https://github.com/creationix/nvm)
* `preinstall`スクリプトを使ってnodeとnpmのバージョンを確かめるのがいいでしょう。
_Why:_
> npmの新たなバージョンでインストールすると依存関係のライブラリが失敗することがあります。
* できるならばDockerイメージを使いましょう。
_Why:_
> Dockerイメージは全てのワークフローを跨いで同じ環境を提供してくれます。依存関係やコンフィグファイルに悩む必要があまりないようになります。[もっと読む...](https://hackernoon.com/how-to-dockerize-a-node-js-application-4fbab45a0c19)
* グローバルのモジュールを使うのではなくローカルのモジュールを使いましょう。
_Why:_
> 同僚が特定のモジュールを彼らのマシンにすでにインストールしていることを期待するのではなく、使うライブラリは共有できるようにしておきましょう。
<a name="consistent-dependencies"></a>
### 3.2 一貫した依存関係
* チームメンバーが同じ依存関係を取得できることを確認しましょう。
_Why:_
   > コードにはどんな開発マシンでも同じ挙動をしてほしいからです。[もっと読む...](https://medium.com/@kentcdodds/why-semver-ranges-are-literally-the-worst-817cdcb09277)
_how:_
> `npm@5`以上で`package-lock.json`を使いましょう。
_npm@5は使ってない:_
> `Yarn`を使い`README.md`を確かめることで代替手段とすることができます。各ライブラリをアップデートした後にロックファイルと`package.json` は同じバージョンを保持しているでしょう。
_`Yarn`という名前が気にくわない:_
> それは残念です。 古いバージョンの`npm`用に、パブリッシュする前に新しいライブラリをインストールしたり`npm-shrinkwrap.json`を作るときには、`—save --save-exact`を使いましょう。[もっと読む...](https://docs.npmjs.com/files/package-locks)
<a name="dependencies"></a>
## 4. 依存関係
![Github](/images/modules.png)
* 使用可能な最新のパッケージを保ちましょう。 e.g.,`npm ls --depth=0`. [もっと読む...](https://docs.npmjs.com/cli/ls)
* 無関係であったり使っていないパッケージを確認しましょう: `depcheck`. [もっと読む...](https://www.npmjs.com/package/depcheck)
_Why:_
> もしかしたら使っていないライブラリがproductionのサイズを増加させているかもしれません。使っていない依存関係を見つけてそれを消すようにしましょう。
* ライブラリをインストールする前に、そのライブラリがコミュニティでよく使われているかどうかを確認しましょう。`npm-stat`。[もっと読む...](https://npm-stat.com/)
_Why:_
> 多く使われているということは多くのコントリビューターがいるということで、それは良いメンテナンスが行われているということになります。そのことはバグが開発者によっていち早く発見され、修正されることに繋がります
* ライブラリをインストールする前に、それがいい機能を持っているか、多くのメンテナーがいて成熟したバージョンを頻繁にリリースしているライブラリかを確認しましょう。: e.g., `npm view async`. [もっと読む...](https://docs.npmjs.com/cli/view)
_Why:_
> もしメンテナーが修正をマージしなかったりパッチを素早く当てないと、コントリビュータが効率的な開発を行えなくなるでしょう。
* それほど知られてないライブラリが必要な場合には、使用する前にチームメンバーと議論しましょう。
* ライブラリはビルドを破壊しない限りは常に最新で動くかを確かめましょう: `npm outdated` [もっと読む...](https://docs.npmjs.com/cli/outdated)
_Why:_
> 依存パッケージの更新はたまに破壊的変更が含まれていることがあります。アップデートが出たときには常にリリースノートを確認しましょう。何かあったときにトラブルシューティングを簡単にするために、依存ライブラリを一つ一つ更新しましょう。[npm-check-updates](https://github.com/tjunnone/npm-check-updates)のように素晴らしいツールを使いましょう。
* 依存パッケージに公開されている脆弱性が含まれている場合があるのでチェックしましょう。 e.g.,[Snyk](https://snyk.io/test?utm_source=risingstack_blog)
<a name="testing"></a>
## 5. テスト
![テスト](/images/testing.png)
* 必要であれば`test`の環境を用意しましょう。
_Why:_
> 通常はend to endのテストを`production`に行うだけで十分なですが、例外がいくつかあります。統計データを`production`環境で有効にしたくなく、テストデータでダッシュボードを汚したくない場合です。あとは`production`のAPIに制限があって、テストをする際のリクエスト数が制限に達してブロックされてしまう場合です。
* 単体テストコードはテストされるファイルの隣におきましょう。 `moduleName.spec.js`のように`*.test.js``*.spec.js` のようなファイル名が慣例となっています。
_Why:_
> ユニットテストを探すためにフォルダ構造を掘り進めたくないでしょう。[もっと読む...](https://hackernoon.com/structure-your-javascript-code-for-testability-9bc93d9c72dc)
* 追加のテストファイルがどこにあるか混乱を避けるために隔離されたフォルダに入れましょう
_Why:_
> いくつかのテストコードは実装コードと関連してないことがあります。他の開発者が見つけやすいフォルダ(`__test__`フォルダのような)にテストコードをおきましょう。`__test__`フォルダはスタンダートであり、様々なJavaScriptフレームワークのテストで使用されています。 
* テストの書きやすコードを書きましょう。副作用を避けましょう。副作用を抽出しましょう。純粋な関数を書きましょう。
_Why:_
> 結合を分けてロジックのテストをしたい場合。ランダムで非決定性のプロセスがコードの信頼性に与える影響を最小にする必要があります。[もっと読む...](https://medium.com/javascript-scene/tdd-the-rite-way-53c9b46f45e3)
> 純粋関数は同じ入力に対して常に同じ結果を出力します。逆に言えば純粋でない関数は副作用をもっているか結果を出力する際に外部の状況に左右されます。そのような関数は予想通りの結果が返ってきにくくなります。[もっと読む...](https://hackernoon.com/structure-your-javascript-code-for-testability-9bc93d9c72dc)
* 静的解析ツールを使いましょう。
_Why:_
> 静的解析ツールが必要な場面があるかもしれません。コードが信頼できる基準をもたらしてくれます。

* `develop`ブランチにするリクエストを投げる前にローカルでテストを実行しましょう。
_Why:_
> 誰しもプロダクション準備中のビルドを失敗される犯人になりたくたいでしょう。`rebase`した後、リモートのfeatureブランチにリポジトリにPushする前にテストを実行するようにしましょう。
* テストの実行方法などの情報を含めて、ドキュメントとして`README.md`ファイルに記述しましょう。
_Why:_
> ドキュメントを残すことで他の開発者、DevOpsの担当者もしくはQAにプロジェクトを引き継いだ時に、彼らがあなたのコードで仕事をしやすくなります。
<a name="structure-and-naming"></a>
## 6. プロジェクトの構造と名前付け
![Structure and Naming](/images/folder-tree.png)
* ファイルを役割ではなく商品、ページ、コンポーネントのように集約しましょう。テストファイルも実装の隣に配置しましょう。

**Bad**
```
.
├── controllers
| ├── product.js
| └── user.js
├── models
| ├── product.js
| └── user.js
```
**Good**
```
.
├── product
| ├── index.js
| ├── product.js
| └── product.test.js
├── user
| ├── index.js
| ├── user.js
| └── user.test.js
```
_Why:_
> 長いファイルのリストの代わりに、テストコードを含めたカプセル化された単一責任の小さいモジュールが出来上がります。そうすることでコードのガイドがしやすくなり、一目で見つけることができるようになります。

* 追加のテストファイルは混乱を避けるためにtestフォルダに置きましょう。
_Why:_
> 他の開発者やチームのDevOpsの担当者の時間を節約することにつながります。
* `./config`フォルダを作成しましょう。違う環境のための違うconfigファイルを作らないようにしましょう。
_Why:_
> 異なる目的(例えばデータベースやAPI等々)のために複数のconfigファイルに分割する時は、同じフォルダに`config`のようなわかりやすい名前でまとめておきましょう。ただし、異なる環境ごとに異なるconfigファイルを作成しないように気をつけてください。新たなデプロイ先が増えた時に新たな環境の名前が必要となり、綺麗にスケールすることができないからです。
configファイル内の変数は環境変数から与えるのが良い方法です。[もっと読む...](https://medium.com/@fedorHK/no-config-b3f1171eecd5)
* スクリプトは`./scripts`フォルダに置きましょう。ここにはnodeやbashのスクリプトが含まれます。
_Why:_
> プロダクション、デベロップのビルド、データベースの構築と同期等々を行う際に少なくとも一つ以上のスクリプトがプロジェクトで必要とされる可能性が高いでしょう。
* ビルドの成果物は`./build`に出力するようにしましょう。`build/``.gitignore`に加えましょう。
_Why:_
   > 名前はなんでもよくて、distという名前でもかっこいいです。なんでもいいとはいえ、チームのメンバーが矛盾なく理解できる名前でなければなりません。例えば何がそのフォルダで取得できるのか、作成されたものなのかバンドルされたものなのか、コンパイルされたものなのか、もしくはただ移動されてきたものなのか。なにを出力するのか、チームメートがそこになにを出力できるのかもそうです。だからそのフォルダは特殊な事情がない限りですがリモートリポジトリにコミットする必要がありません。
* `PascalCase``camelCase`をファイルとディレクトリの名前に使用しましょう。`PascalCase`はコンポーネントのみに使用しましょう。
* `CheckBox/index.js``CheckBox`のコンポーネントを持っているべきです。`CheckBox.js`もそうでしょう。しかし`CheckBox/CheckBox.js``checkbox/CheckBox.js`のような名前は冗長なので避けるべきです。
* 理想的にはフォルダの名前は`index.js`のデフォルトexportの名前と一致させるべきです。
_Why:_
>そうすることで親フォルダをシンプルにimportするだけでモジュールやコンポーネントを想像できます。
<a name="code-style"></a>
## 7. コードスタイル
![Code style](/images/code-style.png)
<a name="code-style-check"></a>
### 7.1 コードスタイルガイドライン
* 新しいプロジェクトではstage-2かそれよりバージョンの新しいモダンなJavaScriptを使用するようにしましょう。古いプロジェクトについては、モダンなJavaScriptが動くプロジェクトにさせたい場合は別として既存のバージョンと互換性のあるバージョンにとどめておきましょう。
_Why:_
>チーム次第ではありますが、私たちはトランスパイラを使用することで、新しいシンタックスの利点を活用しています。stage-2は残りわずかな改訂で仕様の一部になる可能性が徐々に高くなっています。
* コードスタイルチェックをビルドプロセスに含めましょう。
_Why:_
>ビルドを壊すことはコードスタイルを矯正する一つの方法になります。あなたがだんだんコードスタイルを真剣に捉えなくなるということを防いでくれます。クライアントとサーバーサイドのコード両方に導入しましょう。[もっと読む...](https://www.robinwieruch.de/react-eslint-webpack-babel/)
* コードスタイルを強制するために[ESLint - Pluggable JavaScript linter](http://eslint.org/)を使いましょう。
_Why:_
>私たちはシンプルな `eslint` が好きなだけなので、あなたがそうである必要はないです。`eslint` 自体たくさんのルールをサポートしています。ルールを設定でき、カスタムルールを追加することができます。
* 私たちは[Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript)をJavaScriptに使っています。[もっと読む...](https://www.gitbook.com/book/duk/airbnb-javascript-guidelines/details)。あなたのチームに求められたJavaScriptのスタイルガイドを使用しましょう。
* 私たちは[FlowType](https://flow.org/)を使用する時には[Flow type style check rules for ESLint](https://github.com/gajus/eslint-plugin-flowtype)を使っています。
_Why:_
>Flowには、特定のコードスタイルに従ってチェックする必要がある構文がほとんどありません
* 特定のフォルダやファイルをコードスタイルチェックから除外するために`.eslintignore`を使いましょう。
_Why:_
>複数のファイルをスタイルチェックから除外する時に、`eslint-disable`のコメントでコードを汚す必要がありません。
* プルリクエストを作成する前には`eslint`のコメントアウトを削除しましょう。
_Why:_
>ロジックの実装に注力している時はスタイルチェックを無効にするのは一般的ですが、`eslint-disable` のコメントを削除してルールに従うことを忘れないようにしましょう。
* タスクのサイズによって、`//TODO:` コメント使うか、チケットを起票するかを選択しましょう。
_Why:_
>チームメートには小さなタスクの事(関数のリファクタリング、コメントのアップデートなど)を定義しておきましょう。大きめのタスクにはリントルール通りに`//TODO(#3456)`と書き、チケットの番号を記載しましょう。
* コメントは常にコードの変更に関連させるようにしましょう。コメントアウトされたコードは取り除きましょう。
_Why:_
>コードは可能な限り読みやすくする必要があると同時に、余分な部分は除去しておくべきです。リファクタリングする時は既存コードをコメントアウトするのではなく、削除しましょう。
* 無関係であったりおかしなコードやログや名前付けは避けましょう。
_Why:_
>ビルドプロセスでそれらを除去できるかも(すべき)です。あなたのコードは別会社や別クライアントの渡される可能性がありますし、あなたのコードがどこかの誰かに見られて笑われないようにしましょう。
* 短い名前を避けて、意味として区別しやすい検索しやすい名前をつけましょう。関数には長くて記述的な名前を使いましょう。関数の名前は動詞もしくは動詞のフレーズにしましょう。その関数の意図を伝える必要があります。
_Why:_
>ソースコードをより自然により読みやすくさせるためです。
* ファイル内の関数を降順によってまとめておきましょう。高いレベルの関数は上部へ、低いレベルの関数は下部へ位置させましょう。
_Why:_
> 読むのに適したソースコードになるようにするためです。
<a name="enforcing-code-style-standards"></a>
### 7.2 標準的なコードスタイルの強制
* .editorconfigファイルを使って開発者が異なるエディタやIDEのプロジェクト間で一貫したコーディングスタイルを定義し維持することができるようにしましょう。
_Why:_
> EditorConfigプロジェクトはコーディングスタイル定義とエディタがファイルフォーマット読み込んでスタイル定義を有効にするエディタプラグインからなります。EditorConfigファイルは可読性が高くバージョンコントロールシステムともうまく機能します。
* コードスタイルのエラーを伝えてくれるエディタを使いましょう。既存のESLintの設定と一緒に[eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier)と[eslint-config-prettier](https://github.com/prettier/eslint-config-prettier)を使いましょう。[もっと読む...](https://github.com/prettier/eslint-config-prettier#installation)
* Git hookの使用を考えましょう。
_Why:_
> Git hookは開発者の生産性を大きく高めてくれます。ビルドの破壊を怖がることなく、ステージングやプロダクション環境に変更を作成、コミット、Pushできます。[もっと読む...](http://githooks.com/)
* Prettierを`precommit hook`とともに使いましょう。
_Why:_
> `prettier`自体はとても力強いものではありますが、毎回のコードフォーマットに対して個別のnpm taskとしてシンプルに実行することはあまり生産的ではありません。ここでは`lint-staged`(と`husky`)が活躍します。`lint-staged` [here](https://github.com/okonet/lint-staged#configuration)の`husky` [here](https://github.com/typicode/husky)の設定をよく読みましょう。
<a name="logging"></a>
## 8. ログ
![Logging](/images/logging.png)
* クライアントサイドのconsole ログをプロダクション環境で出力するのは避けましょう。
_Why:_
> ビルドプロセスを通してConsoleログを取り除くことができます(すべきです)が、コードスタイルチェックが吐き出すconsole logについてのwarningの情報を確認しましょう。
* プロダクションのログは読みやすいように出力しましょう。理想的にはプロダクションモードで使われているロギングライブラリを使いましょう([winston](https://github.com/winstonjs/winston) もしくは
[node-bunyan](https://github.com/trentm/node-bunyan)のようなものがあります。)
_Why:_
> ログのカラー化やタイムスタンプ、ログファイルの出力や日々のログファイルのローテートが、トラブルシューティングの不快感を少なくしてくれます。
<a name="api"></a>
## 9. API
<a name="api-design"></a>
![API](/images/api.png)
### 9.1 APIデザイン
_Why:_
> 私たちは明快に構築されたRESTfulのインターフェースでの開発を強制することで、チームメンバーやクライアントがシンプルに矛盾なくそれを使えることができます。
_Why:_
> 一貫性やシンプルさがないAPIはシステムの結合やメンテナンスのコストを増加させます。だから`API design`をこのドキュメントに含めて説明しています。
* 私たちは多くの場面でリソース志向アーキテクチャに従っています。リソース志向アーキテクチャとは主にリソース、集合、URLの要素で構成されます。
* リソースはデータを持っていて、ネストを取得でき、それらのリソースを操作できるメソッドがあります。
* リソースの集合はコレクションと呼ばれます。
* URLはオンラインのリソースの場所はリソースかコレクションで表します。
_Why:_
> 上記のことは開発者(あなたのAPIを使う人たち)に周知されていることです。可読性や使いやすさを別としても、REST APIではそのAPIの詳細を知らずとも汎用なライブラリやコネクタを書くができます。
* URLにはkebab-caseを使いましょう。
* リクエスト内のパラメータやリソース内のパラメータにはcamelCaseを使いましょう。
* URL内のリソース名は複数形のkebab-caseにしましょう
* コレクションを表すurlには常に複数形の名詞を使いましょう。`/users`
_Why:_
> 基本的にはそうすることで読みやすさの向上URLの一貫性を維持することになるでしょう。[もっと読む...](https://apigee.com/about/blog/technology/restful-api-design-plural-nouns-and-concrete-names)
* ソースコード内での変数やプロパティ名の複数形はリストのサフィックスにしましょう。
_Why:_
> 複数形はURLにおいては良いものですが、ソースコード内では分かりにくくエラーの原因になり得ます。
* コレクションで始まり識別子に終わる単一のパスを常に使用しましょう。
```
/students/245743
/airports/kjfk
```
* 以下のようなURLは避けましょう。
```
GET /blogs/:blogId/posts/:postId/summary
```
_Why:_
> このURLはリソースではなく、プロパティをさしています。プロパティはレスポンスを整えるようにパラメータに渡しましょう。
* リソースを示すURLからは動詞を含めないようにしましょう。
_Why:_
> 各リソースの操作に動詞を含めると、各々のリソースの操作について大量のURLが出来てしまい、開発者にとって理解するのが難しい一貫性のないパターンになってしまうからです。私たちは他の箇所に動詞を使っています。
* リソースではない部分に動詞を使用しましょう。このケースではこのAPIはリソースを返さずに、操作を実行して結果を受け取るのみです。CRUD(Create Retrieve Update Delete)の操作ではないことに注意しましょう。
```
/translate?text=Hallo
```
_Why:_
> CRUDについてはリソースやコレクションのURLに対してHTTPメソッドを使用するからです。説明している動詞はおおよそ`Controller`となります。通常これらのURLをたくさん作成することはないでしょう。[もっと読む...](https://byrondover.github.io/post/restful-api-guidelines/#controller)
* リクエストボディやレスポンスタイプは`JSON`にしましょう。そして一貫性あるメンテナンスをしやすくするために、プロパティ名は`camelCase`を使用するようにしましょう。
_Why:_
> このドキュメントはJavaScriptプロジェクトのガイドラインであるため、JSONの読み書きにはJavaScriptが使用されてることを想定しています。
* リソースオブジェクトインスタンスやDBのレコードと同じような単一なものであったとしても、`table_name``column_name`はリソース名やプロパティ名にしないようにしましょう。
_Why:_
> あくまでリソースを公開するのであってDBのスキーマの詳細を公開するためのものではないからです。
* 念のためにもう一度、URLには名詞のみを使い、機能を説明するような名前付けは避けましょう。
_Why:_
> 名詞のみをリソースのURLには使用しましょう。`/addNewUser``/updateUse`のようなエンドポイントを用意するのはやめましょう。同様にリソース操作をパラメータを送るのも避けましょう。
* CRUDの機能的説明にはHTTPのメソッドを使いましょう。
_How:_
> `GET`: 存在するリソースの取得。
> `POST`: 新しいリソースとサブリソースの作成。
> `PUT`: 既存のリソースの更新。
> `PATCH`: 既存のリソースの更新。提供されたフィールドのみを更新し、他のフィールドはそのままにしておきます。
> `DELETE`: 存在するリソースの削除。
* ネストしているリソースのために関連するURL間にリレーションを使用しましょう。例えば会社の従業員を関連されるために、idを使用します。
_Why:_
> 各リソースを探索しやすくするための自然なやり方です。
_How:_
> `GET /schools/2/students `。2の学校のすべての生徒を取得できるはずです。
> `GET /schools/2/students/31` 。2の学校に所属する、31の生徒の詳細を取得できるはずです。
> `DELETE /schools/2/students/31` 。2の学校に所属する31の生徒を削除できるはずです。
> `PUT /schools/2/students/31` 。31の生徒の情報を更新するはずです。またPUTはコレクションには使用せずにリソースURLのみに使用するようにしましょう。
> `POST /schools`。新たな学校を作成して、その作成された学校の情報を返却するはずです。POSTはコレクションのURLに使用しましょう。
* バージョンには`v`をプレフィックスとした単純な整数を使用しましょう(v1,v2)。全てのURLを残したまま移動するために、バージョンは一番上のスコープに使用しましょう。
```
http://api.domain.com/v1/schools/3/students
```
_Why:_
> APIがサードパーティのために公開される時には、APIの破壊的変更を伴うバージョンアップは既存のプロダクトやAPIを使うサービスに多大な影響を与えます。バージョンをURLに含めることで、これらの問題が起きることを防いでくれます。[もっと読む...](https://apigee.com/about/blog/technology/restful-api-design-tips-versioning)
* レスポンスメッセージは自己記述的でなければなりません。良いエラーレスポンスは以下のようなものになります。
```json
{
"code": 1234,
"message" : "Something bad happened",
"description" : "More details"
}
```
またバリデーションエラーならこうです。
```json
{
"code" : 2314,
"message" : "Validation Failed",
"errors" : [
{
"code" : 1233,
"field" : "email",
"message" : "Invalid email"
},
{
"code" : 1234,
"field" : "password",
"message" : "No password provided"
}
]
}
```
_Why:_
> APIを使用したアプリケーションがそのユーザーの手元に届けられたあと、問題解決やトラブルシューティングをする重要な時に、開発者は良いデザインのエラーメッセージに頼ることになります。
_Note: セキュリティの例外のメッセージは極力一般化しましょう。例えば"パスワードが間違っています"と言う代わりに、"ユーザー名もしくはパスワードが間違っています"と言いましょう。私たちの場合はユーザー名が正しくて、パスワードだけ間違っていると伝えることはしないようにしています。_
* **全てがうまく動いていた**、**クライアントアプリがうまく動いてなかった** 、**APIがうまく動いてなかった** 等
レスポンスの説明には8個のステータスのみを送るようにしましょう。
_一覧:_
> `200 OK` `GET``PUT``POST`リクエストが成功したことを表します。
> `201 Created` 新しいインスタンスが作成された時に返却されます。新しいインスタンスの作成、`POST`メソッドの使用は`201`のステータスコードを返します。
> `304 Not Modified` ユーザーがすでにレスポンスのキャッシュを持っている場合に返却されます、最小の転送に抑えることになります。
> `400 Bad Request` リクエストが処理されなかった場合に返却されます。サーバーがクライアントの要求するリクエストを理解できなかったような時です。
> `401 Unauthorized` リクエストの認証情報が不足している時に返却されます。要求された認証情報で再リクエストを行うことになるでしょう。
> `403 Forbidden` サーバーはリクエストを解釈できていますが、認証を拒否したという意味です。
> `404 Not Found` リクエストしたリソースが見つからなかったことを示します。
> `500 Internal Server Error` リクエストは正しいが、サーバーが予期せぬ事態により動作しなかったことを示します。
_Why:_
> 多くのAPIの提供者は少数のHTTPのステータスコードを使用します。例えばGoogleのGdata APIは10個のステータスコードしか使っていません。Netflixは9つです。Diggは8つだけです。もちろんながらこれらのレスポンスは追加の情報をbodyに含めています。70を超えるHTTPのステータスが存在しますが。あまり一般的でないステータスコードを選択すると、アプリケーションの開発者は開発を離れて、ステータスコードが何を示しているのかを理解しようとwikipedia等で調べざるを得なくなります。[もっと読む...](https://apigee.com/about/blog/technology/restful-api-design-what-about-errors)
* レスポンスにはリソースの数の合計を提供しましょう。
* `limit``offset`のパラメータを受けつけましょう。
* リソースの公開するデータ量はよく考える必要があります。APIの利用者は常にリソースの全ての表現が必要というわけではありません。フィールドのカンマ区切りリストを含むフィールドクエリパラメータを使用します。
```
GET /student?fields=id,name,age,class
```
* ページネーション、フィルタリング、ソートは初めから全てのリソースをサポートする必要はありません。フィルタリングやソートのあとにこれらのリソースを記述しましょう。
<a name="api-security"></a>
### 9.2 APIセキュリティ
いくつかのセキュリティのベストプラクティスをご紹介します。
* セキュアな通信(HTTPS)以外ではベーシック認証を使わないようにしましょう。認証トークンをURLに含めてはいけません。`GET /users/123?token=asdf....`
_Why:_
> トークンやユーザーIDやパスワードが平文としてネットワークを超えてくるのでbase64にエンコードされているでしょうが、base64は可逆なエンコード方法です。、ベーシック認証機構はセキュアではないです。[もっと読む...](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication)
* トークンは毎回のリクエストの認証ヘッダーに乗せて送信されなければなりません。`Authorization: Bearer xxxxxx, Extra yyyyy`
* 認証コードの生存期間は短く設定されるべきです。
* 安全ではないデータの受け渡しを避けるためにHTTPリクエストに応答しないことでTLSではないリクエストを拒否するようにしましょう。その際には`403 Forbidden`で応答しましょう。
* リクエスト制限を使うことを考えましょう。
_Why:_
> 一時間あたり何千ものリクエストを送りつけてくるボットから身を守るために、リクエスト制限を早いうちから考えておくべきでしょう。
* HTTPヘッダを適切に設定することはWebアプリケーションをより強固に、より安全にするのに役立ちます。[もっと読む...](https://github.com/helmetjs/helmet)
* APIは標準的なフォームのデータを受け取ってデータを加工しましょう。できなければリクエストを拒否するようにしましょう。400 Bad Requestとともにデータの不足やエラーについての詳細を返却しましょう。
* RESTなAPIで交換される全てのデータはAPI上でValidateするようにしましょう。
* JSONをシリアライズしましょう。
_Why:_
> JSONエンコーダの悩みの種は、ブラウザ内でリモートからの任意のJavaScriptの実行を防ぐことです。もしくはnode.jsを使用しているのであれば、サーバーサイドも同様です。ユーザーから与えられた入力がブラウザ内で実行されないように、ユーザーからの情報をエンコードできる適切なJSONシリアライザーを使用することが重要です。
* Content-TypeをValidateするようにしましょう。多くの場合で `application/*json` (Content-Typeヘッダ)を使いましょう。
_Why:_
> 例えば、`application/x-www-form-urlencoded`のmime-typeを受け入れることは、攻撃者にフォームを作成させ、シンプルなPOSTリクエストを誘引させることを許すことになります。サーバは受け入れるContent-Typeを決して推定させないべきです。Content-Typeヘッダもしくは予期しないContent-Typeヘッダに対しては`4XX`のレスポンスでリクエストを拒否する結果を返却しましょう。
* APIのセキュリティをチェックリストを見て確認しましょう。[もっと読む...](https://github.com/shieldfy/API-Security-Checklist)
<a name="api-documentation"></a>
### 9.3 APIドキュメント
* [README.md template](./README.sample.md)の`API Reference`のセクションを埋めましょう。
* コードのサンプルとともにAPIの認証方法について記述しましょう。
* URLの構造(pathについてのみでいいです。rootのURLについては必要ありません。)をリクエストのメソッドとともに説明しましょう。
各エンドポイントについて
* URLパラメータはもし存在する場合は、URLセクションに記載されている名前に従って指定しましょう。
```
Required: id=[integer]
Optional: photo_id=[alphanumeric]
```
* リクエストタイプがPOSTなら、ちゃんと動く例も用意しましょう。URLパラメータのルールはここにも適用します。OptionalとRequiredに分けましょう。
* レスポンスの成功の場合ステータスコードは何でしょうかどんなデータを返されるでしょうかドキュメントはAPIの返答を開発者が知りたいときに役立ちます。
```
Code: 200
Content: { id : 12 }
```
* レスポンスの失敗の時は、ほとんどのエンドポイントの失敗は複数通りあります。認証されていないアクセスからの不正な値等。それら全てをここでは列挙しましょう。繰り返しになりますが、こうすることで憶測のみで開発せざるを得ない状況を防ぎます。例
```json
{
"code": 403,
"message" : "Authentication failed",
"description" : "Invalid username or password"
}
```
* APIデザインツールを使用しましょう。[API Blueprint](https://apiblueprint.org/)、[Swagger](https://swagger.io/)のようなオープンソースの良いドキュメンテーションツールがたくさんあります。
<a name="licensing"></a>
## 10. ライセンス
![Licensing](/images/licensing.png)
使用できる権利のあるリソースを使用していることを確認してください。ライブラリを使っているのであれば、MIT、Apache、BSDのライセンスを見つけることを心がけましょう。ライブラリを修正したいのであれば、ライセンスの詳細を少し見て見ましょう。著作権で保護されている画像や動画が法的問題を引き起こすかもしれません。
---
Sources:
[RisingStack Engineering](https://blog.risingstack.com/),
[Mozilla Developer Network](https://developer.mozilla.org/),
[Heroku Dev Center](https://devcenter.heroku.com),
[Airbnb/javascript](https://github.com/airbnb/javascript),
[Atlassian Git tutorials](https://www.atlassian.com/git/tutorials),
[Apigee](https://apigee.com/about/blog),
[Wishtack](https://blog.wishtack.com)
Icons by [icons8](https://icons8.com/)

775
README-ko.md Normal file
View File

@ -0,0 +1,775 @@
[ENGLISH](./README.md)
| [中文版](./README-zh.md)
| [日本語版](./README-ja.md)
| [РУССКИЙ](./README-ru.md)
| [Português](./README-pt-BR.md)
[<img src="./images/elsewhen-logo.png" width="180" height="180">](https://www.elsewhen.com/)
# Project Guidelines &middot; [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
> 새로운 프로젝트를 개발하는 할 때는 초원에서 뛰어노는 것 같지만, 유지보수는 모두에게 잠재적인 악몽입니다.
이것은 우리가 발견하고, 작성하고 수집한 가이드라인의 목록입니다. 이 가이드라인은 대부분의 [elsewhen](https://www.elsewhen.com)에서의 JavaScript 프로젝트에 잘 맞습니다.
만약 모범 사례를 공유하고 싶으시거나 여기에 있는 가이드라인 중 어떤 것이 지워져야 한다고 생각하신다면, [부담없이 우리에게 공유해주세요](http://makeapullrequest.com).
- [Git](#git)
- [Git 규칙](#some-git-rules)
- [Git 워크플로우](#git-workflow)
- [좋은 커밋 메시지 작성하기](#writing-good-commit-messages)
- [문서화](#documentation)
- [환경](#environments)
- [일관적인 개발환경](#consistent-dev-environments)
- [일관적인 의존성](#consistent-dependencies)
- [의존성](#dependencies)
- [테스트](#testing)
- [구조 및 네이밍](#structure-and-naming)
- [코드 스타일](#code-style)
- [코드 스타일 가이드라인](#code-style-check)
- [표준 코드 스타일 강제하기](#enforcing-code-style-standards)
- [로깅](#logging)
- [API](#api)
- [API 설계](#api-design)
- [API 보안](#api-security)
- [API 문서화](#api-documentation)
- [라이센스](#licensing)
<a name="git"></a>
## 1. Git
![Git](/images/branching.png)
<a name="some-git-rules"></a>
### 1.1 Git 규칙
Git에는 명심해야할 규칙들이 있습니다.
* feature 브랜치(branch)에서 작업하세요.
_이유:_
> 이 방법을 사용하면 모든 작업은 메인 브랜치 대신에 격리된 별도의 브랜치에서 하게 됩니다. 이렇게 하면 혼란 없이 여러개의 풀 리퀘스트(Pull Request)를 제출할 수 있습니다. 또한 잠재적으로 불안정한, 완료되지 않은 코드로 마스터 브랜치를 오염시키지 않고, 작업을 반복할 수 있습니다. [더 알아보기](https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow)
* `develop`에서 브랜치를 만드세요.
_이유:_
>이 방법을 사용하면, 마스터 브랜치의 코드를 항상 거의 문제없이 빌드할 수 있고, 릴리즈를 위해서 직접 사용할 수도 있습니다 (일부 프로젝트의 경우 과할 수도 있음).
* `develop``master`에 직접 푸시하지 않고, 풀 리퀘스트를 만드세요.
_이유:_
> 풀 리퀘스트는 기능 구현을 완료한 것을 다른 팀 멤버들에게 알립니다. 또한 쉬운 코드 리뷰를 가능케 하며, 제안된 기능에 대해 토론할 수 있는 포럼을 제공합니다.
* 개발한 기능을 푸시하고 풀 리퀘스트를 만들기 전에, 로컬 `develop` 브랜치를 업데이트하고 인터랙티브한 리베이스(rebase)를 진행하세요.
_이유:_
> 리베이스는 요청한 브랜치(`master` 혹은 `develop`)을 병합(merge)합니다. 또한 병합 커밋을 만들지 않으면서 로컬에서 만든 커밋들을 적용합니다 (충돌이 없다고 가정한다면). 결국 깨끗한 히스토리를 남기게 됩니다. [더 알아보기](https://www.atlassian.com/git/tutorials/merging-vs-rebasing)
* 풀 리퀘스트를 만들기 전에 리베이스하는 동안 잠재적인 충돌을 제거하세요.
* 병합 후, 로컬과 원격에 있는 feature 브랜치를 삭제하세요.
_이유:_
> 이 방법은 더 이상 사용하지 않는 브랜치들로부터 브랜치 리스트를 정리할 것입니다. 또한, 브랜치가 `master` 또는 `develop`으로 병합되는 것을 단 한 번으로 보장합니다. feature 브랜치는 작업이 진행되고 있는 도중에만 존재해야 합니다.
* 풀 리퀘스트를 생성하기 전에, feature 브랜치는 잘 빌드되는지, 코드 스타일 체크를 포함한 모든 테스트를 통과하는 지 검증하세요.
_이유:_
> 안정적인 브랜치에 코드를 새로 푸시하려 할 때, 만약 feature 브랜치의 테스트가 실패한다면, 목표한 브랜치의 빌드도 실패할 가능성이 높습니다. 또한 풀 리퀘스트를 만들기 전에 코드 스타일 검사를 적용해야합니다. 이렇게 하면 가독성을 높이고, 코드에 실제 변경사항을 작성할 때 포맷을 수정하는 변경사항이 섞일 가능성을 낮춥니다.
* 이 [.gitignore file](./.gitignore)을 사용하세요.
_이유:_
> 이 파일에는 이미 원격 저장소에 코드와 함께 보내면 안되는 시스템 파일 목록이 있습니다. 또한 이 파일은 가장 많이 사용되는 에디터와 대부분의 공통 의존성 폴더에 대한 폴더 및 파일 설정을 포함하고 있습니다.
* `develop``master` 브랜치를 보호하세요.
_이유:_
> 이 방법은 예측하지 못한, 돌이킬 수 없는 변경으로부터 production-ready 브랜치들을 보호합니다. 더 알아보기: [Github](https://help.github.com/articles/about-protected-branches/), [Bitbucket](https://confluence.atlassian.com/bitbucketserver/using-branch-permissions-776639807.html)
<a name="git-workflow"></a>
### 1.2 Git 워크플로우
상기한 이유들 때문에, 우리는 [인터랙티브 리베이스](https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing), 그리고 [Gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows#gitflow-workflow)의 몇가지 요소(브랜치 네이밍과 develop 브랜치의 보유)와 함께 [Feature 브랜치 워크플로우](https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow)를 사용해야 합니다. 주요 단계는 다음과 같습니다.
* 새로운 프로젝트의 경우, 프로젝트 디렉토리에 Git 레포지토리를 초기화하세요. __유지보수 작업의 경우 이 단계는 무시하세요__.
```sh
cd <project directory>
git init
```
* 새로운 feature/bug-fix 브랜치를 체크아웃하세요.
```sh
git checkout -b <branchname>
```
* 변경사항을 작성하세요.
```sh
git add
git commit -a
```
_이유:_
> `git commit -a`는 제목과 본문을 분리시킨 상태로 에디터를 엽니다. *섹션 1.3*에서 자세히 알아보세요.
* 놓친 변경사항을 받기 위해 원격 저장소와 동기화하세요.
```sh
git checkout develop
git pull
```
_이유:_
> 이렇게 하면 충돌(conflict)을 포함하는 풀 리퀘스트를 만드는 대신에, 당신의 컴퓨터에서 리베이스함으로써 충돌을 처리할 수 있습니다.
* 인터랙티브한 리베이스를 통해 develop 브랜치의 마지막 변경사항을 feature 브랜치로 업데이트 하세요.
```sh
git checkout <branchname>
git rebase -i --autosquash develop
```
_이유:_
> --autosquash를 사용해서 모든 커밋을 하나의 커밋으로 밀어 넣을 수도 있습니다. develop 브랜치에서 하나의 기능을 위한 많은 커밋들은 아무도 원하지 않기 때문이죠. [더 알아보기](https://robots.thoughtbot.com/autosquashing-git-commits)
* 만약 충돌이 발생하지 않았다면 이 단계를 건너뛰어도 좋습니다. 충돌이 발생했다면, [그것을 해결(resolve)하고](https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/) 리베이스를 계속하세요.
```sh
git add <file1> <file2> ...
git rebase --continue
```
* 브랜치를 푸시하세요. 리베이스는 이력을 변경시킵니다. 따라서 당신은 `-f`를 사용해서 원격 브랜치로 강제 변경해야합니다. 만약 다른 누군가가 당신의 브랜치에서 작업하고 있다면, 조금 덜 파괴적인 `--force-with-lease`를 사용하세요.
```sh
git push -f
```
_이유:_
> 리베이스 할 때, 당신은 feature 브랜치의 이력을 변경하고 있는 겁니다. 그 결과, Git은 일반적인 `git push`를 거부합니다. 대신, 당신은 -f 혹은 --force 플래그를 사용할 필요가 있습니다. [더 알아보기](https://developer.atlassian.com/blog/2015/04/force-with-lease/)
* 풀 리퀘스트를 만드세요.
* 풀 리퀘스트는 리뷰어에 의해 수용되고, 병합되고 종료될 것 입니다.
* 모든 작업이 끝났다면 당신의 로컬 feature 브랜치는 지우세요.
```sh
git branch -d <branchname>
```
원격 저장소에 존재하지 않는 모든 브랜치를 제거하기 위해서는 다음과 같이 하면 됩니다.
```sh
git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done
```
<a name="writing-good-commit-messages"></a>
### 1.3 좋은 커밋 메시지 작성하기
커밋을 작성하는 좋은 가이드라인을 가지고 있으면 Git으로 작업하거나 다른 사람들과 협업하는 것이 상당히 쉬워집니다. 다음은 그 규칙들입니다. ([출처](https://chris.beams.io/posts/git-commit/#seven-rules))
* 줄 바꿈을 통해서 제목과 본문을 구분하세요.
_이유:_
> Git은 당신의 커밋 메시지의 첫번째 줄을 요약으로 분간할만큼 똑똑합니다. 사실, git log 대신에 git shortlog를 사용하면 커밋 ID와 요약정보만이 표시된 커밋 메시지의 긴 리스트를 볼 수 있습니다.
* 제목을 50자로, 본문은 72자로 제한하세요.
_이유:_
> 커밋은 가능한 보기 좋고 집중되어야하며, 장황하게 설명해서는 안됩니다. [더 알아보기](https://medium.com/@preslavrachev/what-s-with-the-50-72-rule-8a906f61f09c)
* 제목에 대문자를 사용하세요.
* 제목을 마침표로 끝내지마세요.
* 제목에 [명령법(imperative mood)](https://en.wikipedia.org/wiki/Imperative_mood)을 사용하세요.
_이유:_
> 커미터가 완료한 일을 표현하는 메시지를 작성하는 것이 아닙니다. 이런 메시지들은 커밋이 레포지토리에 적용된 뒤에 어떻게 되는지를 설명하는 것으로 간주하는 것이 낫습니다. [더 읽기](https://news.ycombinator.com/item?id=2079612)
* 본문은 **어떻게** 대신 **무엇을**과 **왜**를 설명하는데 사용하세요.
<a name="documentation"></a>
## 2. 문서화
![문서화](/images/documentation.png)
* `README.md`를 위해서 이 [템플릿](./README.sample.md)을 사용하세요. 필요한 섹션은 자유롭게 추가하세요.
* 한 개 이상의 레포지토리가 있는 프로젝트는 각각의 `README.md` 파일에 링크를 추가해주세요.
* 프로젝트가 발전함에 따라 `README.md`를 최신으로 유지하세요.
* 코드에 주석을 달아주세요. 가능하다면, 각 섹션에서 무엇을 표현하려고 하는지 명확하게 만드세요.
* GitHub 혹은 StackOverflow에 당신이 사용한 접근법이나 코드에 대한 토론이 있다면, 주석에 그 링크를 첨부하세요.
* 주석을 나쁜 코드에 대한 변명으로 사용하지 마세요. 코드를 깔끔하게 유지하세요.
* 클린 코드는 주석을 전혀 달지 않는 것에 대한 변명이 아닙니다.
* 코드가 발전함에 따라 주석도 적절하게 바꿔주세요.
<a name="environments"></a>
## 3. 환경
![환경](/images/laptop.png)
* 필요하다면 `development`, `test``production` 환경을 분리하세요.
_이유:_
> 다른 데이터, 토큰, API, 포트 등... 아마도 별도의 환경을 필요로 할 것입니다. 아마도 당신은 격리된 `development` 모드에서는 가짜 API를 호출하고 예상가능한 데이터를 리턴해서 수동/자동 테스트를 보다 쉽게 할 수 있게 하는 것을 원할 겁니다. 혹은 Google Analytics를 `production` 모드에서만 사용하고 싶을 수도 있습니다. [더 읽기](https://stackoverflow.com/questions/8332333/node-js-setting-up-environment-specific-configs-to-be-used-with-everyauth)
* 배포에 관련된 설정 변수들은 환경 변수에서 불러오도록 하고 그 변수들을 코드 베이스에 상수로 포함하지 마세요. [이 샘플을 참고하세요](./config.sample.js).
_이유:_
> 당신은 토큰이나 비밀번호 혹은 그 외에 중요한 정보를 가지고 있을 겁니다. 언제든지 코드베이스를 공개할 수 있을 것처럼 설정 변수는 어플리케이션의 내부와 제대로 구분되어야 합니다.
_방법:_
> `.env` 파일을 당신의 변수들을 저장하는 용도로 사용하고, 그 파일을 `.gitignore`에 넣어 제외하세요. 대신에, 다른 개발자들에게 가이드를 제공하는 `.env.example` 이라는 파일을 커밋하세요. 프로덕션 환경에서는 표준적인 방법으로 환경 변수를 설정헤야 합니다. [더 읽기](https://medium.com/@rafaelvidaurre/managing-environment-variables-in-node-js-2cb45a55195f)
* 어플리케이션이 실행되기 전에 환경 변수를 검증(validate)하는 것을 추천합니다. 값들을 검증하기 위해 `joi`를 사용하고 있는 [이 샘플을 참고하세요](./configWithTest.sample.js).
_이유:_
> 다른 이들을 트러블슈팅에서 구해낼 수 있습니다.
<a name="consistent-dev-environments"></a>
### 3.1 일관적인 개발 환경
* `package.json``engines`에 Node.js 버전을 설정하세요.
_이유:_
> 다른 이들에게 프로젝트가 동작하는 Node.js 버전에 대해 알려줄 수 있습니다. [더 읽기](https://docs.npmjs.com/files/package.json#engines)
* 추가로, `nvm`을 사용하고 `.nvmrc` 파일을 프로젝트의 루트 경로에 만드세요. 문서에 그것을 명시하는 것도 잊지마세요.
_이유:_
> `nvm`을 사용하는 사람이라면 `nvm use` 명령어를 사용해서 간단하게 적절한 Node.js 버전으로 전환할 수 있습니다. [더 읽기](https://github.com/creationix/nvm)
* `preinstall`을 사용해서 Node.js와 npm 버전을 체크하는 것도 좋은 방법입니다.
_이유:_
> 어떤 의존(dependency)은 새로운 npm 버전으로 설치할 때 실패할 수도 있습니다.
* 가능하다면 도커 이미지를 사용하세요.
_이유:_
> 도커는 전체적인 워크플로우에 걸쳐 일관적인 환경을 제공합니다. 사용하지 않으면 의존성 혹은 설정에 많은 작업이 필요할 수도 있습니다. [더 읽기](https://hackernoon.com/how-to-dockerize-a-node-js-application-4fbab45a0c19)
* 글로벌로 모듈을 설치하지 말고 로컬 모듈을 사용하세요.
_이유:_
> 당신의 툴을 동료들이 글로벌로 설치하지 않고 당신이 사용하는 툴을 공유하도록 해줍니다.
<a name="consistent-dependencies"></a>
### 3.2 일관적인 의존성
* 다른 팀 멤버들이 당신과 정확히 같은 의존성을 갖도록 하세요.
_이유:_
> 왜냐면 당신은 어떤 개발 기기에서도 코드가 예상한대로 동일하게 동작하는 것을 원하니까요. [더 읽기](https://medium.com/@kentcdodds/why-semver-ranges-are-literally-the-worst-817cdcb09277)
_방법:_
> `npm@5` 이상의 버전에서 `package-lock.json`을 사용하세요.
_저는 npm@5 버전 미만이에요:_
> 대안으로 `Yarn`을 사용할 수 있습니다. `README.md`에 Yarn에 대해 확실히 명시하세요. 당신의 락(lock) 파일과 `package.json` 파일은 각 의존성 업데이트 후 동일한 버전을 가져야 합니다. [더 읽기](https://yarnpkg.com/en/)
_저는 `Yarn`이라는 이름이 싫은데요:_
> 유감입니다. 구 버전의 `npm`에서는 새로운 의존을 설치할 때 `-—save --save-exact`를 사용해서 올리기 전에 `npm-shrinkwrap.json`을 생성하세요. [더 읽기](https://docs.npmjs.com/files/package-locks)
<a name="dependencies"></a>
## 4. 의존성
![Github](/images/modules.png)
* `npm ls --depth=0`를 사용해서 현재 사용 가능한 패키지를 추척하세요. [더 읽기](https://docs.npmjs.com/cli/ls)
* `depcheck`를 사용해서 패키지 중에 사용되지 않거나 관련이 없는 패키지가 있는지 확인하세요. [더 읽기](https://www.npmjs.com/package/depcheck)
_이유:_
> 당신은 쓰이지 않고 있는 라이브러리를 당신의 코드에 포함할 수도 있고 그로인해 프로덕션의 번들 사이즈가 커집니다. 쓰이지 않는 의존성을 찾아 제거하세요.
* 의존을 사용하기 전에, `npm-stat`을 사용해 커뮤니티에서 잘 사용되는 패키지인지 확인하기 위해서 다운로드 통계를 확인하세요. [더 읽기](https://npm-stat.com/)
_이유:_
> 대개, 사용량이 많을 수록 기여자(contributor)가 더 많아지므로, 유지 보수가 잘 됩니다. 또한, 이로 인해 버그가 빠르게 발견되고 고쳐집니다.
* 의존을 사용하기 전에, 많은 메인테이너와 함께, 성숙한 버전 릴리즈 주기가 있는지 확인하세요. 예: `npm view async` [더 읽기](https://docs.npmjs.com/cli/view)
_이유:_
> 아무리 많은 컨트리뷰터가 있어도 메인테이너들이 패치를 충분히 빠르게 머지(merge)하지 않으면 소용이 없습니다.
* 덜 알려진 의존성이 필요한 경우, 그걸 사용하기 전에 팀 내에서 의논하세요.
* `npm outdated`를 사용해서 당신의 어플리케이션이 깨지지 않고 의존 패키지의 최신 버전으로 동작하도록 만드세요. [더 읽기](https://docs.npmjs.com/cli/outdated)
_이유:_
> 의존은 때때로 깨트리는 변화(breaking change)를 담은 채로 업데이트 됩니다. 항상 업데이트가 있을 때마다 릴리즈 노트를 확인하세요. 당신의 의존성을 한 번에 하나씩 업데이트하면, 뭔가 잘못되었을 때 트러블슈팅이 쉬워집니다. [npm-check-updates](https://github.com/tjunnone/npm-check-updates) 같이 좋은 툴을 활용하세요.
* [Snyk](https://snyk.io/test?utm_source=risingstack_blog) 같은 것을 사용해서 패키지에 알려진 보안 취약점이 있는지 확인하세요.
<a name="testing"></a>
## 5. 테스트
![Testing](/images/testing.png)
* 필요하다면 `test` 모드를 만드세요.
_이유:_
> 때때로 프로덕션 모드로도 End-to-End 테스트에 충분할 수도 있지만, 예외는 항상 있습니다. 예를 들어, 당신은 프로덕션 모드를 사용해서 다른 사람의 대시보드를 테스트 데이터로 오염시키는 것을 원하지 않을 수도 있습니다. 다른 예로, 프로덕션 모드에서 당신이 사용하는 API는 호출 수 제한을 가져서, 일정량의 요청 후에는 테스트 호출을 차단할 수 있습니다.
* 테스트 파일을 테스트 되는 모듈과 같은 경로에 위치시키고 `moduleName.spec.js` 처럼 `*.test.js``*.spec.js` 같은 네이밍 컨벤션으로 이름을 지어주세요.
_이유:_
> 유닛 테스트를 찾기 위해서 폴더 구조를 다 뒤지길 원하는 사람은 없을 겁니다. [더 읽기](https://hackernoon.com/structure-your-javascript-code-for-testability-9bc93d9c72dc)
* 혼란을 방지하기 위해 추가적인 테스트 파일들은 별도의 테스트 폴더에 넣으세요.
_이유:_
> 몇몇 테스트 파일들은 여러 개의 구현 파일과 관련이 있습니다. 당신은 그 파일들을 다른 개발자들이 찾을 가능성이 큰 `__test__` 폴더에 집어 넣어야 합니다. 또한, 이제 이 `__test__`라는 이름은 표준이며, 대부분의 JavaScript 테스트 프레임워크에 의해 사용되고 있습니다.
* 테스트 가능한 코드를 작성하세요. 사이드 이펙트를 피하세요. 사이드 이펙트를 분리하세요. 순수 함수를 작성하세요.
_이유:_
> 당신은 비즈니스 로직을 별개의 유닛으로 분리해 테스트 하기를 원할 겁니다. 그렇다면 당신은 "무작위의 영향과 코드 안정성에 대한 비결정적(nondeterministic) 프로세스를 최소화" 해야 합니다. [더 읽기](https://medium.com/javascript-scene/tdd-the-rite-way-53c9b46f45e3)
> 순수 함수는 같은 입력에 대해 항상 같은 출력을 돌려주는 함수를 말합니다. 반대로, 불순(impure) 함수는 사이드 이펙트를 포함하고 있거나 값을 얻기 위해 바깥의 상태에 의존하는 함수를 말합니다. 이러한 특징은 함수를 예측하기 어렵게 만듭니다. [더 읽기](https://hackernoon.com/structure-your-javascript-code-for-testability-9bc93d9c72dc)
* 정적 타입 분석기를 활용하세요.
_이유:_
> 이따금 당신은 정적 타입 분석기가 필요할 수도 있습니다. 정적 타입 분석기는 코드에 일정 수준의 신뢰도를 제공합니다. [더 읽기](https://medium.freecodecamp.org/why-use-static-types-in-javascript-part-1-8382da1e0adb)
* `develop`에 풀 리퀘스트를 만들기 전에 테스트를 로컬로 돌리세요.
_이유:_
> 프로덕션 준비된 브랜치의 빌드를 실패한 사람이 되고 싶진 않을 겁니다. 당신의 기능 브랜치를 원격 저장소에 푸시하기 전에 먼저 `rebase` 한 뒤 테스트를 돌리세요.
* `README.md` 파일의 적절한 섹션에 설명을 포함해서 테스트에 대해 문서화하세요.
_이유:_
> 다른 개발자 혹은 DevOps 전문가나 QA, 아니면 당신의 코드를 가지고 일하는 운 좋은 누군가에게 남겨두는 편리한 메모입니다.
<a name="structure-and-naming"></a>
## 6. 구조 및 네이밍
![Structure and Naming](/images/folder-tree.png)
* 프로덕트를 구성하는 파일을 역할이 아닌 기능, 페이지, 컴포넌트 단위로 구성하세요. 또한, 테스트 파일은 구현 파일과 같은 경로에 두세요.
**Bad**
```
.
├── controllers
| ├── product.js
| └── user.js
├── models
| ├── product.js
| └── user.js
```
**Good**
```
.
├── product
| ├── index.js
| ├── product.js
| └── product.test.js
├── user
| ├── index.js
| ├── user.js
| └── user.test.js
```
_이유:_
> 긴 파일 리스트 대신에, 테스트를 포함해서 하나의 책임을 캡슐화한 작은 모듈을 만들게 될 겁니다. 그렇게 하면 파일 탐색이 훨씬 쉬워지고, 훑어봐도 파일을 찾을 수 있습니다.
* 혼란을 방지하기 위해 추가적인 테스트 파일들은 별도의 테스트 폴더에 넣으세요.
_이유:_
> 다른 개발자 혹은 DevOps 전문가 들의 시간을 아껴줄 수 있습니다.
* `./config` 폴더를 사용하고 다른 환경을 위해 다른 설정 파일을 만들지 마세요.
_이유:_
> 서로 다른 목적(데이터베이스, API 등)을 위해 설정 파일을 분리할 때, 그 파일들을 한 폴더에 넣고 `config` 처럼 잘 알려진 이름을 가진 폴더에 넣으면 됩니다. 그냥 다른 환경을 위해 다른 설정 파일을 만들지 말라는 것만 기억하세요. 그렇게 하면 깔끔하게 확장할 수 없습니다. 앱의 더 많은 배포판이 만들어지면 새로운 환경의 이름이 필요합니다. 설정 파일에서 사용되는 값들은 환경 변수에 의해 제공되어야 합니다. [더 읽기](https://medium.com/@fedorHK/no-config-b3f1171eecd5)
* 스크립트 파일들은 `./scripts` 폴더에 넣으세요. `bash``node` 스크립트를 포함해서요.
_이유:_
> 당신은 프로덕션 빌드, 개발용 빌드, 데이터베이스 공급, 데이터베이스 동기화 등, 최소 1개 이상의 스크립트를 필요로 할 가능성이 높습니다.
* `./build` 폴더에 빌드 결과물을 위치시키도록 하세요. 그리고 `.gitignore``build/`를 추가하세요.
_이유:_
> 취향대로 이름을 지으세요. `dist`도 괜찮습니다. 하지만 팀 내에서 일관성을 지키도록 하세요. 그 안에 들어가는 것은 대부분 생성되거나(번들되거나, 컴파일되거나, 트랜스파일되거나) 옮겨진 파일일 가능성이 높습니다. 당신이 생성할 수 있다면, 당신의 팀원도 생성할 수 있을 것이므로 그 파일들을 원격 저장소에 올릴 필요는 없습니다. 특별히 필요한 경우가 아니라면요.
* 파일명과 디렉토리명을 위해 `PascalCase``camelCase`를 사용하세요. `PascalCase`는 컴포넌트용으로만 사용하세요.
* `CheckBox` 컴포넌트를 위해서 `CheckBox/index.js``CheckBox.js`를 사용하세요. 하지만 장황한 `CheckBox/Checkbox.js` 혹은 `checkbox/CheckBox.js`는 사용하지 **마세요**.
* 이상적으로는, `index.js`에서 디폴트로 내보내는 모듈의 이름이 디렉토리의 이름과 일치해야 합니다.
_이유:_
> 그러면 부모 폴더만 그냥 간단히 불러와도 당신이 받게 될 컴포넌트나 모듈이 뭔지 예상할 수 있게 됩니다.
<a name="code-style"></a>
## 7. 코드 스타일
![Code style](/images/code-style.png)
<a name="code-style-check"></a>
### 7.1 코드 스타일 가이드라인
* 새로운 프로젝트에는 stage-2 이상의 현대적인 JavaScript 문법을 사용하세요. 오래된 프로젝트에서는 프로젝트를 현대화(modernize)할 계획이 없다면 일관성을 위해 기존 문법을 유지하세요.
_이유:_
> 이것은 모두 당신에게 달렸습니다. 우리는 새로운 문법의 장점을 사용하기 위해 트랜스파일러를 사용합니다. stage-2는 약간의 사소한 수정이 있을 수는 있지만, 결국 스펙의 일부가 될 겁니다.
* 빌드 프로세스에 코드 스타일 체크를 포함하세요.
_이유:_
> 빌드를 깨트리는 건 당신의 코드에 스타일을 강제하는 방법 중 하나입니다. 그렇게 하면 당신이 코드 스타일을 유지하는 데에 더 진지해질 겁니다. 클라이언트, 서버 양 쪽 모두에 하세요. [더 읽기](https://www.robinwieruch.de/react-eslint-webpack-babel/)
* 코드 스타일을 강제하기 위해 [ESLint](http://eslint.org/)를 사용하세요.
_이유:_
> 꼭 `eslint`를 선택할 필요는 없지만 우리는 `eslint`를 선호합니다. `eslint`는 더 많은 룰을 지원하고, 규칙을 설정하거나 추가할 수도 있습니다.
* 우리는 JavaScript에 [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript)를 사용합니다. ([더 읽기](https://www.gitbook.com/book/duk/airbnb-javascript-guidelines/details)) 프로젝트나 팀이 요구하는 JavaScript 스타일 가이드를 사용하세요.
* [FlowType](https://flow.org/)을 사용할 때, 우리는 [ESLint용 Flow type 스타일 체크 룰](https://github.com/gajus/eslint-plugin-flowtype)을 사용합니다.
_이유:_
> Flow는 약간의 문법을 제공합니다. 그 문법 역시 특정한 코드 스타일을 따르고 체크되어야할 필요가 있습니다.
* 코드 스타일 체크로부터 파일이나 폴더를 제외하기 위해 `.eslintignore`를 사용하세요.
_이유:_
> 스타일 체크로부터 몇 몇 파일을 제외할 때마다 `eslint-disable` 주석으로 코드를 더럽게 만들 필요가 없습니다.
* 풀 리퀘스트를 만들기 전에 `eslint` 비활성화 주석을 제거하세요.
_이유:_
> 코드를 짜는 동안 로직에 집중하기 위해서 스타일 체크를 비활성화 하는 건 일상적인 일입니다. 그냥 `eslint-disable` 주석을 비활성화하는 걸 잊지말고 규칙을 따르세요.
* 작업의 크기에 따라서 `//TODO` 주석을 사용하거나 이슈를 새로 만드세요.
_이유:_
> 그렇게 하면 당신 스스로나 다른 사람들에게 작은 작업(함수 리팩토링 혹은 주석 업데이트)을 상기시킬 수 있습니다. 조금 더 큰 작업에 대해서는 린트 규칙에 의해 강제되는 `//TODO(#3456)` 같은 주석을 사용하세요. 번호는 이슈 번호를 뜻합니다.
* 항상 주석이 코드 변경점과 관련이 있도록 유지하세요. 주석처리된 코드 블록은 제거하세요.
_이유:_
> 당신의 코드는 최대한 읽기 좋게 만드세요. 집중을 할 수 없게 만드는 것은 무엇이든 지워야합니다. 만약 함수를 리팩토링한다면, 예전 코드를 주석처리하지 말고 제거하세요.
* 부적절하거나 웃기는 주석, 로그, 네이밍을 피하세요.
_이유:_
> 빌드 프로세스에서 그것들을 제거할 수도 있지만, 때때로 당신의 소스 코드가 다른 회사/클라이언트에게 넘어가서 곤란한 상황이 될 수도 있습니다.
* 의미있게 구별이 되도록 검색이 잘되는 이름을 짓고 줄임말을 피하세요. 함수의 경우, 길고 설명적인 이름으로 지으세요. 함수의 이름은 동사이거나 동사구여야 하며, 의도를 전달해야합니다.
_이유:_
> 소스코드를 더 자연스럽고 가독성 좋게 만듭니다.
* 함수를 내림차 순으로 정렬해두세요. 고레벨의 함수는 최상단에 위치해야 하며 저레벨의 함수는 아래에 위치해야 합니다.
_이유:_
> 소스코드를 더 자연스럽고 가독성 좋게 만듭니다.
<a name="enforcing-code-style-standards"></a>
### 7.2 표준 코드 스타일 강제하기
* 서로 다른 에디터들 사이에서도 일관적인 코딩 스타일을 정의하고 유지하도록 돕는 [.editorconfig](http://editorconfig.org/) 파일을 사용하세요.
_이유:_
> EditorConfig 프로젝트는 코딩 스타일을 정의하는 파일 포맷과, 에디터가 파일 포맷을 읽을 수 있도록 도와주고 정의한 스타일을 고수하는 텍스트 에디터 플러그인들의 모음으로 정의됩니다. EditorConfig 파일은 가독성이 좋고 버전 컨트롤 시스템과도 잘 동작합니다.
* 코드 스타일 에러를 표시해주는 에디터를 사용하세요. 이미 사용하고 있는 ESLint 설정과 함께 [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier)와[eslint-config-prettier](https://github.com/prettier/eslint-config-prettier)를 사용하세요. [더 읽기](https://github.com/prettier/eslint-config-prettier#installation)
* Git hook을 고려해보세요.
_이유:_
> Git hook은 개발자의 생산성을 크게 끌어올립니다. 빌드를 깨트릴 걱정 없이 스테이징이나 프로덕션에 변경 사항을 만들고 커밋, 푸시를 할 수 있습니다. [더 읽기](http://githooks.com/)
* precommit hook과 함께 Prettier를 사용하세요.
_이유:_
> `prettier` 자체는 매우 강력하지만, 매번 코드를 포맷팅 할 때마다 npm 태스크로 실행하는 건 별로 생산적이지 않습니다. 이 부분에서는 `lint-staged``husky`가 편리합니다. 설정하는 방법은 `lint-staged`([여기](https://github.com/okonet/lint-staged#configuration))나 `husky`([여기](https://github.com/typicode/husky))에서 더 알아보세요.
<a name="logging"></a>
## 8. 로깅
![Logging](/images/logging.png)
* 프로덕션에서 클라이언트 사이드의 로깅은 피하세요.
_이유:_
> 아마 빌드 프로세스가 로깅 함수를 지워버리겠지만, 그럼에도 불구하고 코드 스타일 체크를 통해 `console.log`가 있으면 경고하도록 만드세요.
* 프로덕션에서 가독성 좋은 로그를 남기세요. 프로덕션 모드에서 [winston](https://github.com/winstonjs/winston) 이나 [node-bunyan](https://github.com/trentm/node-bunyan) 같은 로깅 라이브러리를 사용하는 것이 이상적입니다.
_이유:_
> 이렇게하면 로그 색상, 타임스탬프, 매일 반복되는 로그 파일 출력 등의 요소 덕분에 트러블 슈팅이 덜 고통스럽습니다. [더 읽기](https://blog.risingstack.com/node-js-logging-tutorial/)
<a name="api"></a>
## 9. API
<a name="api-design"></a>
![API](/images/api.png)
### 9.1 API 설계
_이유:_
> 우리가 RESTful 인터페이스를 명확하게 구성해서 개발하도록 강제하기 때문에 팀 멤버나 고객들이 간편하고 일관적으로 사용할 수 있습니다.
_이유:_
> 일관성과 단순함의 부족은 통합 및 유지보수 비용을 크게 상승시킬 수도 있습니다. 이것이 `API 설계`가 이 문서에 포함되어있는 이유입니다.
* 우리는 대부분 리소스 지향(resource-oriented) 설계를 따릅니다. 리소스 지향 설계는 세 개의 큰 요소(리소스, 콜렉션, URL)를 가집니다.
* 리소스는 데이터를 가지고, 중첩되며, 리소스를 조작할 수 있는 메소드가 존재합니다.
* 리소스의 그룹은 콜렉션이라고 부릅니다.
* URL은 리소스 혹은 콜렉션의 온라인 위치를 식별합니다.
_이유:_
> 이것은 개발자들(당신의 주 API 사용자들을 포함)에게 매우 잘 알려져있는 설계입니다. 가독성과 사용 편의성을 제외하더라도, 범용적인 라이브러리와 커넥터를 작성할 수 있습니다. 심지어 API가 뭔지 모르더라도 말이죠.
* URL에는 케밥 케이스(kebab-case)를 사용하세요.
* 쿼리 스트링이나 리소스 필드의 파라미터로는 카멜 케이스(camelCase)를 사용하세요.
* URL 내부 리소스의 이름은 복수의 케밥 케이스를 사용하세요.
* 콜렉션을 가리키는 URL의 네이밍에는 항상 복수 명사를 사용하세요. 예: `/users`
_이유:_
> 기본적으로, 더 읽기 쉽고 URL을 일관성있게 유지시킬 수 있습니다. [더 읽기](https://apigee.com/about/blog/technology/restful-api-design-plural-nouns-and-concrete-names)
* 소스 코드에서는 복수형을 변수나 프로퍼티로 변환할 때 `List` 접미사를 사용하세요.
_이유_:
> 복수형은 URL에는 좋지만 소스 코드에서는 식별하기가 어려워 에러의 원인이 될 수 있습니다.
* 항상 콜렉션에서 시작해 식별자에서 끝나는 단일 컨셉을 사용하세요.
```
/students/245743
/airports/kjfk
```
* 이런 URL은 피하세요.
```
GET /blogs/:blogId/posts/:postId/summary
```
_이유:_
> 이건 리소스가 아니라 프로퍼티를 가리키는 겁니다. 프로퍼티는 파라미터로 넘겨 응답(Response)을 정리할 수 있습니다.
* 리소스 URL에서 동사는 제거하세요.
_이유:_
> 각각의 리소스 작업에 동사를 사용하면 엄청난 양의 URL 리스트가 생기는 건 금방입니다. 또한 패턴에 일관성이 없어 개발자들이 배우기 어렵게 만듭니다. 게다가 우리는 동사를 좀 다른 용도로 사용할 겁니다.
* 리소스가 아닌 것들을 위해 동사를 사용하세요. 이 경우, API는 어떠한 리소스도 돌려주지 않습니다. 대신, 특정 동작(Operation)을 수행하고 그 결과를 반환합니다. **이것은 CRUD(create, retrieve, update and delete)가 아닙니다!**
```
/translate?text=Hallo
```
_이유:_
> CRUD 용도로 우리는 `리소스` 혹은 `콜렉션` URL에 HTTP 메소드를 사용하기 때문입니다. 우리가 말하고 있는 동사는 실제로는 `컨트롤러` 입니다. 보통은 이런 걸 개발할 일이 별로 없습니다. [더 읽기](https://byrondover.github.io/post/restful-api-guidelines/#controller)
* 요청 본문(Request body)과 응답 타입은 JSON이며, 일관성을 유지하기 위해서 `JSON` 프로퍼티 이름으로 `camelCase`를 사용하세요.
_이유:_
> 이건 JavaScript 프로젝트 가이드라인입니다. 때문에, JSON을 생성하는 프로그래밍 언어 뿐만 아니라 JSON을 파싱하는 프로그래밍 언어도 JavaScript일거라 가정합니다.
* 리소스는 객체 인스턴스 혹은 데이터베이스 레코드와 비슷한 단일 개념이지만, 리소스 이름에 테이블 명을 사용하거나 프로퍼티 이름으로 컬럼 명을 사용하지 마세요.
_이유:_
> API의 용도는 데이터베이스 스키마를 공개하는 것이 아니라 리소스를 노출하는 것입니다.
* 재강조합니다. 리소스를 네이밍할 때 URL에는 명사만 사용하고 기능적인 측면을 설명하려고 하지마세요.
_이유:_
> 리소스 URL에는 오직 명사만 사용하고, `/addNewUser``/updateUser` 같은 끝점은 피하세요. 또한 리소스 동작을 파라미터로 보내지마세요.
* HTTP 메소드를 사용해 CRUD의 기능적 측면을 나타내세요.
_방법:_
> `GET`: 리소스의 표현을 가져오기 위해 사용합니다.
> `POST`: 새로운 리소스나 서브 리소스를 만들기 위해 사용합니다.
> `PUT`: 존재하는 리소스를 업데이트하기 위해서 사용합니다.
> `PATCH`: 존재하는 리소스를 업데이트하기 위해 사용합니다. 오직 제공된 필드만 업데이트하고 다른 것들은 그대로 놔둡니다.
> `DELETE`: 존재하는 리소스를 삭제하기 위해서 사용합니다.
* 중첩된 리소스는 URL에서의 관계를 이용하세요, 예를 들어, 직원과 회사를 연결하기 위해 `id`를 사용하세요.
_이유:_
> 이것은 리소스를 탐색 가능하도록 만드는 자연스러운 방법입니다.
_방법:_
> `GET /schools/2/students ` , 2번 학교의 모든 학생들의 리스트를 가져옵니다.
> `GET /schools/2/students/31` , 2번 학교에 속한 31번 학생의 구체적인 정보를 가져옵니다.
> `DELETE /schools/2/students/31` , 2번 학교에 속한 31번 학생을 삭제합니다.
> `PUT /schools/2/students/31` , 31번 학생의 정보를 업데이트 합니다. PUT은 콜렉션 말고 리소스 URL에만 사용하세요.
> `POST /schools` , 새로운 학교를 만들고 만들어진 학교의 구체적인 정보를 반환합니다. 콜렉션 URL에 POST 메소드를 사용하세요.
* 버전을 위해서 `v` 접두어와 함께 간단한 서수(ordinal number)를 사용하세요(v1, v2). 가장 높은 스코프를 가지도록 URL의 가장 왼쪽에 위치시키세요.
```
http://api.domain.com/v1/schools/3/students
```
_이유:_
> 다른 서드 파티를 위해 API를 공개한 경우, Breaking change를 포함하는 API 업그레이드는 그 API를 사용하는 프로덕트나 서비스 또한 깨트릴 수 있습니다. URL에 버전을 사용해서 그런 사건을 예방하세요. [더 읽기](https://apigee.com/about/blog/technology/restful-api-design-tips-versioning)
* 응답 메시지는 스스로 설명할 수 있어야 합니다. 좋은 에러 메시지 응답은 다음과 같이 생겼습니다.
```json
{
"code": 1234,
"message" : "뭔가 안 좋은 일 발생",
"description" : "세부 정보"
}
```
혹은 Validation 에러의 경우,
```json
{
"code" : 2314,
"message" : "Validation 실패",
"errors" : [
{
"code" : 1233,
"field" : "email",
"message" : "유효하지 않은 이메일"
},
{
"code" : 1234,
"field" : "password",
"message" : "비밀번호가 제공되지 않음"
}
]
}
```
_이유:_
> 개발자들이 당신의 API를 사용해 어플리케이션을 개발한 뒤에, 트러블 슈팅을 할 때나, 이슈를 해결하는 중요한 상황에서 그들은 잘 설계된 에러에 의존합니다.
_주의: 보안상의 예외 메시지는 가능한 일반적으로 만드세요. 예를 들어, '틀린 비밀번호' 대신에 '틀린 유저명 혹은 비밀번호'라는 답변으로 대신하여 유저명은 실제로 맞고 비밀번호만 잘못되었다는 사실을 유저에게 무의식적으로 알리지 않을 수 있습니다._
* **모든 것이 잘 동작한다**, **클라이언트 앱이 뭔가 잘못했다**, 혹은 **API가 뭔가 잘못했다** 여부를 표현하기 위해, 응답으로 아래의 8가지 상태 코드만 사용하세요.
_목록:_
> `200 OK``GET`, `PUT` 혹은 `POST` 요청이 성공했음을 표현합니다.
> `201 Created`는 새로운 인스턴스가 생성되었을 때 보냅니다. `POST` 메소드를 이용해 새로운 인스턴스를 생성하면 `201` 상태 코드를 반환합니다.
> `304 Not Modified` 응답은 수신자가 캐시 데이터를 가지고 있을 때 정보 교환을 최소화하기 위해서 사용됩니다.
> `400 Bad Request` 응답은 요청이 처리되지 않았을 때, 서버가 클라이언트가 요청하는 게 무엇인지 알 수 없을 때 사용합니다.
> `401 Unauthorized`는 요청에 유효한 자격증명이 없을 때, 필요한 자격증명으로 다시 요청해야하는 경우 사용합니다.
> `403 Forbidden`는 서버가 요청을 이해했으나, 승인은 거절한다는 의미입니다.
> `404 Not Found`는 요청한 리소스를 찾을 수 없음을 나타냅니다.
> `500 Internal Server Error`는 요청이 유효하나, 서버가 예상치 못한 상황으로 인해 요청을 실행하지 못했음을 나타냅니다.
_이유:_
> 대부분의 API 공급자들은 HTTP 상태 코드의 작은 부분집합만 사용합니다. 예를 들어 구글의 GData API는 단 10개의 상태 코드를 사용하고, 넷플릭스는 9개, Digg는 겨우 8개를 사용합니다. 물론, 이러한 응답들은 추가적인 정보를 담고있는 본문을 포함합니다. HTTP 상태 코드는 70개 이상 존재합니다. 그러나, 대부분의 개발자는 70개 모두를 기억하지는 못합니다. 그러므로 만약 당신이 일반적으로 쓰이지 않는 상태 코드를 사용한다면, 어플리케이션 개발자들은 개발을 하다말고 위키피디아로 가서 당신이 뭘 말하려고 했는지 알아볼 것입니다. [더 읽기](https://apigee.com/about/blog/technology/restful-api-design-what-about-errors)
* 응답에 리소스의 숫자를 제공하세요.
* `limit``offset` 파라미터를 허용하세요.
* 노출되는 리소스 데이터의 양도 고려해야 합니다. API 사용자는 항상 리소스의 모든 필드를 필요로 하지 않습니다. 쉼표로 구분된 필드 목록을 포함하는 필드 쿼리 파라미터를 사용하세요.
```
GET /student?fields=id,name,age,class
```
* 페이지네이션, 필터링 및 정렬은 처음부터 모든 리소스에 대해 지원될 필요는 없습니다. 필터링과 정렬을 지원하는 리소스에 대해 문서를 작성하세요.
<a name="api-security"></a>
### 9.2 API 보안
다음과 같이, 몇 가지 기본적인 보안 모범사례가 존재합니다.
* 보안 연결(HTTPS) 없이 "Basic" 인증은 사용하지 마세요. 인증 토큰은 URL로 전달(`GET /users/123?token=asdf....`)되어서는 안됩니다.
_이유:_
> 토큰 혹은 유저 ID 및 비밀번호는 네트워크를 통해 명확한 텍스트로 전달됩니다. (Base64 인코딩을 사용하지만, Base64는 디코딩이 가능하죠.) Basic 인증 방식은 안전하지 않습니다. [더 읽기](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication)
* 토큰은 다음처럼 모든 요청에 대해 Authorization 헤더를 사용해서 전달되어야 합니다. `Authorization: Bearer xxxxxx, Extra yyyyy`
* 인증 코드(Authorization Code)는 유효기간이 짧아야 합니다.
* 안전하지 않은 데이터 교환을 피하기 위해 HTTP 요청에 응답하지 않음으로써 TLS 요청이 아닌 요청을 거부하세요. HTTP 요청에 `403 Forbidden`으로 응답하세요.
* 요청 제한을 고려해보세요.
_이유:_
> API를 봇이 시간 당 몇 천 건의 요청을 보내는 위협에서 보호하세요. 빠른 속도로 요청 제한을 구현하는 걸 고려해야합니다.
* HTTP 헤더를 적절하게 설정하면, 웹 어플리케이션의 보안을 유지하는데 도움이 됩니다. [더 읽기](https://github.com/helmetjs/helmet)
* API는 받은 데이터를 표준 형식으로 변환하거나 거부해야 합니다. 잘못되거나 빠진 데이터에 대한 세부 정보와 함께 400 Bad Request를 돌려주세요.
* REST API로 교환된 모든 데이터는 API에 의해 유효한지 검사되어야 합니다.
* JSON을 직렬화(Serailize)하세요.
_이유:_
> JSON 인코더의 중요한 관심사는 브라우저 혹은 Node.js 서버에서 임의의 JavaScript 원격 코드의 실행을 막는 것입니다. 브라우저에서 사용자가 제공한 데이터를 실행할 수 없도록 적절한 JSON 인코더를 사용해서 사용자가 제공한 데이터를 적절하게 인코딩하는 것은 중요합니다.
* Content-Type을 검증하고, Content-Type 헤더로 거의 `application/*.json`을 사용하세요.
_이유:_
> 예를 들머, `application/x-www-form-urlencoded` MIME 타입을 받아들이게 되면 공격자들이 폼을 만들고 간단한 POST 요청을 일으키는 것을 허용하게 됩니다. 서버는 절대 Content-Type을 가정해서는 안됩니다. Content-Type 헤더의 부재 혹은, 예상치 못한 Content-Type 헤더는 서버에서 `4XX` 응답으로 거부해야 합니다.
* API 보안 체크리스트 프로젝트를 살펴보세요. [더 읽기](https://github.com/shieldfy/API-Security-Checklist)
<a name="api-documentation"></a>
### 9.3 API 문서화
* [README.md 템플릿](./README.sample.md)의 `API 참조` 섹션을 채우세요.
* 샘플 코드를 첨부해서 API 인증 방법을 기술하세요.
* 요청 타입(HTTP METHOD)을 포함해 URL(경로만 포함, 루트 URL 제외) 구조를 설명하세요.
각각의 끝점(Endpoint)에 대해서 다음과 같은 사항이 포함되어야 합니다.
* URL 파라미터가 존재한다면 다음과 같이 URL 섹션에 언급된 이름에 따라 URL 파라미터를 명시합니다.
```
Required: id=[integer]
Optional: photo_id=[alphanumeric]
```
* 요청 타입이 POST인 경우 동작하는 예제를 제공하세요. URL 파라미터 규칙도 여기에 적용됩니다. 필수와 옵션 섹션을 구분하세요.
* 응답 성공: 상태 코드는 어떻게 되어야 하며, 돌려주는 데이터는 어떤 건가요? 아래처럼 하면 요청의 결과를 알아야할 필요가 있을 때 유용합니다.
```
Code: 200
Content: { id : 12 }
```
* 응답 에러: 대부분의 끝점에 대한 요청은 비인증 접근부터 잘못된 파라미터까지, 다양한 방법으로 실패할 수 있습니다. 이런 에러들은 명시되어야 합니다. 너무 반복적일 수도 있지만, 가정을 하지 않게 하는데 도움이 됩니다. 예를 들어,
```json
{
"code": 403,
"message" : "인증 실패",
"description" : "유효하지 않은 유저명 혹은 비밀번호"
}
```
* API 설계 도구를 사용하세요. 좋은 문서화에 도움을 주는 다양한 오픈소스가 있습니다. [API Blueprint](https://apiblueprint.org/)나 [Swagger](https://swagger.io/) 같은 것들 말이죠.
<a name="licensing"></a>
## 10. 라이센스
![Licensing](/images/licensing.png)
사용 권한이 있는 리소스만 사용해야 합니다. 라이브러리를 사용할 때는 MIT, Apache 혹은 BSD 라이센스를 찾아야한다는 걸 기억하세요. 또한 당신이 라이브러리를 수정해야 한다면, 라이센스 세부정보를 잘 살펴보세요. 저작권이 있는 이미지나 비디오는 법적 문제를 야기할 수 있습니다.
---
Sources:
[RisingStack Engineering](https://blog.risingstack.com/),
[Mozilla Developer Network](https://developer.mozilla.org/),
[Heroku Dev Center](https://devcenter.heroku.com),
[Airbnb/javascript](https://github.com/airbnb/javascript),
[Atlassian Git tutorials](https://www.atlassian.com/git/tutorials),
[Apigee](https://apigee.com/about/blog),
[Wishtack](https://blog.wishtack.com)
Icons by [icons8](https://icons8.com/)

871
README-pt-BR.md Normal file
View File

@ -0,0 +1,871 @@
[中文版](./README-zh.md)
| [日本語版](./README-ja.md)
| [한국어](./README-ko.md)
| [РУССКИЙ](./README-ru.md)
| [ENGLISH](./README.md)
[<img src="./images/elsewhen-logo.png" width="180" height="180">](https://www.elsewhen.com/)
# Padrões de Projeto &middot; [![PRs são bem vindos](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
> Enquanto desenvolver um novo projeto é apenas diversão para você, manter esse projeto pode ser um dos piores pesadelos para outra pessoa.
> Isso aqui é uma lista dos padrões que encontramos, coletamos e escrevemos que (para nós) funcionam realmente bem com a maioria dos projetos JavaScript aqui na [elsewhen](https://www.elsewhen.com).
> Se você quer compartilhar alguma prática que considera importante ou acha que alguma das coisas descritas aqui deve ser removida, [Sinta se a vontade para nos dizer](http://makeapullrequest.com).
🔥 [Confira](https://github.com/elsewhencode/react-redux-saucepan) nosso [react redux projeto base](https://github.com/elsewhencode/react-redux-saucepan) em Flow com hot reloading e server-side rendering.
<hr>
- [Padrões de Projeto &middot; ![PRs são bem vindos](http://makeapullrequest.com)](#padr%C3%B5es-de-projeto-middot-prs-s%C3%A3o-bem-vindoshttpmakeapullrequestcom)
- [1. Git](#1-git)
- [1.1 Algumas regras do Git](#11-algumas-regras-do-git)
- [1.2 Git workflow](#12-git-workflow)
- [1.3 Escrevendo boas mensagens de commit](#13-escrevendo-boas-mensagens-de-commit)
- [2. Documentação](#2-documenta%C3%A7%C3%A3o)
- [3. Ambientes](#3-ambientes)
- [3.1 Ambientes de dev consistentes:](#31-ambientes-de-dev-consistentes)
- [3.2 Dependências consistentes:](#32-depend%C3%AAncias-consistentes)
- [4. Dependências](#4-depend%C3%AAncias)
- [5. Testes](#5-testes)
- [6. Nomes e estrutura](#6-nomes-e-estrutura)
- [7. Estilo de código](#7-estilo-de-c%C3%B3digo)
- [7.1 Alguns padrões de estilo de código](#71-alguns-padr%C3%B5es-de-estilo-de-c%C3%B3digo)
- [7.2 Force o code style](#72-force-o-code-style)
- [8. Logging](#8-logging)
- [9. API](#9-api)
- [9.1 API design](#91-api-design)
- [9.2 API security](#92-api-security)
- [9.3 API documentation](#93-api-documentation)
- [10. Licença](#10-licen%C3%A7a)
<a name="git"></a>
## 1. Git
![Git](/images/branching.png)
<a name="some-git-rules"></a>
### 1.1 Algumas regras do Git
Essas são algumas regras do Git para manter em mente:
- Trabalhe em uma feature branch.
_Por que?:_
> Porque desse jeito todo o código é criado isolado em uma branch específica ao invés de poluir a branch principal com trabalho em progresso. Isso vai permitir você abrir vários pull requets sem confusão. Você pode continuar com uma branch em progresso sem correr o risco de quebrar a branch principal com código instável. [Leia mais sobre...](https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow)
- Sempre comece uma nova branch a partir da `develop`
_Por que?_
> Desse jeito você pode garantir que o código na master vai estar sempre pronto para fazer build sem problemas e poderá ser usado a qualquer momento para fazer releases (isso pode ser exagero para alguns projetos).
- Nunca dê push direto na `develop` ou `master`. Sempre faça Pull Requests.
_Por que?_
> Isso permite outros membros do time saberem que você terminou uma feature. Também possibilita code review e dicussões sobre o código que está prestes a ser introduzido no code base.
- Atualize sua `develop` local e faça rebase interativo antes de subir sua feature e abrir um Pull Request.
_Por que?_
> Rebase vai fazer um merge do branch destino do pull request e aplicar os commits que você tem localmente no topo da história sem criar um commit de merge (assumindo que não tem conflitos). Como resultado você tem uma história limpa no seu repositório. [Leia mais sobre ...](https://www.atlassian.com/git/tutorials/merging-vs-rebasing)
- Resolva os conflitos enquanto faz o rebase e antes de abrir o Pull Request.
- Delete feature branches, local e remoto, depois de realizar o merge.
_Por que?_
> Vai reduzir sua lista de branches removendo branches mortas. Vai garantir que você apenas faça o merge de uma branch uma única vez. Feature branches só devem existir enquanto o código ainda está em progresso.
- Antes de fazer um Pull Request, tenha certeza que sua feature branch está fazendo build corretamente e passando em todos os testes (incluindo os padrões de estilo de código).
_Por que?_
> Você está prestes a colocar seu código em uma branch estável. Se sua feature branch faz algum teste falhar, a chance é alta de que você vai quebrar o build na branch destino. Você também precisa conferir o code style antes de fazer um Pull Request. Isso contribui para legibilidade e reduz a chance de algum problema de formatação is para o code base com as outras alterações.
- Faça uso desse [`.gitignore`](./.gitignore).
_Por que:_
> É uma lista que já contém arquivos de sistemas que não devem ser enviados para o seu repositório remoto. E também exclui pastas de configuração e os arquivos comumente usado por editores e obviamente, também, pastas de dependência.
- Proteja (Bloqueie) a `develop` e `master`.
_Por que?_
> Protege suas branchs que devem, em teoria, estarem prontas para irem para produção de receberem códigos e mudanças irreversíveis. Leia mais sobre... [Github](https://help.github.com/articles/about-protected-branches/), [Bitbucket](https://confluence.atlassian.com/bitbucketserver/using-branch-permissions-776639807.html) e [GitLab](https://docs.gitlab.com/ee/user/project/protected_branches.html)
<a name="git-workflow"></a>
### 1.2 Git workflow
Devido a maioria dos motivos listados acima, nos usamos [Feature-branch-workflow](https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow) com [Interactive Rebasing](https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing) e alguns pontos do [Gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows#gitflow-workflow) (nomeação e ter uma develop branch). Os principais passos são:
- Em um projeto novo, inicialize o git na pasta do projeto. **Para qualquer features/changes ignore esse passo**.
```sh
cd <pasta do projeto>
git init
```
- Checkout para uma nova branch feature/bug-fix.
```sh
git checkout -b <branchname>
```
- Faça as alterações.
```sh
git add <arquivo1> <arquivo2> ...
git commit
```
_Por que?_
> `git add <arquivo1> <arquivo2> ...` - Você deve add apenas arquivos com mudanças pequenas e concisas.
> `git commit` Abrirá o editor, o que permite você separar o titulo da mensagem.
> Leia mais sobre na _seção 1.3_.
_Dica:_
> Você poderia usar `git add -p`, o que te daria a chance de revisar todas as mudanças introduzidas, uma a uma, e decidir se inclui ou não naquele commit.
- Sincronize com as ultimas alterações no repositório remoto.
```sh
git checkout develop
git pull
```
_Por que?_
> Isso vai permitir que você lide com os conflitos na sua máquina local enquanto você faz o rebase (posteriormente) ao invés de criar um pull request com conflitos.
- Atualize sua feature branch com as ultimas alterações da develop usando rebase iterativo.
```sh
git checkout <branchname>
git rebase -i --autosquash develop
```
_Por que?_
> Você pode usar --autosquash para comprimir todos os seus commits em um único commit. Ninguém quer commits de desenvolvimento de uma feature na develop. [Leia mais sobre...](https://robots.thoughtbot.com/autosquashing-git-commits)
- Se você não tem conflitos, pule esse passo. Se você tem conflitos, [resolva-os](https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/) e continue onrebase.
```sh
git add <file1> <file2> ...
git rebase --continue
```
- Push sua branch. Rebase vai alterar a história, então você precisa usar `-f` para forçar a mudança no branch remoto. Se tem mais alguém trabalhando na mesma branch, use o comando `--force-with-lease`.
```sh
git push -f
```
_Por que?_
> Quando você faz rebase, você está mudando a história na sua feature branch. Então o git ira rejeitar seu `git push`. Para passar por isso você precisa usar -f ou --force flag. [Leia mais sobre...](https://developer.atlassian.com/blog/2015/04/force-with-lease/)
- Abra um Pull Request.
- Pull request deve ser aceito, mergiado e fechado por quem estiver revisando.
- Delete seu branch local se tiver terminado.
```sh
git branch -d <nome do branch>
```
Para remover todos os branchs que não existem no repositório remoto:
```sh
git fetch -p && for branch in `git branch -vv --no-color | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done
```
<a name="writing-good-commit-messages"></a>
### 1.3 Escrevendo boas mensagens de commit
Ter um bom padrão para criar commits e se atentar a ele faz com que trabalhar com Git e colaborar com outros seja muito mais fácil. Aqui estão algumas boas práticas ([fonte](https://chris.beams.io/posts/git-commit/#seven-rules)):
- Separe o assunto e a mensagem com uma nova linha entre eles.
_Por que?_
> Git é inteligente o suficiente para identificar a primeira linha do seu commit como um resumo. Na verdade, se você tentar shortlog, ao invés de git log, você vai ver uma longa lista de mensagens de commits, com apenas o id e o resumo do commit.
- Máximo de 50 caracteres para o assunto e 72 para a mensagem.
_Por que?_
> Commits devem ser objetivos e claros, não é o momento para ser verboso. [Leia mais sobre...](https://medium.com/@preslavrachev/what-s-with-the-50-72-rule-8a906f61f09c)
- Capitalize a linha do assunto.
- Não use um ponto para finalizar a linha do assunto.
- Use [imperative mood](https://en.wikipedia.org/wiki/Imperative_mood) na linha do assunto.
_Por que?_
> É melhor que o commit diga o que vai acontecer no projeto depois daquele commit do que o que o que aconteceu dentro do commit em si. [Lei mais sobre...](https://news.ycombinator.com/item?id=2079612)
* Use a mensagem para explicar **o que** e **porque** ao invés de **como**.
<a name="documentation"></a>
## 2. Documentação
![Documentation](/images/documentation.png)
- Use esse [template](./README.sample.md) para `README.md`, sinta-se a vontade para adicionar seções que achar necessárias.
- Para projetos com mais de um repositório adicione todos os respctivos links nos `README.md` de todos os projetos.
- Mantenha o `README.md` enquanto o projeto evolui.
- Comente seu código. Tente sempre deixar claro o que uma grande parte do código tem a intenção de fazer.
- Se existe alguma referência em relação a forma como você resolveu o problema ou uma discussão em aberto, adicione os links.
- Não use comentários como desculpa para fazer um código ruim. Mantenha seu código limpo.
- Não use código limpo como uma desculpa para não fazer nenhum comentário.
- Mantenha apenas os comentários relevantes enquanto o código evolui.
<a name="environments"></a>
## 3. Ambientes
![Environments](/images/laptop.png)
- Defina ambientes de `desenvolvimento`, `testes` e `produção` separados.
_Por que?_
> Diferentes informações, dados, tokens, APIs, portas etc... podem ter que ser diferentes em cada ambiente. Você provavelmente vai querer isolar seu ambiente de `desenvolvimento` para fazer chamadas fake para a API que retornará dados previsíveis, tornando tanto os testes automatizados quanto os manuais muito mais facéis. Ou você pode querer ativar o Google Analytics apenas em `produção` e etc... [Leia mais sobre...](https://stackoverflow.com/questions/8332333/node-js-setting-up-environment-specific-configs-to-be-used-with-everyauth)
* Carregue suas configurações específicas de deploy de variáveis de ambiente e nunca as adicione no seu codebase como constantes, [veja aqui um exemplo](./config.sample.js).
_Por que?_
> Você terá tokens, senhas e outras informações sigilosas nessa configuração. Sua configuração deve ser corretamente separada da sua aplicação como se seu codebase pudesse se tornar público a qualquer momento.
_Como?_
> Arquivos `.env` para manter suas variáveis e então adicione-o ao `.gitignore` para ser excluído. Ao invés, commit um `.env.example` que servirá de modelo para outros desenvolvedores. Para produção, você deve setar suas variáveis no jeito padrão. [Leia mais sobre...](https://medium.com/@rafaelvidaurre/managing-environment-variables-in-node-js-2cb45a55195f)
* É recomendável validar suas variáveis de ambiente antes de inicializar sua aplicação. [De uma olhada nesse exemplo](./configWithTest.sample.js) usando `joi` para validar os valores.
_Por que?_
> Pode salvar todos de horas de "dor de cabeça".
<a name="consistent-dev-environments"></a>
### 3.1 Ambientes de dev consistentes:
- Defina sua versão do node em `engines` no `package.json`.
_Por que?_
> Permite que todos saibem em qual versão o projeto funciona. [Leia mais sobre...](https://docs.npmjs.com/files/package.json#engines)
- Adicionalmente, use `nvm` e crie um arquivo `.nvmrc` na raíz do seu projeto. Não se esqueça de menciona-lo na sua documentação.
_Por que?_
> Qualque pessoa que usar `nvm` pode apenas rodar `nvm use` para trocar para a versão correta. [leia mais sobre...](https://github.com/creationix/nvm)
- É uma boa ideia criar um script `preinstall` para conferir as versões do node e do npm.
_Por que?_
> Algumas dependências podem falhar quando instaladas por versões mais recentes do NPM.
- Use Docker se puder.
_Por que?_
> Te dará um ambiente estável durante todo o workflow. Sem muita necessidade de lidar com dependências e configurações. [leia mais sobre...](https://hackernoon.com/how-to-dockerize-a-node-js-application-4fbab45a0c19)
- Use local modules ao invés de modules instalados globalmente.
_Por que?_
> Você estará compartilhando suas dependências com os outros ao invés de esperar que eles a tenham instalado globalmente.
<a name="consistent-dependencies"></a>
### 3.2 Dependências consistentes:
- Garanta que seus colegas de equipe obtenham exatamente a mesma versão de dependências que você.
_Por que?_
> Porque você quer que se código tenha o mesmo comportamento em qualquer máquina de desenvolvimento [leia mais sobre...](https://medium.com/@kentcdodds/why-semver-ranges-are-literally-the-worst-817cdcb09277)
_Como?_
> Use `package-lock.json` a partir do `npm@5`
_E se eu não tenho npm@5?_
> Uma alternativa pode ser o `Yarn` e não se esqueça de mencionar o seu uso no `README.md`. Seu lock file e o `package.json` devem manter as mesmas versões após cada atualização. [leia mais sobre...](https://yarnpkg.com/en/)
_E se eu não gosto do nome `Yarn`?_
> Que pena. Para versões antigas do `npm`, use `—save --save-exact` quando instalando novas dependências e criando um `npm-shrinkwrap.json` antes de publicar. [Leia mais sobre...](https://docs.npmjs.com/files/package-locks)
<a name="dependencies"></a>
## 4. Dependências
![Github](/images/modules.png)
- Acompanhe seus pacotes disponíveis atualmente: e.g., `npm ls --depth=0`. [Leia mais sobre...](https://docs.npmjs.com/cli/ls)
- Confira se algum dos seus pacotes não está em uso ou se tornou irrelevante: `depcheck`. [Leia mais sobre...](https://www.npmjs.com/package/depcheck)
_Por que?_
> Você pode estar fazendo o bundle final ficar maior com bibliotecas não usadas. Identifique essas bibliotecas não usadas e se livre delas.
- Antes de começar a usar uma dependência, confira o quanto ela é usada pela comunidade: `npm-stat`. [Leia mais sobre...](https://npm-stat.com/)
_Por que?_
> Maior uso geralmente significa mais contribuidores, o que leva a deduzir que possui melhor manutenção, o que tudo isso junto leva a concluir que bugs serão encontrados mais facilmente e resolvidos rapidamente.
- Antes de usar uma dependência, confira se possui uma versão madura o suficiente com um grande número de pessoas mantendo: e.g., `npm view async`. [Leia mais sobre...](https://docs.npmjs.com/cli/view)
_Por que?_
> Ter muitos contribuidores não var ser tão efetivo se os mantenedores não fizerem os merge fixes e patches rápido.
- Se você precisa de uma dependência menos conhecida, discuta com o time antes de usa-la.
- Sempre tenha certeza que sua aplicação funciona com a ultima versão das dependências: `npm outdated`. [Leia mais sobre...](https://docs.npmjs.com/cli/outdated)
_Por que?_
> Atualização de dependência as vezes possuem 'breaking changes'. Sempre confira a descrição da nova versão sempre que sair, isso faz com que lidar com os possíveis problemas seja mais fácil. Use uma dessas ferramentas maneiras, como: [npm-check-updates](https://github.com/tjunnone/npm-check-updates).
- Confira problemas de segurança com a dependência que você quer adicionar, e.g., [Snyk](https://snyk.io/test?utm_source=risingstack_blog).
<a name="testing"></a>
## 5. Testes
![Testes](/images/testing.png)
- Tenha um ambiente the `test` se necessário
_Por que?_
> Embora algumas vezes testes end to end em `produção` possam parecer suficientes, existem algumas exceções: Um exemplo é que você não vai querer colocar dados analíticos em `produção` e assim poluir o dashboard de alguém com dados de teste. Outro exemplo é que sua API pode ter algumas limitações enquanto em `produção` e chamadas de teste depois de uma certa quantidade.
- Coloque os arquivos de teste junto com os arquivos a serem testados usando a convenção `*.test.js` ou `*.spec.js` para nomear os arquivos, como `moduleName.spec.js`.
_Por que?_
> Você não quer ter que navegar em várias pastas para achar um teste unitário. [Leia mais sobre...](https://hackernoon.com/structure-your-javascript-code-for-testability-9bc93d9c72dc)
* Coloque seus arquivos de testes adicionais em uma pasta separada para evitar confusão.
_Por que?_
> Alguns arquivos de testes não tem nenhuma relação com qualquer outro arquivo. Você deve coloca-los em uma pasta fácil de ser encontrada pelos outros desenvolvedores do time, como por exemplo: Uma pasta `__test__`. Essa nomeação é padrão e reconhecida pela maioria de frameworks de teste de JavaScript.
* Escreva código testável, evite efeitos colaterais (side effects), escreva funções puras
_Por que?_
> Você vai querer testar uma regra de negócio como uma unidade separada. Voce tem que "minimizar o impacto de aleatoriedade e processos não determinísticos no seu código". [Leia mais sobre...](https://medium.com/javascript-scene/tdd-the-rite-way-53c9b46f45e3)
> Uma função pura é uma função que sempre retorna o mesmo valor para uma entrada específica. Por outro lado, uma função impura é uma função que pode ter efeitos colaterais e depender de condições externas para retornar algum valor. Isso reduz a capacidade de prever o que o código vai realizar. [Leia mais sobre...](https://hackernoon.com/structure-your-javascript-code-for-testability-9bc93d9c72dc)
* Use uma checagem de tipo estática
_Por que?_
> As vezes você vai precisar de checagem de tipo estática. O que também aumenta a regidibilidade e legibilidade do seu código. [Leia mais sobre...](https://medium.freecodecamp.org/why-use-static-types-in-javascript-part-1-8382da1e0adb)
- Rode os testes localmente antes de abrir um pull request para `develop`.
_Por que?_
> Você não quer ser a pessoa a fazer com que a branch com código pronto para produção pare de funcionar. Rode seus teste depois que fizer `rebase` e antes de fazer push para sua feature branch.
- Documente seus testes incluindo instruções importantes em uma seção no arquivo `README.md`.
_Por que?_
> Vai ser de muita ajuda para outros desenvolvedores, DevOps, QA ou qualquer um que tiver a sorte de trabalhar com seu código.
<a name="structure-and-naming"></a>
## 6. Nomes e estrutura
![Structure and Naming](/images/folder-tree.png)
- Organize seus arquivos considerando feature / páginas / componentes. E também, coloque os arquivos de teste próximos à implementação..
**Ruim**
```
.
├── controllers
| ├── product.js
| └── user.js
├── models
| ├── product.js
| └── user.js
```
**Bom**
```
.
├── product
| ├── index.js
| ├── product.js
| └── product.test.js
├── user
| ├── index.js
| ├── user.js
| └── user.test.js
```
_Por que?_
> Ao invés de uma longa lista de arquivos você estará criando pequenos modulos encapsulando responsabilidades e seus respectivos testes. Fica muito mais fácil de se navegar e as coisas podem ser facilmente encontradas.
- Use uma pasta com o nome `./config` e **não** crie arquivos de configuração diferente para cada ambiente.
_Por que?_
> Quando você distribuí as configurações em arquivos com propósitos diferentes (database, API e etc); Coloca-los em uma pasta com o nome fácil de reconhecer como `config` faz sentido. Apenas se lembre de não criar arquivos de configuração diferentes para cada ambiente. Isso não escala, cada novo deploy diferente que se faz necessário, novos nomes de ambientes são criados.
> Valores para serem usados por arquivos de configuração devem ser providos através de variáveis de ambiente. [Leia mais sobre...](https://medium.com/@fedorHK/no-config-b3f1171eecd5)
* Coloque seus scripts em uma pasta nomeada `./scripts`. Isso vale para `bash` e `node`.
_Por que?_
> É bem provável que você vai acabar com mais de um script, build de produção, build de dev, database feeders, database sync e etc...
- Direcione os arquivos de output do build em uma pasta nomeada `./build`. Adicione `build/` no `.gitignore`.
_Por que?_
> Dê o nome que você achar conveniente, `dist` também é uma boa opção. Mas tenha a certeza de manter isso consistente com os projetos do time. Os arquivos que vão para essa pasta são gerados automaticamente (bundled, compiled, transpiled) ou movidos automaticamente para lá. O que você pode gerar, qualquer um no time deve ser capaz de gerar também, então não faz nenhum sentido comitar isso para o repositório. A não ser que você realmente queira muito fazer isso.
<a name="code-style"></a>
## 7. Estilo de código
![Code style](/images/code-style.png)
<a name="code-style-check"></a>
### 7.1 Alguns padrões de estilo de código
- Use stage-2 e sintaxe moderna de JavaScript nos seus novos projetos. Para os projetos antigos, mantenha a consistência, a não ser que modernizar o projeto seja o objetivo.
_Por que?_
> É claro, isso só depende de você. Nós usamos transpilers para tirar vantagem de novas sintaxes. stage-2 é bem provável de se tornar parte da especificação em alguma revisão.
- Inclua alguma conferência automática de padrão de código no seu build.
_Por que?_
> Quebrar o build é uma forma de forçar os padrões de código. Evite que não seja levado a sério. Faça isso tanto para o backend quanto para o front. [Leia mais sobre...](https://www.robinwieruch.de/react-eslint-webpack-babel/)
- Use [ESLint - Pluggable JavaScript linter](http://eslint.org/) para garantir que os padrões serão seguidos.
_Por que?_
> Nós simplesmente preferimos `eslint`, você não precisa necessariamente o usar. Ele tem mais regras suportadas, a possibilidade de configura-las e criar regras customizadas.
- Nós usamos [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript) para JavaScript, [Leia mais sobre](https://www.gitbook.com/book/duk/airbnb-javascript-guidelines/details). Escolha os padrões necessário para seu projeto.
- Usamos [Flow type style check rules for ESLint](https://github.com/gajus/eslint-plugin-flowtype) ao usar [FlowType](https://flow.org/).
_Por que?_
> Flow usa algumas sintaxes que também precisam de seguir um padrão.
- Use `.eslintignore` para excluir os arquivos que devem ser ignorados pelas regras.
_Por que?_
> Você não precisa poluir seu código com comentários como `eslint-disable` toda vez que quiser desabilitar alguma regra em um certo arquivo.
- Remova todos `eslint-disable` antes de fazer um pull request.
_Por que?_
> É normal desabilitar o `eslint` para focar na lógica de uma parte do código. Apenas se lembre de remover o `eslint-disable` quando terminar.
- Dependendo do tamanho da task, use comentários com `//TODO:` para ajudar na criação de novas tasks para o backlog.
_Por que?_
> Você vai deixar um lembrete para os outros, e para você mesmo, de pequenas tarefas ou correções (como refatorar uma função ou atualizar um comentário). Para tarefas maiores escreva `//TODO(#3456)` fazendo referência ao ticket aberto no backlog para aquela task.
* Sempre faça comentários relevantes. Delete código morto ou comentado.
_Por que?_
> Você deve prezar pela legibilidade do seu código, então se livre de qualquer distração possível no código. Se você refatorou uma função, não deixe a antiga lá apenas comentada, delete-a.
* Evite comentários irrelevantes, engraçados ou ofensivos.
_Por que?_
> Mesmo que seu processo de build possa remove-los, as vezes seu código pode ser pego por alguém diferente, uma empresa terceirizada ou um chefe de outra área e isso pode não ser tão tranquilo.
* Use nomes com significados, fáceis de pesquisar e sem abreviações para suas variáveis ou funções. O nome de uma função deve ser um verbo ou uma frase e precisa de deixar claro a sua intenção.
_Por que?_
> Faz com que o seu código seja mais legível e natual.
<a name="enforcing-code-style-standards"></a>
### 7.2 Force o code style
- Use o arquivo [.editorconfig](http://editorconfig.org/) para ajudar a definir e manter a consistência de estilo de código entre diferentes editores e IDE.
_Por que?_
> O EditorConfig consiste em um arquivo para edição de estilo de código e declaração de plugins para habilitar o editor a ler os arquivos em um determinado formato e formatá-los de acordo com o esperado. EditorConfig são fáceis de ler e funcionam muito bem com sistemas de controle de versão.
- Configure seu editor para alertar sobre erros de estilo de código. Use [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) e [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) com seu arquivo ESLint já existente. [Leia mais sobre...](https://github.com/prettier/eslint-config-prettier#installation)
- Considere usar Git Hooks.
_Por que?_
> Git hooks aumentam de forma expressiva a produtividade do desenvolvedor. Faça alterações, commit e push sem o medo de quebrar o código pronto para produção. [Leia mais sobre...](http://githooks.com/)
- Use Prettier com o precommit hook.
_Por que?_
> O `prettier` por si só pode ser bem poderoso porém, não é muito produtivo rodar uma npm task sozinha toda hora só para formatar o código. É então que o `lint-staged` (e o `husky`) entram em ação. Leia mais sobre como configurar o `lint-staged` [aqui](https://github.com/okonet/lint-staged#configuration) e sobre o `husky` [aqui](https://github.com/typicode/husky).
<a name="logging"></a>
## 8. Logging
![Logging](/images/logging.png)
- Evite console logs no client-side em produção
_Por que?_
> Mesmo que o seu processo de compilação possa (e deva) se livrar deles, certifique-se de que seu lint de código avise sobre os console logs restantes.
- Crie logs de produção legíveis. O ideal é utilizar bibliotecas de log em produção (como, por exemplo [winston](https://github.com/winstonjs/winston) ou
[node-bunyan](https://github.com/trentm/node-bunyan)).
_Por que?_
> Ele torna sua solução de problemas mais agradável com sistema de cores, data e hora, registra em um arquivo além do console e até mesmo pode atualizar o arquivo diariamente. [saiba mais...](https://blog.risingstack.com/node-js-logging-tutorial/)
<a name="api"></a>
## 9. API
<a name="api-design"></a>
![API](/images/api.png)
### 9.1 API design
_Por que?_
> Queremos promover o desenvolvimento de RESTful interfaces bem construídas, fazendo com que o consumo por clientes e pelo time seja simples e consistente.
_Por que?_
> Falta de consistência e simplicidade podem aumentar de forma expressiva os custos de manutenção e integração. E por isso `API design` está nesse documento.
- Devemos seguir o padrão orientado a recursos. O qual tem 3 principais fatore: recursos, coleções, e URLs.
- Um recurso possui dados, gets aninhados, e methods para permitir operações.
- Um grupo de recursos é chamado coleção.
- URL identifica a localização online de um recurso ou coleção.
_Por que?_
> Esse é um padrão muito bem conhecido por desenvolvedores (os principais consumidores de sua API). Fora o fato de ser fácil de usar e ler, permite-nos escrever bibliotecas genéricas e conectores sem ao menos precisar saber sobre o que a API é.
- use kebab-case para as URLs.
- use camelCase para os parâmetros na query string ou campo de recursos.
- use o plural do kebab-case nome dos recursos na URL.
- Sempre use o plural para nomear algum recurso na URL ou coleção: `/users`.
_Por que?_
> Basicamente, é melhor para ler e torna a URL mais consistente. [Leia mais sobre...](https://apigee.com/about/blog/technology/restful-api-design-plural-nouns-and-concrete-names)
- No código fonte, converta plurais para variáveis e propriedades com uma lista de sufixos.
_Por que?_
> Plural é interessante para URLs mas no código é muito sucetível a erros.
- Sempre use um conceito singular que comece com a coleção e termine com um identificador:
```
/students/245743
/airports/kjfk
```
- Evite URLs como:
```
GET /blogs/:blogId/posts/:postId/summary
```
_Por que?_
> Isso não está apontando para um recurso mas, para uma propriedade. Você pode passar a propriedade como um parâmetro para encurtar a resposta.
- Matenha as URLs de recursos sem verbos.
_Por que?_
> Porque se você usar verbos para cada operação em um recurso você vai acabar com uma lista enorme de URLs e nenhum padrão consistente, o que torna difícil para desenvolvedores lerem. Além disso, nos usamos verbos para outra situação.
- Use verbos para 'não recursos'. Nesse caso, sua API não retorna nenhum recurso. Ao invés, você executa uma operação que retorna um resultado. Essas **não são** operações de um CRUD (criar, ler, atualizar, e deletar):
```
/translate?text=Hallo
```
_Por que?_
> Porque para CRUD nos usamos os métodos HTTP nos `recursos` ou `coleções`. Os verbos que estamos falando são literalmente `Controllers`. Você geralmente não chega a desenvolver muito deles. [Leia mais sobre...](https://byrondover.github.io/post/restful-api-guidelines/#controller)
- Use `camelCase` para as propriedades no `JSON` das requisições e da repostas do servidor para manter a consistência.
_Por que?_
> Esse é um padrão de projeto para JavaScript, onde a linguagem usada para gerar e parsear JSON é, em teoria, JavaScript.
- Mesmo que um recurso seja um conceito singular, similar à uma instância ou registro do banco de dados, você não deve usar `nome_da_tabela` para o nome de um recurso e `nome_da_coluna` para a propriedade de um recurso.
_Por que?_
> Porque sua intenção é expor os recursos, não detalhes do schema do seu banco de dados.
- Novamente, apenas use substantivos quando nomeando a URL de um recurso e não tente explicar a funcionalidade.
_Por que?_
> Apenas use substantivos nos recursos na URL, evite coisas como `/addNewUser` ou `/updateUser`. Também, evite enviar operações sobre os recursos como parâmetros.
- Explicite as operações de CRUD usando funcionalidades do métodos HTTP:
_Como:_
> `GET`: Para obter/recuperar um recurso.
> `POST`: Para criar um novo recurso ou sub-recurso.
> `PUT`: Para atualizar recursos existentes.
> `PATCH`: Para atualizar recursos existentes. Atualiza apenas os campos enviados deixando as outras propriedades como eram.
> `DELETE`: Para deletar um recurso existente.
* Para recursos aninhados, use a relação entre eles e a URL. Por exemplo, usando `id` para se referir a um usuário específico.
_Por que?_
> Esse é um jeito natural de tornar os recursos fáceis de explorar.
_Como?_
> `GET /schools/2/students` , Deve obter a lista de estudantes da escola com ID 2.
> `GET /schools/2/students/31` , Deve obter os detalhes do estudante 31, que pertence a escola 2.
> `DELETE /schools/2/students/31` , Deve deletar o estudante 31, que pertence a escola 2.
> `PUT /schools/2/students/31` , Deve atualizar as informações do estudante 31, Use PUT apenas para URL de recursos, não para coleções.
> `POST /schools` , Deve criar uma nova escola e retornar os detalhes da nova escola criada. Use POST em URL de coleções.
* Use um simples número ordinal para a versão com o prefixo `v` (v1, v2). Coloque a versão à esquerda de todos URL da api:
```
http://api.domain.com/v1/schools/3/students
```
_Por que?_
> Quando suas APIs são públicas, atualizar a API com alguma mudança que quebra o funcionamento antigo (Breaking Change) pode levar ao mal funcionamento de vários produtos e serviços que dependem da sua API. Usnado versões na URL você previne isso de acontecer. [Leia mais sobre...](https://apigee.com/about/blog/technology/restful-api-design-tips-versioning)
- Messagens das respostas devem ser auto descritivas. Uma boa mensagem de erro deve ser algo parecido com:
```json
{
"code": 1234,
"message": "Algo de errado aconteceu",
"description": "Mais detalhes"
}
```
Ou para validação de erros:
```json
{
"code": 2314,
"message": "Validação Falhou",
"errors": [
{
"code": 1233,
"field": "email",
"message": "Email inválido"
},
{
"code": 1234,
"field": "password",
"message": "Senha em branco"
}
]
}
```
_Por que?_
> Desenvolvedores dependem de erros bem descritivos em momentos críticos quando eles estão com dificuldades resolvendo problemas da aplicação que eles construíram usando sua API.
_Nota: Mantenha mensagens relacionadas a exceções de segurança o mais genéricas possível. Por exemplo, ao invés de 'Senha incorreta', você pode responder dizendo 'Usuário ou senha inválidos' para que não vaze informações sobre dados corretos que não deveriam ser conhecido por terceiros._
- Use códigos de status para enviar e descrever suas respostas ao invés de **tudo funcionou corretamente**,
**App do cliente fez algo errado** ou A **API fez algo errado**.
_Quais?_ > `200 OK` resposta de sucesso para requisições `GET`, `PUT` ou `POST`.
> `201 Created` para quando uma nova instância é criada. Criar uma nova instância usando `POST` deve retornar o código de status `201`.
> `204 No Content` resposta representa sucesso porém não tem nenhum conteúdo para ser enviado na resposta. Use quando operações com `DELETE` são bem sucedidas.
> `304 Not Modified` resposta para minimizar informações trafegadas quando o "requerente" já possui os dados em cache.
> `400 Bad Request` para quando a requisição não foi processada, como por exemplo quando o servidor não compreendeu o conteúdo da requisição.
> `401 Unauthorized` para quando a requisição não possui credenciais suficientes para ser executada.
> `403 Forbidden` siginifica que o servidor entendeu a requisição mas se recusa a realizá-la.
> `404 Not Found` indica que o recurso da requisição não foi encontrado.
> `500 Internal Server Error` indica que a requisição foi recebida mas devida à algum erro interno a requisição não pode ser completada.
_Por que?_
> A maioria das APIs fornecem um algum subconjunto de códigos de status HTTP. Por exemplo, a API do Google GData usa apenas 10 códigos, Netflix usa 9, e Digg, apenas 8. Evidente que essas requisições possuem dados com informações adicionais. Existem mais de 70 códigos de status HTTP. De qualquer forma, A maioria dos desenvolvedores não tem todos memorizados. Então se você escolher códigos que não são muito comuns pode assustar e repelir desenvolvedores de usar sua API. [Leia mais sobre...](https://apigee.com/about/blog/technology/restful-api-design-what-about-errors)
* Forneça o número total de recursos na sua resposta.
* Aceite `limit` e `offset` como parâmetros.
* A quantidade de dados que os recursos expõem deve ser levado em consideração. O consumidor da API nem sempre precisa ter uma representação completa do recurso. Use `fields` na query string para filtrar propriedades a serem enviadas:
```
GET /student?fields=id,name,age,class
```
* Paginação, filtragem e ordenação não precisam ser suportadas inicialmente para todos os recursos. Documente os recursos que oferecem tais funcionalidades.
<a name="api-security"></a>
### 9.2 API security
Algumas boas práticas básicas de segurança:
- Não use autenticação básica a não ser sob uma conexão HTTPS. Tokens de autenticação não devem ser enviados na URL: `GET /users/123?token=asdf....`
_Por que?_
> Porque tokens ou ID de usuário e senha são enviados pela rede como texto (encoded como base64, mas base64 é um encoding reversível), o esquema básico de autenticação não é seguro [Leia mais sobre...](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication)
- Tokens devem ser enviados fazendo uso do header `Authorization` em todas as requisições: `Authorization: Bearer xxxxxx, Extra yyyyy`.
- Códigos de autorização devem ter "tempo de vida curto".
- Rejeite qualquer requisição não-TLS não respondendo nenhuma requisição HTTP para evitar vazamento de dados. Apenas responda `403 Forbidden`.
- Considere usar Limite de requisições.
_Por que?_
> Para proteger sua API de requisições maliciosas repetidas milhares de vezes por hora. Você deve considerar implementar Limite de requisições o mais cedo possível.
- Configurando os headers HTTP corretamente pode te ajudar a protejer sua aplicação web. [Leia mais sobre...](https://github.com/helmetjs/helmet)
- Sua API deve converter os dados recebidos para sua forma canônica ou rejeita-los. Retrone status `400 Bad Request` com detalhes sobre os de dados errados ou faltantes.
- Todos os dados trocados com a API REST devem ser validados pela API.
- Serialize seu JSON.
_Por que?_
> Uma das principais preocupações lidando com JSON encoders é previnir JavaScript malicioso de ser executado no browser... Ou, se você está usando `node.js`, no servidor. É vital usar JSON corretamente serializados para evitar a execução de código enviado como input pelo broswer.
- Valide o content-type e na maioria dos casos use `application/*json` (Content-Type header).
_Por que?_
> Por exemplo, aceitando `application/x-www-form-urlencoded` mime type permite que alguém com má intenções crie um form e execute uma simple requisição POST. O servidor nunca deve tentar adivinhar o Content-Type. A falta do Content-Type ou um Content-Type inesperado deve resultar no servidor recusando a request com um erro `4XX` na resposta.
- Confira o checklist de segurança para um projeto de API. [Leia mais sobre...](https://github.com/shieldfy/API-Security-Checklist)
<a name="api-documentation"></a>
### 9.3 API documentation
- Complete a seção `API Reference` no [README.md Template](./README.sample.md) para sua API.
- Descreva os métodos de autenticação da sua API com exemplos de código.
- Explique a estrutura de recursos da sua URL (apenas o caminho do recurso) incluindo o tipo de request (Método).
Para cada `endpoint` explique:
- Parâmetros da URL se existirem, especifique de acordo com os nomes na descritos na seção de URL:
```
Required: id=[integer]
Optional: photo_id=[alphanumeric]
```
- Se o tipo da requisiçõa é POST, forneça alguns exemplos de código. Essa regra se aplica para parâmetros de URL também. Separe a seção entre `Requeridos` e `Opcionais`.
- Resposta de sucesso, qual deveria ser o código de status e tem algum dado à ser retornado junto? Isso é útil quando as pessoas precisam saber o que os seus `callbacks` devem esperar:
```
Code: 200
Content: { id : 12 }
```
- Mensagens de erro, a maioria dos `endpoints` possuem várias maneiras de falhar. De acesso negado à parâmetros errados e etc. Todos devem ser listados. Pode parecer repetitivo, mas ajuda a previnir que desenvolvedores tentem prever o que vai acontecer. Por exemplo
-
```json
{
"code": 403,
"message": "Authentication failed",
"description": "Invalid username or password"
}
```
* Use ferramentas de design de API, existem muitas ferramentas de código aberto para uma boa documentação como [API Blueprint](https://apiblueprint.org/) e [Swagger](https://swagger.io/).
<a name="licensing"></a>
## 10. Licença
![Licensing](/images/licensing.png)
Tenha certeza de usar recursos aos quais você possui o direito de uso. Se você usa bibliotecas, lembre-se de procurar por MIT, Apache ou BSD mas se você precisa modifica-las, então confira nos detalhes da licença. Imagens e vídeos com copyright podem te causar problemas.
---
Fontes:
[RisingStack Engineering](https://blog.risingstack.com/),
[Mozilla Developer Network](https://developer.mozilla.org/),
[Heroku Dev Center](https://devcenter.heroku.com),
[Airbnb/javascript](https://github.com/airbnb/javascript),
[Atlassian Git tutorials](https://www.atlassian.com/git/tutorials),
[Apigee](https://apigee.com/about/blog),
[Wishtack](https://blog.wishtack.com)
Icons by [icons8](https://icons8.com/)

View File

@ -1,51 +0,0 @@
[English](./README.md)
[<img src="https://git.sthope.dev/sthope/.gitea/raw/branch/master/avatar-sthope.png" align="right" width="13%" height="13%">](https://www.sthope.dev/)
# Project_Name &middot; [![Build Status](https://img.shields.io/drone/build/sthope/gitea_templates?server=https%3A%2F%2Fdrone.sthope.dev&style=plastic)](../../..) [![MIT license](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=plastic&logo=appveyor)](LICENSE)
> 🔥[Sthope](https://www.sthope.dev)
Uma breve descrição do teu projeto e para que é utilizado.
## :construction_worker: Instalação / Introdução
Uma introdução rápida da configuração mínima necessária.
```shell
commands here
```
Aqui deves dizer o que realmente acontece quando executas o código acima.
## :trophy: Versioning
Este projecto usa [semantic releases](https://github.com/cenk1cenk2/drone-semantic-release) para controle de versões. For the versions available, see the [Tags](../../../tags).
## 📥 Configuração
example_how_it_works
## :bug: Problemas
Fique a vontade **para criar uma nova issue** com o respectivo título e descrição na página [issues](../../../issues) do Repositório.
Se já encontrou a solução para o problema, [**Eu adoraria fazer o review do pull request**](../../../pulls)!
## :tada: Contribuir
Em primeiro lugar, obrigado por estar interessado em ajudar, o seu tempo é sempre apreciado! :100:
Aqui estão algumas dicas:
* Verifique a [página de problemas](../../../issues) para problemas já abertos (ou talvez até mesmo fechados) que já podem resolver a sua questão / bug / feature request.
* Feature requests são bem-vindos! Forneça alguns detalhes sobre porque isso seria útil para si e para outras pessoas e, se possível, até mesmo alguns print screens!
Verifique a página [contributing](./CONTRIBUTING.md) para ver os melhores locais para registrar questões, iniciar discussões e começar a contribuir.
## :closed_book: Licença
Lançado em 2021 :closed_book: License
Made with :heart: by [Sthope](https://www.sthope.dev)
Para mais informações, consulte a [LICENÇA](LICENSE) file.
<small>Give a ⭐️ if this project helped you!</small>

792
README-ru.md Normal file
View File

@ -0,0 +1,792 @@
[中文版](./README-zh.md)
| [日本語版](./README-ja.md)
| [한국어](./README-ko.md)
| [English](./README.md)
| [Português](./README-pt-BR.md)
[<img src="./images/elsewhen-logo.png" width="180" height="180">](https://www.elsewhen.com/)
# Советы по созданию проектов &middot; [![ПРы приветствуются](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
> Тогда как для некоторых разработка нового проекта - это прогулка по парку, то для других поддержка этого проекта - полнейший кошмар.
Здесь представлен список советов, которые мы нашли, написали, собрали и которые, как мы думаем, прекрасно подходят к большинству JavaScript проектов в [elsewhen](https://www.elsewhen.com).
Если вы хотите поделиться лучшей практикой или считаете, что какой-нибудь из советов стоит убрать, [можете спокойно сообщить нам об этом](http://makeapullrequest.com).
🔥 [Попробуйте](https://github.com/elsewhencode/react-redux-saucepan) наш [минималистичный react redux проект](https://github.com/elsewhencode/react-redux-saucepan) на Flow с горячей заменой кода (hot reloading) и серверным рендерингом (SSR, server-side rendering).
<hr>
- [Git](#git)
- [Правила работы с Git](#some-git-rules)
- [Рабочий процесс в Git](#git-workflow)
- [Пишем хорошее сообщение коммита](#writing-good-commit-messages)
- [Документация](#documentation)
- [Окружения](#environments)
- [Консистентные dev окружения](#consistent-dev-environments)
- [Консистентные зависимости](#consistent-dependencies)
- [Зависимости](#dependencies)
- [Тестирование](#testing)
- [Структура и Именование](#structure-and-naming)
- [Оформление кода](#code-style)
- [Советы по оформлению кода](#code-style-check)
- [Обеспечение определенного стиля кода](#enforcing-code-style-standards)
- [Логирование](#logging)
- [API](#api)
- [Дизайн API](#api-design)
- [Безопасность API](#api-security)
- [Документация API](#api-documentation)
- [Лицензирование](#licensing)
<a name="git"></a>
## 1. Git
![Git](/images/branching.png)
<a name="some-git-rules"></a>
### 1.1 Правила работы с Git
Набор правил, которые следует иметь ввиду:
* Разрабатывайте в `feature/*` ветке.
_Зачем:_
> Таким образом вся работа выполняется изолированно в отдельной ветке, а не в главной. Это позволит создать множество запросов на слияние (pull requests) без путаницы. Вы можете продолжить разработку без загрязнения `master` ветки потенциально нестабильным и незаконченным кодом. [узнать больше...](https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow)
* Откалывайте ветку от `develop`
_Зачем:_
> Чтобы быть уверенным, что код в `master` ветке практически всегда собирается без проблем, и, в основном, может быть использован для релизов (это может быть излишним для некоторых проектов).
* Никогда не выкладывайте (push) коммиты напрямую в `develop` или `master` ветки. Создавайте Запрос на Слияние (Pull Request).
_Зачем:_
> Так члены команды получат оповещение, что работа над новой функцией (feature) завершена. Также это облегчит процесс рецензирования кода (code review) и предоставит площадку для обсуждения предложенной функции.
* Обновляйте вашу локальную `develop` ветку и делайте интерактивное перебазирование (rebase) перед тем как выкладывать (push) свою новую функцию и создавать Запрос на Слияние (Pull Request).
очему:_
> Перебазирование сольет (merge) коммиты из запрошенной ветки (`master` или `develop`) в текущую и вставит те, которые вы сделали локально, в самый конец истории без создания коммита слияния (merge commit), если не возникнут конфликты. В результате чего получим линейную и чистую историю изменений. [узнать больше...](https://www.atlassian.com/git/tutorials/merging-vs-rebasing)
* Разрешите потенциальные конфликты в процессе перебазирования (rebase) перед тем как создавать Запрос на Слияние (Pull Request).
* Удалите локальные и удаленные (remote) ветки после сливания (merge).
_Зачем:_
> Чтобы не загромождать ваш список веток мертвыми ветками. Это гарантирует, что вы сольете (merge) вашу ветку обратно (`master` или `develop`) только один раз. `feature/*` ветки должны существовать пока не будет завершена разработка.
* Перед созданием Запроса на Слияние (Pull Request) убедитесь, что ваша `feature/*` ветка успешно собирается и все тесты проходят успешно, включая проверки на оформление кода.
_Зачем:_
> Вы собираетесь добавить ваш код в стабильную ветку. Если тесты в вашей `feature/*` ветке не проходят, то с большой долей вероятности стабильная ветка тоже не сможет собраться. Дополнительно надо будет запустить проверку на оформление кода перед созданием Запроса на Слияние (Pull Request). Это улучшит читаемость кода и уменьшит шанс, что изменения в оформлении смешаются с реальными изменениями.
* Используйте [этот](./.gitignore) `.gitignore` файл.
очему:_
> Он уже включает в себя список системных файлов, которые не надо посылать вместе с вашим кодом в удаленный репозиторий. К тому же он исключает не только файлы и папки с настройками для большинства используемых редакторов кода, но и самые распространенные папки с зависимостями.
* Обезопасьте ваши `develop` и `master` ветки.
_Зачем:_
> Это защитит ваши готовые для релиза ветки от получения неожиданных и необратимых изменений. Узнать больше: [Github](https://help.github.com/articles/about-protected-branches/), [Bitbucket](https://confluence.atlassian.com/bitbucketserver/using-branch-permissions-776639807.html) и [GitLab](https://docs.gitlab.com/ee/user/project/protected_branches.html)
<a name="git-workflow"></a>
### 1.2 Рабочий процесс в Git
Исходя из большинства причин, описанных выше, стоит использовать [Рабочий процесс с использованием `feature/*` ветки](https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow) с [Интерактивным Перебазированием (rebase)](https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing) и некоторые элементы [Gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows#gitflow-workflow) (наименования и использование develop ветки). Основные шаги следующие:
* Для нового проекта инициализируем git репозиторий в папке с проектом. __Для последующих новых функций/изменений этот шаг нужно игнорировать__.
```sh
cd <project directory>
git init
```
* Создаем новую `feature/bug-fix` ветку.
```sh
git checkout -b <branchname>
```
* Делаем изменения.
```sh
git add <file1> <file2> ...
git commit
```
ояснение:_
> `git add <file1> <file2> ... ` - необходимо добавлять только те файлы, которые вносят небольшие и последовательные изменения.
> `git commit` запустит редактор, который позволит разделить в сообщении коммита краткое описание от полного.
> Больше об этом в [*разделе 1.3*](#writing-good-commit-messages).
_Совет:_
> Также вместо `git add` вы можете использовать `git add -p`, который позволит последовательно просмотреть изменения, представленные в коммите, и решить - включать их в коммит или нет.
* Синхронизируйтесь с удаленным репозиторием, чтобы получить изменения, которые вы пропустили.
```sh
git checkout develop
git pull
```
_Зачем:_
> Это даст вам шанс решить конфликты на вашей локальной машине во время перебазирования (rebase) перед созданием Запроса на Слияние (Pull Request), содержащего конфликты.
* Вливайте в вашу `feature/*` ветку последние изменения из `develop` ветки, используя интерактивное перебазирование (rebase).
```sh
git checkout <branchname>
git rebase -i --autosquash develop
```
ояснение:_
> Вы можете использовать `--autosquash`, чтобы объединить ваши коммиты в один. Никто не хочет создавать множество коммитов ради одной новой функции в `develop` ветке. [узнать больше...](https://robots.thoughtbot.com/autosquashing-git-commits)
* Если у вас нет конфликтов, пропустите этот шаг. Если же они возникли, [решите их](https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/) и продолжайте перебазирование (rebase).
```sh
git add <file1> <file2> ...
git rebase --continue
```
* Отправьте (push) вашу ветку в удаленный репозиторий. Перебазирование (rebase) меняет историю коммитов, поэтому вам придется использовать `-f`, чтобы форсировать изменения в удаленную ветку. Если кто-то еще работает в вашей ветке, используйте менее деструктивный флаг `--force-with-lease`.
```sh
git push -f
```
очему:_
> Когда вы делаете перебазирование (rebase), вы меняете историю вашей `feature/*` ветки. Как результат, Git отклонит обычный `git push`. Поэтому вам надо использовать флаг `-f` или `--force`. [узнать больше...](https://developer.atlassian.com/blog/2015/04/force-with-lease/)
* Создайте Запрос на Слияние (Pull Request).
* Запрос на Слияние (Pull Request) будет принят, слит (merge) и закрыт рецензентом.
* Удалите вашу локальную `feature/*` ветку, если работа в ней завершена.
```sh
git branch -d <branchname>
```
Удалите все локальные ветки, которых больше нет в удаленном репозитории.
```sh
git fetch -p && for branch in `git branch -vv --no-color | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done
```
<a name="writing-good-commit-messages"></a>
### 1.3 Пишем хорошее сообщение коммита
Хороший гайдлайн по создании коммитов и следование ему облегчит работу с Git и сотрудничество с другими разработчиками. Вот несколько правил большого пальца ([источник](https://chris.beams.io/posts/git-commit/#seven-rules)):
* Разделите краткое описание коммита от основного, используя разрыв строки между ними.
_Зачем:_
> Git достаточно умный, чтобы распознавать первую строку вашего сообщения коммита, как краткое описание. По факту, если вы попробуете `git shortlog` вместо `git log`, вы увидите длинный список сообщений коммитов, состоящий только из идентификатора (id) коммита и краткого описания.
* Ограничьте краткое описание 50 символами, а основное описание - 72 символами.
_Зачем:_
> Коммиты должны быть краткими и максимально сфокусированными; это не место для многословия. [узнать больше...](https://medium.com/@preslavrachev/what-s-with-the-50-72-rule-8a906f61f09c)
* Начните краткое описание с заглавной буквы.
* Не заканчивайте краткое описание точкой.
* В кратком описании используйте [повелительное наклонение](https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%B2%D0%B5%D0%BB%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BD%D0%B0%D0%BA%D0%BB%D0%BE%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5).
очему:_
> Вместо того, чтобы писать в сообщениях что сделал разработчик, лучше относиться к этим сообщениям, как к инструкциям что произойдет после того, как коммит попадет в ветку. [узнать больше...](https://news.ycombinator.com/item?id=2079612)
* Используйте основное описание, чтобы объяснить **что** и **почему** вместо **как**.
<a name="documentation"></a>
## 2. Документация
![Документация](/images/documentation.png)
* Используйте этот [шаблон](./README.sample.md) для `README.md`, свободно добавляйте отсутствующие разделы.
* Для проектов с множеством репозиториев укажите ссылки на них в соответствующих `README.md` файлах.
* Постоянно обновляйте `README.md` по мере развития проекта.
* Пишите комментарии в коде. Старайтесь сделать код максимально прозрачным, чтобы было понимание что именно задумывалось в каждом основном фрагменте.
* Если открыта дискуссия на github или stackoverflow по поводу кода или подхода, который вы используете, оставьте ссылку на эту дискуссию в вашем комментарии.
* Не используйте комментарии в качестве оправдания плохого кода. Сохраняйте ваш код в чистоте.
* Не используйте чистый код в качестве оправдания полного отсутствия комментариев.
* Обновляйте ваши комментарии по мере развития проекта.
<a name="environments"></a>
## 3. Окружения
![Окружения](/images/laptop.png)
* Определите отдельные `development`, `test` и `production` окружения, если есть такая необходимость.
_Зачем:_
> Различные данные, токены, API, порты и т.п. могут быть использованы в разных окружениях. Например, вам может понадобиться изолированный `development` режим, для того чтобы вызывать тестовое API, которое будет возвращать предсказуемые данные, делая автоматическое и ручное тестирование в разы проще. Или вам нужна Google аналитика (Google Analytics) только в `production` окружении и т.д. [узнать больше...](https://stackoverflow.com/questions/8332333/node-js-setting-up-environment-specific-configs-to-be-used-with-everyauth)
* Загружайте ваши специфичные для развертывания конфигурации из переменных окружения и никогда не добавляйте их, как константы, в код проекта. [Пример файла](./config.sample.js).
очему:_
> Вы храните токены, пароли и другую важную информацию в конфигурации. Ваша конфигурация должна быть корректно отделена от основной части приложения, как будто ваш код может стать публичным в любое время.
_Как:_
> Используйте `.env` файлы для хранения важных данных. Обязательно добавьте их в `.gitignore`, чтобы исключить попадание в Git, взамен создайте коммит с `.env.example` файлом, который будет служить как шаблон для разработчиков. Для релизного стенда вы должны устанавливать переменные окружения стандартным методом.
[узнать больше...](https://medium.com/@rafaelvidaurre/managing-environment-variables-in-node-js-2cb45a55195f)
* Рекомендуется валидировать переменные окружения перед запуском приложения. [Данный пример](./configWithTest.sample.js) использует `joi` для валидации представленных параметров.
_Зачем:_
> Это поможет сэкономить другим часы поиска проблемы.
<a name="consistent-dev-environments"></a>
### 3.1 Консистентные dev окружения:
* Установите вашу версию Node.js в `engines` в файле `package.json`.
_Зачем:_
> Это позволит другим разработчикам узнать, какая версия Node.js используется в проекте. [узнать больше...](https://docs.npmjs.com/files/package.json#engines)
* Дополнительно используйте `nvm` и создайте `.nvmrc` в корне вашего проекта. Не забудьте упомянуть это в документации.
_Зачем:_
> Любой, кто использует `nvm`, сможет спокойно вызвать `nvm use`, чтобы переключиться на подходящую версию Node.js. [узнать больше...](https://github.com/creationix/nvm)
* Хорошей идеей будет настроить `preinstall` скрипт, который будет проверять версии Node.js и npm.
очему:_
> Некоторые зависимости могут не установиться при использовании новых версий npm.
* Используйте Docker образ, если можете.
_Зачем:_
> Это даст вам консистентное окружение во всем рабочем процессе. Без необходимости копаться с зависимостями и конфигами. [узнать больше...](https://hackernoon.com/how-to-dockerize-a-node-js-application-4fbab45a0c19)
* Используйте локальный модули вместо глобально установленных.
очему:_
> Если вы будете использовать глобальные модули, то вам будет сложно поделиться вашим инструментом с коллегами, так как на их системах должны будут установлены эти же модули. Локально модули решают эту задачу путем автоматического добавления всех необходимых зависимостей при установке инструмента.
<a name="consistent-dependencies"></a>
### 3.2 Консистентные зависимости:
* Убедитесь, что ваши коллеги получат точно такие же зависимости, что и вы.
очему:_
> Потому что код должен вести себя предсказуемо и идентично тому, как он выполняется на машине разработчика. [узнать больше...](https://medium.com/@kentcdodds/why-semver-ranges-are-literally-the-worst-817cdcb09277)
_Как:_
> Используйте `package-lock.json` в `npm@5` или версией выше.
_Если нет npm@5:_
> То вы можете использовать `Yarn`, но не забудьте упомянуть об этом в `README.md`. Файлы `yarn.lock` и `package.json` должны содержать одни и те же версии после каждого обновления зависимостей. [узнать больше...](https://yarnpkg.com/en/)
_Если вам не нравится `Yarn`:_
> Печально. Для старших версий `npm` используйте `—save --save-exact` при установке новых зависимостей и создайте `npm-shrinkwrap.json` перед публикованием пакета. [узнать больше...](https://docs.npmjs.com/files/package-locks)
<a name="dependencies"></a>
## 4. Зависимости
![Модули](/images/modules.png)
* Следите за вашими текущими пакетами: `npm ls --depth=0`. [узнать больше...](https://docs.npmjs.com/cli/ls)
* Проверьте ваши пакеты на наличие неиспользуемых или ненужных: `depcheck`. [узнать больше...](https://www.npmjs.com/package/depcheck)
_Зачем:_
> Вы могли добавить неиспользуемую библиотеку в ваш код и, тем самым, увеличить итоговый размер релизной сборки. Найдите неиспользуемые зависимости и избавьтесь от них.
* Перед использованием зависимости проверьте её статистику скачиваний, чтобы узнать как часто она используется в сообществе: `npm-stat`. [узнать больше...](https://npm-stat.com/)
_Зачем:_
> Частое использование подразумевает большое количество соавторов, что обычно означает лучшую поддержку и все это, в итоге, приводит к быстрому нахождению и исправлению багов.
* Перед использованием зависимости проверьте, есть ли у нее хороший, зрелый релизный цикл с большим числом людей, ведущих разработку пакета: `npm view async`. [узнать больше...](https://docs.npmjs.com/cli/view)
_Зачем:_
> От большого количества соавторов не будет пользы, если люди, ведущие разработку пакета, не будут сливать (merge) исправления и патчи вовремя.
* Если есть необходимость в малоизвестной зависимости, обсудите это с командой перед использованием.
* Всегда проверяйте, что ваше приложение работает с последними версиями зависимостей без поломок: `npm outdated`. [узнать больше...](https://docs.npmjs.com/cli/outdated)
_Зачем:_
> Обновления зависимости иногда могут содержать переломные изменения (breaking changes). Всегда проверяйте релизные примечания (release notes), когда появляется новое обновление. Обновляйте ваши зависимости по очереди, это сделает процесс поиска потенциальных проблем проще. Используйте такой крутой инструмент, как [npm-check-updates](https://github.com/tjunnone/npm-check-updates).
* Проверьте, есть ли у пакета известные уязвимости безопасности инструментом [Snyk](https://snyk.io/test?utm_source=risingstack_blog).
<a name="testing"></a>
## 5. Тестирование
![Тестирование](/images/testing.png)
* Используйте `test` окружение, если есть необходимость.
очему:_
> Хотя в некоторых случаях сквозного (end-to-end) тестирования в `production` окружении будет достаточно, есть несколько исключений. Например, при тестировании вам не нужно отправлять аналитические данные, чтобы не забить тестовыми данными чью-нибудь панель управления (dashboard). Другой пример: у вашего API может быть ограничение на количество запросов в `production` окружении и ваши тестовые запросы могут заблокироваться, если лимит будет превышен.
* Размещайте ваши файлы с тестами рядом с тестируемыми модулями, используя следующее соглашение о наименовании: `*.test.js` или `*.spec.js`, например `moduleName.spec.js`.
_Зачем:_
> Вам не придется копаться в структуре папок, чтобы найти файл модульного тестирования (unit test). [узнать больше...](https://hackernoon.com/structure-your-javascript-code-for-testability-9bc93d9c72dc)
* Размещайте дополнительные файлы с тестами в отдельной папке, чтобы исключить путаницу.
очему:_
> Некоторые файлы с тестами невозможно отнести к какому-либо файлу с реализацией. Такие тесты надо размещать в папке, где другие разработчики смогут легко их найти: папка `__test__`. Имя папки `__test__` теперь является стандартом и многие JavaScript фреймворки для тестирования его используют.
* Пишите тестируемый код, избегайте побочных эффектов, выносите побочные эффекты, пишите чистые функции.
_Зачем:_
> Бизнес-логику лучше тестировать как отдельные единицы. Вам надо "минимизировать влияние случайных факторов и недетерминированных процессов на надежность вашего кода". [узнать больше...](https://medium.com/javascript-scene/tdd-the-rite-way-53c9b46f45e3)
ояснение:_
> Чистая функция - это функция, которая всегда возвращает одинаковый результат, когда она вызывается с тем же набором аргументов. И, наоборот, нечистая функция - это функция, у которой есть побочные эффекты, и/или которая зависит от внешних условий, чтобы вернуть значение. Это делает их менее предсказуемыми. [узнать больше...](https://hackernoon.com/structure-your-javascript-code-for-testability-9bc93d9c72dc)
* Используйте статическую проверку типов.
_Зачем:_
> Иногда вам может понадобиться Статическая проверка типов. Она привнесет некоторый уровень надежности вашему коду. [узнать больше...](https://medium.freecodecamp.org/why-use-static-types-in-javascript-part-1-8382da1e0adb)
* Запускайте тесты локально перед тем как создавать Запрос на Слияние (Pull Request) в `develop` ветку.
_Зачем:_
> Вам не захочется оказаться тем человеком, который сломал сборку в ветке, готовой для релиза. Запускайте тесты после перебазирования `rebase` и перед отправкой (push) `feature/*` ветки в удаленный репозиторий.
* Задокументируйте инструкцию по работе с тестами в соответствующем разделе вашего `README.md` файла.
_Зачем:_
> Вы оставите полезное примечание для других разработчиков, DevOps экспертов, тестировщиков или кого-либо еще, кому повезет работать с вашим кодом.
<a name="structure-and-naming"></a>
## 6. Структура и Именование
![Структура и Именование](/images/folder-tree.png)
* Структурируйте ваши файлы вокруг продуктовых функций / страниц / компонентов, а не ролей. Также размещайте файлы с тестами рядом с файлами, к которым они относятся.
**Плохо**
```
.
├── controllers
| ├── product.js
| └── user.js
├── models
| ├── product.js
| └── user.js
```
**Хорошо**
```
.
├── product
| ├── index.js
| ├── product.js
| └── product.test.js
├── user
| ├── index.js
| ├── user.js
| └── user.test.js
```
очему:_
> Вместо длинных списков файлов вы получите небольшие модули, которые инкапсулируют только одну обязанность и включают в себя тесты и прочие связанные файлы. Навигация в проекте станет гораздо легче, так как нужные файлы будут находиться рядом, сгруппированные по модулям.
* Размещайте дополнительные файлы с тестами в отдельной папке, чтобы избежать путаницы.
очему:_
> Это сэкономит время другим разработчикам или DevOps экспертам в вашей команде.
* Используйте папку `./config` и не создавайте разные файлы с конфигурациями для разных окружений.
очему:_
> Когда вы разбиваете общий файл конфигурации на отдельные файлы (база данных, API и т.п.), то размещение этих файлов в папке с прозрачным именованием, как `config`, имеет смысл. Просто запомните: не создавайте файлы с конфигурациями для разных окружений. Это сложно масштабировать, так как, чем больше создается разных стендов для развертывания (deploys) приложения, тем сложнее будет придумывать новые имена для окружений, чтобы создать файл конфигурации. Для файлов конфигурации нужно использовать значения из переменных окружения. [узнать больше...](https://medium.com/@fedorHK/no-config-b3f1171eecd5)
* Размещайте ваши скрипты в папке `./scripts`. Это включает `bash` и `node` скрипты.
_Зачем:_
> Скорее всего у вас будет больше, чем один скрипт в проекте: для релизной сборки, сборка для разработки, наполнение базы данных, синхронизация базы данных и т.д.
* Размещайте выходные файлы сборки в папке `./build`. Добавьте `build/` в `.gitignore`.
очему:_
> Именуйте папку как хотите, `dist` тоже подойдет. Но стоит убедиться, чтобы имя было консистентно для всей команды. В эту папку будут попадать в основном сгенерированные файлы (упакованные, компилированные, транслированные) или просто перемещенные. То, что вы сможете сгенерировать, должно генерироваться и у ваших коллег, поэтому нет смысла добавлять эти файлы к кодовой базе (коммитить) и отправлять в удаленный репозиторий. Если вам это не нужно.
<a name="code-style"></a>
## 7. Оформление кода
![Оформление кода](/images/code-style.png)
<a name="code-style-check"></a>
### 7.1 Советы по оформлению кода
* Используйте stage-2 и выше (современный) синтаксис JavaScript для новых проектов. Для старых проектов стоит придерживаться синтаксиса проекта, если вы не собираетесь его модернизировать.
очему:_
> Stage-2 в скором времени станет частью официального стандарта с небольшими изменениями. В разработке можно задействовать транспилеры, чтобы уже сейчас использовать преимущества нового синтаксиса. Но решать вам.
* Включите проверку на оформление кода в процесс сборки.
_Зачем:_
> Поломка сборки - это один из инструментов, чтобы заставить вас оформлять код в определенном стиле. Это не позволит вам относиться к оформлению кода несерьезно. Сделайте это не только для клиентского кода, но и для серверного. [узнать больше...](https://www.robinwieruch.de/react-eslint-webpack-babel/)
* Вы можете использовать [ESLint - JavaScript linter](http://eslint.org/), чтобы обеспечить соблюдение определенного стиля кода.
очему:_
> Многие предпочитают `eslint`, но выбор за вами. `eslint` поддерживает множество правил, возможность конфигурировать их и добавлять свои.
* Вы можете использовать уже готовый набор правил оформления кода. Например, [руководство по оформлению кода от Airbnb для JavaScript](https://github.com/airbnb/javascript). [узнать больше...](https://www.gitbook.com/book/duk/airbnb-javascript-guidelines/details)
* Если вы пишите на [FlowType](https://flow.org/), то можно использовать [правила оформления кода на FlowType для ESLint](https://github.com/gajus/eslint-plugin-flowtype).
_Зачем:_
> Flow вводит немного новый синтаксис, который нужно обязать следовать определенным правилам оформления кода.
* Используйте `.eslintignore`, чтобы исключить файлы и папки из проверки на оформление кода.
_Зачем:_
> Чтобы не загрязнять ваш код `eslint-disable` комментариями каждый раз, когда вам надо исключить файл из проверки.
* Удалите `eslint-disable` комментарии перед тем как создавать Запрос на Слияние (Pull Request).
очему:_
> В процессе разработки можно выключать проверку на оформление кода, чтобы больше сосредотачиваться на бизнес-логике. Просто не забывайте удалять `eslint-disable` комментарии, когда логика уже написана, чтобы следовать правилам оформления.
* В зависимости от размера задачи, используйте `// TODO:` комментарии или открывайте тикет.
_Зачем:_
> Чтобы напомнить себе и другим о небольших задачах (например, рефакторинг функции или обновление комментария). Для больших задач используйте `// TODO(#3456)`, номер в скобках - это номер открытого тикета.
* Всегда пишите комментарии и актуализируйте их с обновлением кода. Удаляйте закомментированные части кода.
_Зачем:_
> Ваш код должен быть максимально читабельным, вы должны избавиться от всего лишнего. Если вы сделали рефакторинг функции, не комментируйте старую, удалите ее.
* Избегайте неуместных и шуточных комментариев, логов и наименований.
очему:_
> Хотя во время сборки можно/нужно удалить их, иногда ваш исходный код может быть передан в другую компанию/клиенту, и они могут не разделить вашего чувства юмора.
* Используйте имена со смыслом, не сокращайте их, чтобы потом было легко их искать. Для функций используйте длинные и наглядные имена. Имя функции должно быть глаголом или глагольной фразой, и должно сообщать нам что делает функция.
_Зачем:_
> Это облегчит чтение исходного кода и сделает его более естественным.
* Располагайте функции в файле в соответствии с правилом понижения (step-down rule). Сложные составные функции располагаются в начале файла, а затем идут простые функции.
_Зачем:_
> Это облегчит чтение исходного кода и сделает его более естественным.
<a name="enforcing-code-style-standards"></a>
### 7.2 Обеспечение определенного стиля кода
* Используйте файл [.editorconfig](http://editorconfig.org/), который помогает разработчикам определять и поддерживать одинаковые стили оформления кода между разными текстовыми редакторами и средами разработки (IDE) в проекте.
ояснение:_
> Проект EditorConfig состоит из файла, в котором указываются определенные стили оформления кода, и набора плагинов для текстового редактора, которые позволяют редактору прочитать файл и придерживаться стилям кода, определенным в этом файле. Файлы EditorConfig легко читаются и прекрасно работают с системами контроля версий.
* Ваш редактор оповещает вас об ошибках оформления кода? Используйте [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) и [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) с вашим текущими настройками ESLint. [узнать больше...](https://github.com/prettier/eslint-config-prettier#installation)
* Рассмотрите использование Git hooks.
_Зачем:_
> Git hooks в разы увеличивают продуктивность разработчика. Добавляйте изменения, создавайте коммит и отправляйте (push) на тестовое или релизное окружение без страха, что сломается сборка. [узнать больше...](http://githooks.com/)
* Используйте Prettier с precommit hook.
_Зачем:_
> Хотя `prettier` сам по себе достаточно мощный инструмент, запускать его каждый раз как отдельную `npm` задачу, чтобы отформатировать код, не очень продуктивно. Здесь в игру вступает `lint-staged` и `husky`. Узнать больше о настройке `lint-staged` можно [здесь](https://github.com/okonet/lint-staged#configuration), а про настройку `husky` [здесь](https://github.com/typicode/husky).
<a name="logging"></a>
## 8. Логирование
![Логирование](/images/logging.png)
* Избегайте логов в консоли разработчика на клиенте в релизном окружении
_Совет:_
> Хотя в процессе сборки вы можете/должны удалять их, убедитесь, что ваш линтер оформления кода предупреждает вас об оставшихся логах консоли.
* Создавайте читабельные логи релизного окружения. В идеале, в релизном окружении используйте библиотеки для логирования. Например, [winston](https://github.com/winstonjs/winston) или
[node-bunyan](https://github.com/trentm/node-bunyan).
_Зачем:_
> Это сделает процесс поиска проблем более приятным: раскрашивание в разные цвета, метки времени, логирование в файл в дополнение к консоли или даже логирование в файлы, которые разбиваются по дням. [узнать больше...](https://blog.risingstack.com/node-js-logging-tutorial/)
<a name="api"></a>
## 9. API
<a name="api-design"></a>
![API](/images/api.png)
### 9.1 Дизайн API
_Зачем:_
> Чтобы разработчики создавали качественные RESTful интерфейсы, которые можно легко и консистентно использовать как членам команды, так и клиентам.
очему:_
> Отсутствие консистентности и простоты может в разы усложнить интеграцию и поддержку. Поэтому раздел `Дизайн API` включен в этот документ.
* В основном вы можете следовать ресурсо-ориентированному дизайну. Три основных фактора: ресурсы, коллекции и URLы.
* Ресурсы состоят из данных, могут быть вложены и имеют методы для работы с данными.
* Группы ресурсов называются коллекциями.
* URL идентифицирует онлайновое местоположение ресурса или коллекции.
очему:_
> Этот дизайн хорошо известен разработчикам (вашим главным потребителям API). Он не только читабельный и легкий в использовании, но еще и позволяет писать универсальные библиотеки и коннекторы, не зная, как будет выглядеть API.
* Для URL'ов используйте kebab-case.
* Для параметров в поисковой строке или полях ресурса используйте camelCase.
* Для имен ресурсов в URL'ах используйте kebab-case во множественном числе.
* Всегда используйте существительные во множественном числе для именования URL'ов, указывающих на коллекцию: `/users`.
очему:_
> Лучше читается и сохраняет консистентность URL'ов. [узнать больше...](https://apigee.com/about/blog/technology/restful-api-design-plural-nouns-and-concrete-names)
* В исходном коде замените множественное число на переменные и свойства с суффиксом `List`.
очему:_
> Использовать множественное число в URL'е удобно, а в исходном коде недостаточно прозрачно и может привести к ошибкам.
* Всегда используйте уникальное представление URL'а, которое начинается с коллекции и заканчивается идентификатором:
```
/students/245743
/airports/kjfk
```
* Не используйте URL'ы наподобие:
```
GET /blogs/:blogId/posts/:postId/summary
```
очему:_
> Этот URL указывает не на ресурс, а на свойство ресурса. Вы можете передать его как параметр запроса.
* Не используйте глаголы в URL'ах, указывающих на ресурсы.
очему:_
> Потому что, если использовать глаголы в каждой операции над ресурсом, в скором времени у вас получится огромный список URL'ов и не будет консистентного шаблона, что усложнит изучение API для разработчиков. К тому же глаголы используются для других целей.
* Используйте глаголы в URL'ах, не указывающих на ресурсы. В этом случае ваше API не возвращает ресурсы, оно запускает операцию и возвращает результат выполнения. Это **не** CRUD (create, retrieve, update и delete) операции:
```
/translate?text=Hallo
```
очему:_
> Потому что для CRUD используются HTTP методы с URL'ами `ресурса` или `коллекции`. Глаголы же на самом деле являются `Контроллерами`. Обычно их не так часто разрабатывают. [узнать больше...](https://byrondover.github.io/post/restful-api-guidelines/#controller)
* Если в теле запроса или ответа возвращается `JSON` объект, то именуйте свойства объекта в `camelCase`, чтобы поддерживать консистентность.
очему:_
> Это советы для JavaScript проекта, где подразумевается, что язык программирования для генерации и парсинга `JSON` - это JavaScript.
* Хотя ресурс и является уникальной сущностью, как экземпляр объекта или запись базы данных, вы не должны использовать `table_name` как имя ресурса и `column_name` как свойство ресурса.
очему:_
> Потому что вы намереваетесь показать Ресурс, а не схему таблицы из базы данных.
* И снова, при именовании ресурсов в URL'ах используйте только существительные, не указывайте в имени ресурса действие.
_Совет:_
> Используйте только существительные в URL'ах ресурса, избегайте подобных URL'ов: `/addNewUser` или `/updateUser`. Также не стоит посылать операцию над ресурсом как параметр запроса.
* Объяснение функциональных возможностей CRUD с использованием HTTP методов:
> `GET`: Получить представление ресурса.
> `POST`: Создать новые ресурсы или под-ресурсы.
> `PUT`: Обновить существующие ресурсы.
> `PATCH`: Обновить существующие ресурсы. Обновляет только переданные поля, остальные не трогает.
> `DELETE`: Удалить существующие ресурсы.
* Для вложенных ресурсов используйте связь между ними в URL'е. Например, используйте `id` для связи сотрудника с компанией.
очему:_
> Это естественный метод, чтобы добраться до ресурсов.
_Как:_
> `GET /schools/2/students`, должен получить список всех студентов из школы с `id` 2.
> `GET /schools/2/students/31`, должен получить данные о студенте с `id` 31, который учится в школе с `id` 2.
> `DELETE /schools/2/students/31`, должен удалить студента с `id` 31, который учится в школе с `id` 2.
> `PUT /schools/2/students/31` , должен обновить данные о студенте с `id` 31. Используйте `PUT` только на URL'е ресурса, а не коллекции.
> `POST /schools` , должен создать новую школу и вернуть данные по ней. Используйте `POST` на URL'е коллекции.
* Для версионности используйте обычный порядковый номер с префиксом `v` (v1, v2). Разместите его в начале URL'а, чтобы у него был самый широкий охват:
```
http://api.domain.com/v1/schools/3/students
```
_Зачем:_
> Когда ваше API публично и предназначено для третьих лиц, его обновление может вносить переломные изменения (breaking changes), которые могут привести к поломке существующих продуктов и сервисов, использующих ваше API. Использование версионности не позволит этому случиться. [узнать больше...](https://apigee.com/about/blog/technology/restful-api-design-tips-versioning)
* Ответное сообщение не должно требовать дополнительного описания. Например, корректное сообщение об ошибке может выглядеть вот так:
```json
{
"code": 1234,
"message" : "Something bad happened",
"description" : "More details"
}
```
или сообщение с ошибками валидации:
```json
{
"code" : 2314,
"message" : "Validation Failed",
"errors" : [
{
"code" : 1233,
"field" : "email",
"message" : "Invalid email"
},
{
"code" : 1234,
"field" : "password",
"message" : "No password provided"
}
]
}
```
очему:_
> В критические моменты разработчики надеются на качественно сформулированные ошибки, когда ищут проблему или решают вопросы после того, как приложение, использующее ваше API, попало в руки к пользователям.
_Замечание: Сообщения об ошибках безопасности должны быть как можно более обобщенными. Например, вместо того чтобы говорить `неверный пароль`, стоит отвечать `неверное имя пользователя или пароль`, чтобы мы, не осознавая того, не сообщали, что имя пользователя верное, а пароль нет._
* Используйте следующие коды статусов в вашем ответном сообщении, чтобы описать что **все нормально**, **клиентское приложение сделало что-то не так** или **API сломалось**.
_Коды статусов:_
> `200 OK` означает успешное выполнение `GET`, `PUT` или `POST` запросов.
> `201 Created` означает, что создан новый объект. Создание новых объектов, использую метод `POST`, возвращает `201` код статуса.
> `204 No Content` означает успешно обработанный запрос, но отправить обратно нечего. Используйте его, когда операция `DELETE` прошла успешно.
> `304 Not Modified` означает, что запрошенный ресурс уже есть в кэше у получателя и можно сэкономить на передаче данных.
> `400 Bad Request` для необработанных запросов, так как сервер не понимает, что именно запрашивает клиент.
> `401 Unauthorized` для запросов с невалидными учетными данными. При данном ответе надо сделать повторный запрос с валидными данными.
> `403 Forbidden` означает, что сервер понял запрос, но отказывается авторизовать его.
> `404 Not Found` означает, что запрошенный ресурс не найден.
> `500 Internal Server Error` означает, что запрос валидный, но сервер не смог его выполнить по каким-то непредвиденным причинам.
ояснение:_
> Большинство поставщиков API использует малую часть кодов статусов HTTP. Например, Google GData API использует только 10 кодов статусов, Netflix - 9, а Digg только 8. Конечно же, они передают дополнительную информацию в теле ответа. Существует свыше 70 кодов статусов. Однако, большинство разработчиков не помнят все 70 кодов. Поэтому, если вы выбираете код статуса, который не очень распространен, вы заставите разработчика переключиться с построения приложения на поиск в википедии, что же вы хотели ему сказать. [узнать больше...](https://apigee.com/about/blog/technology/restful-api-design-what-about-errors)
* Указывайте общее количество ресурсов в вашем ответе.
* Поддерживайте параметры запроса `limit` и `offset`.
* Количество данных, которое предоставляет ресурс, должно быть учтено. Потребитель вашего API не всегда нуждается в полном представлении ресурса. Используйте параметр запроса `fields`, который принимает на вход разделенный запятой список полей, необходимых для включения в ответ:
```
GET /student?fields=id,name,age,class
```
* Вам не обязательно поддерживать пагинацию, фильтрацию и сортировку с самого начала для всех ресурсов. Просто задокументируйте ресурсы, которые предоставляют эту возможность.
<a name="api-security"></a>
### 9.2 Безопасность API
Здесь представлены несколько основных лучших практик для безопасности:
* Не используйте базовую аутентификацию, если вы не работаете по защищенному соединению (HTTPS). Токены аутентификации не должны передаваться в URL'е: `GET /users/123?token=asdf....`
очему:_
> Потому что Токен или ID пользователя и пароль передаются по сети как простой текст, закодированный в base64, но base64 это обратимое кодирование. Схема базовой аутентификации не безопасна. [узнать больше...](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication)
* Токены должны передаваться с использованием заголовка `Authorization` при каждом запросе: `Authorization: Bearer xxxxxx, Extra yyyyy`.
* Жизненный цикл `Authorization Code` должен быть кратковременным.
* Отклоняйте все запросы, переданные через незащищенный протокол (non-TLS requests), чтобы избежать передачи данных небезопасным путем. Отвечайте на подобные HTTP запросы статусом `403 Forbidden`.
* Задумайтесь над использованием ограничения запросов (Rate Limiting).
_Зачем:_
> Чтобы защитить API от угроз ботов, которые вызывают его тысячи раз в час. Вы должны задуматься над реализацией ограничения количества запросов на ранних этапах построения приложения.
* Правильно сконфигурированные HTTP заголовки помогут вам обезопасить ваше web-приложение. [узнать больше...](https://github.com/helmetjs/helmet)
* Ваше API должно преобразовывать данные, получаемые в запросе, в их каноничное представление или, если это невозможно, отклонять запрос. Вернуть статус `400 Bad Request` с детальной информацией об ошибках с некорректными или отсутствующими данными.
* Весь обмен данными с REST API должен валидироваться самой API.
* Сериализуйте ваш JSON.
_Зачем:_
> Ключевая цель JSON сериализаторов - это предотвращение удаленного выполнения произвольного JavaScript кода в браузере... или, если вы используйте Node.js, на сервере. Поэтому жизненно необходимо иметь правильный JSON сериализатор, чтобы безопасно кодировать данные для предотвращения выполнения предоставленного пользователем кода в браузере.
* Валидируйте заголовок `Content-Type` и используйте, в основном, с `application/*json` значением.
_Зачем:_
> Например, если разрешить MIME-тип `application/x-www-form-urlencoded`, то злоумышленник сможет создать форму и вызвать простой `POST` запрос. Сервер никогда не должен предполагать `Content-Type`. Отсутствие заголовка `Content-Type` или его неожиданное значение должно служить причиной для сервера отклонить запрос со статусом `4XX`.
* Вы можете использовать чек-лист для проверки безопасности API. [например](https://github.com/shieldfy/API-Security-Checklist)
<a name="api-documentation"></a>
### 9.3 Документация API
* Заполните раздел `API Reference` в шаблоне [README.md](./README.sample.md) для API.
* Опишите методы аутентификации API с примерами кода.
* Опишите структуру URL'ов (только путь, без корневого URL), включая тип запроса (метод HTTP).
По каждому URL'у разъясните:
* Параметры URL'а, если они есть, укажите их в соответствии с именами, указанными в разделе URL:
```
Required: id=[integer]
Optional: photo_id=[alphanumeric]
```
* Если метод запроса `POST`, приведите рабочие примеры. Правило для параметров URL'а здесь тоже работает. Разбейте раздел на Необязательные и Обязательные данные.
* Если ответ успешный, укажите какой должен быть код статуса и вернутся ли какие-нибудь данные. Это будет полезно для людей, которые хотят знать какие данные ожидать в ответе.
```
Code: 200
Content: { id : 12 }
```
* Если ответ неуспешный. Большинство запросов имеет множество вариантов неуспешно завершиться. Начиная от неавторизованного доступа до неправильных параметров и т.д. Все эти варианты должны быть задокументированы. При документировании вы будете повторяться, но это поможет предотвратить додумывание со стороны потребителя API. Например:
```json
{
"code": 403,
"message" : "Authentication failed",
"description" : "Invalid username or password"
}
```
* Используйте готовые решения для дизайна API. Существует множество инструментов с открытым исходным кодом для документирования API. Например, [API Blueprint](https://apiblueprint.org/) и [Swagger](https://swagger.io/).
<a name="licensing"></a>
## 10. Лицензирование
![Лицензирование](/images/licensing.png)
Убедитесь, что у вас есть право на ресурсы, которые вы используете. Если вы используете библиотеки, не забудьте проверить, что они имеют лицензию MIT, Apache или BSD. Если вы их модифицируете, проверьте детали лицензии на разрешение. Использование изображений и видео материалов, защищенных авторским правом, может повлечь проблемы с законом.
---
Источники:
[RisingStack Engineering](https://blog.risingstack.com/),
[Mozilla Developer Network](https://developer.mozilla.org/),
[Heroku Dev Center](https://devcenter.heroku.com),
[Airbnb/javascript](https://github.com/airbnb/javascript),
[Atlassian Git tutorials](https://www.atlassian.com/git/tutorials),
[Apigee](https://apigee.com/about/blog),
[Wishtack](https://blog.wishtack.com)
Иконки от [icons8](https://icons8.com/)

781
README-zh.md Normal file
View File

@ -0,0 +1,781 @@
[ENGLISH](./README.md) |
[日本語版](./README-ja.md) |
[한국어](./REAMDE-ko.md) |
[РУССКИЙ](./README-ru.md) |
[Português](./README-pt-BR.md)
[<img src="./images/elsewhen-logo.png" width="180" height="180">](https://www.elsewhen.com/)
# 项目规范 &middot; [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
JavaScript工程项目的一系列最佳实践策略
> 当您在青葱的田野里翻滚一般欢乐(而不受约束)地开发一个新项目,对其他人而言维护这样一个项目简直就是一个潜在的可怕的噩梦。以下列出的指南是我们在[elsewhen](https://www.elsewhen.com)的大多数JavaScript项目中发现撰写和收集的最佳实践至少我们是这样认为的。如果您想分享其他最佳实践或者认为其中一些指南应该删除。[欢迎随时与我们分享](http://makeapullrequest.com)。
- [Git](#git)
- [一些git规则](#some-git-rules)
- [Git工作流](#git-workflow)
- [编写良好的提交备注信息](#writing-good-commit-messages)
- [文档](#documentation)
- [环境](#environments)
- [一致的开发环境](#consistent-dev-environments)
- [一致性的依赖配置](#consistent-dependencies)
- [依赖](#dependencies)
- [测试](#testing)
- [结构与命名规则](#structure-and-naming)
- [代码风格](#code-style)
- [一些代码风格指南](#code-style-check)
- [强制性的代码风格规范](#enforcing-code-style-standards)
- [日志](#logging)
- [API](#api)
- [API 设计](#api-design)
- [API 安全](#api-security)
- [API 文档](#api-documentation)
- [许可](#licensing)
<a name="git"></a>
## 1. Git
<a name="some-git-rules"></a>
![git](/images/branching.png)
### 1.1 一些Git规则
这里有一套规则要牢记:
* 在功能分支中执行开发工作。
_为什么_
> 因为这样,所有的工作都是在专用的分支而不是在主分支上隔离完成的。它允许您提交多个 pull request 而不会导致混乱。您可以持续迭代提交,而不会使得那些很可能还不稳定而且还未完成的代码污染 master 分支。[更多请阅读...](https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow)
* 从 `develop` 独立出分支。
_为什么_
> 这样,您可以保持 `master` 分支中的代码稳定性,这样就不会导致构建问题,并且几乎可以直接用于发布(当然,这可能对某些项目来说要求会比较高)。
* 永远也不要将分支(直接)推送到 `develop` 或者 `master` 请使用合并请求Pull Request
_为什么_
> 通过这种方式,它可以通知整个团队他们已经完成了某个功能的开发。这样开发伙伴就可以更容易对代码进行 code review同时还可以互相讨论所提交的需求功能。
* 在推送所开发的功能并且发起合并请求前,请更新您本地的`develop`分支并且完成交互式变基操作interactive rebase
_为什么_
> rebase 操作会将(本地开发分支)合并到被请求合并的分支( `master``develop` )中,并将您本地进行的提交应用于所有历史提交的最顶端,而不会去创建额外的合并提交(假设没有冲突的话),从而可以保持一个漂亮而干净的历史提交记录。 [更多请阅读 ...](https://www.atlassian.com/git/tutorials/merging-vs-rebasing)
* 请确保在变基并发起合并请求之前解决完潜在的冲突。
* 合并分支后删除本地和远程功能分支。
_为什么_
> 如果不删除需求分支,大量僵尸分支的存在会导致分支列表的混乱。而且该操作还能确保有且仅有一次合并到`master` 或 `develop`。只有当这个功能还在开发中时对应的功能分支才存在。
* 在进行合并请求之前,请确保您的功能分支可以成功构建,并已经通过了所有的测试(包括代码规则检查)。
_为什么_
> 因为您即将将代码提交到这个稳定的分支。而如果您的功能分支测试未通过,那您的目标分支的构建有很大的概率也会失败。此外,确保在进行合并请求之前应用代码规则检查。因为它有助于我们代码的可读性,并减少格式化的代码与实际业务代码更改混合在一起导致的混乱问题。
* 使用 [这个](./.gitignore) `.gitignore` 文件。
_为什么_
> 此文件已经囊括了不应该和您开发的代码一起推送至远程仓库remote repository的系统文件列表。另外此文件还排除了大多数编辑器的设置文件夹和文件以及最常见的工程开发依赖目录。
* 保护您的 `develop``master` 分支。
_为什么_
> 这样可以保护您的生产分支免受意外情况和不可回退的变更。 更多请阅读... [Github](https://help.github.com/articles/about-protected-branches/) 以及 [Bitbucket](https://confluence.atlassian.com/bitbucketserver/using-branch-permissions-776639807.html)
<a name="git-workflow"></a>
### 1.2 Git 工作流
基于以上原因, 我们将 [功能分支工作流](https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow)  [交互式变基的使用方法](https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing) 结合一些 [Gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows#gitflow-workflow)中的基础 (比如命名和使用一个develop branch)一起使用。 主要步骤如下:
* 针对一个新项目, 在您的项目目录初始化您的项目。 __如果是已有项目随后的功能开发/代码变动这一步请忽略__
```sh
cd <项目目录>
git init
```
* 检出Checkout 一个新的功能或故障修复feature/bug-fix分支。
```sh
git checkout -b <分支名称>
```
* 新增代码变更。
```sh
git add
git commit -a
```
_为什么_
> `git commit -a` 会独立启动一个编辑器用来编辑您的说明信息,这样的好处是可以专注于写这些注释说明。更多请阅读 *章节 1.3*
* 保持与远程develop分支的同步以便使得本地 develop 分支)拿到最新变更。
```sh
git checkout develop
git pull
```
_为什么_
> 当您进行(稍后)变基操作的时候,保持更新会给您一个在您的机器上解决冲突的机会。这比(不同步更新就进行下一步的变基操作并且)发起一个与远程仓库冲突的合并请求要好。
* 切换至功能分支并且通过交互式变基从您的develop分支中获取最新的代码提交以更新您的功能分支。
```sh
git checkout <branchname>
git rebase -i --autosquash develop
```
_为什么_
> 您可以使用 `--autosquash` 将所有提交压缩到单个提交。没有人会愿意(看到) `develop` 分支中的单个功能开发就占据如此多的提交历史。 [更多请阅读...](https://robots.thoughtbot.com/autosquashing-git-commits)
* 如果没有冲突请跳过此步骤,如果您有冲突, 就需要[解决它们](https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/)并且继续变基操作。
```sh
git add <file1> <file2> ...
git rebase --continue
```
* 推送您的(功能)分支。变基操作会改变提交历史, 所以您必须使用 `-f` 强制推送到远程(功能)分支。 如果其他人与您在该分支上进行协同开发,请使用破坏性没那么强的 `--force-with-lease` 参数。
```sh
git push -f
```
_为什么:_
> 当您进行 rebase 操作时,您会改变功能分支的提交历史。这会导致 Git 拒绝正常的 `git push` 。那么,您只能使用 `-f``--force` 参数了。[更多请阅读...](https://developer.atlassian.com/blog/2015/04/force-with-lease/)
* 提交一个合并请求Pull Request
* Pull Request 会被负责代码审查的同事接受,合并和关闭。
* 如果您完成了开发,请记得删除您的本地分支。
```sh
git branch -d <分支>
```
(使用以下代码)删除所有已经不在远程仓库维护的分支。
``` sh
git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done
```
<a name="writing-good-commit-messages"></a>
### 1.3 如何写好 Commit Message
坚持遵循关于提交的标准指南,会让在与他人合作使用 Git 时更容易。这里有一些经验法则 ([来源](https://chris.beams.io/posts/git-commit/#seven-rules)):
* 用新的空行将标题和主体两者隔开。
_为什么_
> Git 非常聪明,它可将您提交消息的第一行识别为摘要。实际上,如果您尝试使用 `git shortlog` ,而不是 `git log` ,您会看到一个很长的提交消息列表,只会包含提交的 id 以及摘要(,而不会包含主体部分)。
* 将标题行限制为50个字符并将主体中一行超过72个字符的部分折行显示。
_为什么_
> 提交应尽可能简洁明了,而不是写一堆冗余的描述。 [更多请阅读...](https://medium.com/@preslavrachev/what-s-with-the-50-72-rule-8a906f61f09c)
* 标题首字母大写。
* 不要用句号结束标题。
* 在标题中使用 [祈使句](https://en.wikipedia.org/wiki/Imperative_mood) 。
_为什么_
> 与其在写下的信息中描述提交者做了什么,不如将这些描述信息作为在这些提交被应用于该仓库后将要完成的操作的一个说明。[更多请阅读...](https://news.ycombinator.com/item?id=2079612)
* 使用主体部分去解释 **是什么** 和 **为什么** 而不是 **怎么做**
<a name="文档"></a>
## 2. 文档
![文档](/images/documentation.png)
* 可以使用这个 [模板](./README.sample.md) 作为 `README.md` (的一个参考), 随时欢迎添加里面没有的内容。
* 对于具有多个存储库的项目,请在各自的 `README.md` 文件中提供它们的链接。
* 随项目的进展,持续地更新 `README.md`
* 给您的代码添加详细的注释,这样就可以清楚每个主要部分的含义。
* 如果您正在使用的某些代码和方法在github或stackoverflow上已经有公开讨论请在您的注释中包含这些链接
* 不要把注释作为坏代码的借口。保持您的代码干净整洁。
* 也不要把那些清晰的代码作为不写注释的借口。
* 当代码更新,也请确保注释的同步更新。
<a name="environments"></a>
## 3. 环境
![环境](/images/laptop.png)
* 如果需要,请分别定义 `development`, `test``production` 三个环境。
_为什么_
> 不同的环境可能需要不同的数据、token、API、端口等。您可能需要一个隔离的 `development` 环境,它调用 mock 的 APImock 会返回可预测的数据,使自动和手动测试变得更加容易。或者您可能只想在 `production` 环境中才启用 Google Analytics分析。 [更多请阅读...](https://stackoverflow.com/questions/8332333/node-js-setting-up-environment-specific-configs-to-be-used-with-everyauth)
* 依据不同的环境变量加载部署的相关配置,不要将这些配置作为常量添加到代码库中, [看这个例子](./config.sample.js).
_为什么_
> 您会有令牌,密码和其他有价值的信息。这些配置应正确地从应用程序内部分离开来,这样代码库就可以随时独立发布,不会包含这些敏感配置信息。
> _怎么做_
> 使用 `.env` 文件来存储环境变量,并将其添加到 `.gitignore` 中使得排除而不被提交(到仓库)。另外,再提交一个 `.env.example` 作为开发人员的参考配置。对于生产环境,您应该依旧以标准化的方式设置环境变量。
> [更多请阅读](https://medium.com/@rafaelvidaurre/managing-environment-variables-in-node-js-2cb45a55195f)
* 建议您在应用程序启动之前校验一下环境变量。  [看这个例子](./configWithTest.sample.js) ,它使用了 `joi` 去校验提供的值。
_为什么_
> 它可能会将其他人从上小时的故障排查中解救。
<a name="consistent-dev-environments"></a>
### 3.1 一致的开发环境:
* 在 `package.json` 里的 `engines` 中设置您的node版本。
_为什么_
> 让其他人可以清晰的知道这个项目中用的什么node版本。 [更多请阅读...](https://docs.npmjs.com/files/package.json#engines)
* 另外,使用 `nvm` 并在您的项目根目录下创建一个 `.nvmrc` 文件。不要忘了在文档中标注。
_为什么_
> 任何使用`nvm`的人都可以使用 `nvm use` 来切换到合适的node版本。 [更多请阅读...](https://github.com/creationix/nvm)
* 最好设置一个检查 node 和 npm 版本的 `preinstall` 脚本。
_为什么_
> 某些依赖项可能会在新版本的 npm 中安装失败。
* 如果可以的话最好使用 Docker 镜像。
_为什么_
> 它可以在整个工作流程中为您提供一致的环境,而且不用花太多的时间来解决依赖或配置。 [更多请阅读...](https://hackernoon.com/how-to-dockerize-a-node-js-application-4fbab45a0c19)
* 使用本地模块,而不是使用全局安装的模块。
_为什么_
> 您不能指望您的同事在自己的全局环境都安装了相应的模块,本地模块可以方便您分享您的工具。
<a name="consistent-dependencies"></a>
### 3.2 依赖一致性:
* 确保您的团队成员获得与您完全相同的依赖。
_为什么_
> 因为您希望代码在任何开发环境中运行都能像预期的一样。 [更多请阅读...](https://medium.com/@kentcdodds/why-semver-ranges-are-literally-the-worst-817cdcb09277)
_怎么做_
> 在`npm@5`或者更高版本中使用 `package-lock.json`
_我们没有 npm@5_
> 或者,您可以使用 `yarn` ,并确保在 `README.md` 中标注了使用 `yarn` 。您的锁文件和`package.json`在每次依赖关系更新后应该具有相同的版本。[更多请阅读...](https://yarnpkg.com/en/)
_我不太喜欢 `Yarn` _
> 居然不喜欢 Yarn太糟糕了。对于旧版本的`npm`,在安装新的依赖关系时使用 `-save --save-exact` ,并在发布之前创建` npm-shrinkwrap.json` 。 [更多请阅读...](https://docs.npmjs.com/files/package-locks)
<a name="dependencies"></a>
## 4. 依赖
![依赖](/images/modules.png)
* 持续跟踪您当前的可用依赖包: 举个例子, `npm ls --depth=0`。[更多请阅读...](https://docs.npmjs.com/cli/ls)
* 查看这些软件包是否未使用或者与开发项目无关: `depcheck`。 [更多请阅读...](https://www.npmjs.com/package/depcheck)
_为什么_
> 您可能会在代码中包含未使用的库,这会增大生产包的大小。请搜索出这些未使用的依赖关系并去掉它们吧。
* 在使用依赖之前,请检查他的下载统计信息,看看它是否被社区大量使用: `npm-stat`. [更多请阅读...](https://npm-stat.com/)
_为什么_
> 更多的使用量很大程度上意味着更多的贡献者,这通常意味着拥有更好的维护,这些能确保错误能够被快速地发现并修复。
* 在使用依赖之前,请检查它是否具有良好而成熟的版本发布频率与大量的维护者:例如, `npm view async`。[更多请阅读...](https://docs.npmjs.com/cli/view)
_为什么_
> 如果维护者没有足够快地合并修补程序,那么这些贡献者也将会变得不积极不高效。
* 如果需要使用那些不太熟悉的依赖包,请在使用之前与团队进行充分讨论。
* 始终确保您的应用程序在最新版本的依赖包上面能正常运行,而不是无法使用:`npm outdated`。 [更多请阅读...](https://docs.npmjs.com/cli/outdated)
_为什么_
> 依赖关系更新有时包含破坏性更改。当显示需要更新时,请始终先查看其发行说明。并逐一地更新您的依赖项,如果出现任何问题,可以使故障排除更容易。可以使用类似 [npm-check-updates](https://github.com/tjunnone/npm-check-updates) 的酷炫工具(来解决这个问题)。
* 检查包是否有已知的安全漏洞,例如: [Snyk](https://snyk.io/test?utm_source=risingstack_blog)。
<a name="testing"></a>
## 5. 测试
![测试](/images/testing.png)
* 如果需要,请构建一个 `test` 环境.
_为什么_
> 虽然有时在 `production` 模式下端到端测试可能看起来已经足够了但有一些例外比如您可能不想在生产环境下启用数据分析功能只能用测试数据来填充污染某人的仪表板。另一个例子是您的API可能在 `production` 中才具有速率限制,并在请求达到一定量级后会阻止您的测试请求。
* 将测试文件放在使用 `* .test.js``* .spec.js` 命名约定的测试模块,比如 `moduleName.spec.js`
_为什么_
> 您肯定不想进入一个层次很深的文件夹结构来查找里面的单元测试。[更多请阅读...](https://hackernoon.com/structure-your-javascript-code-for-testability-9bc93d9c72dc)
* 将其他测试文件放入独立的测试文件夹中以避免混淆。
_为什么_
> 一些测试文件与任何特定的文件实现没有特别的关系。您只需将它放在最有可能被其他开发人员找到的文件夹中:`__test__` 文件夹。这个名字:`__test__`也是现在的标准被大多数JavaScript测试框架所接受。
* 编写可测试代码避免副作用side effects提取副作用编写纯函数。
_为什么_
> 您想要将业务逻辑拆分为单独的测试单元。您必须“尽量减少不可预测性和非确定性过程对代码可靠性的影响”。 [更多请阅读...](https://medium.com/javascript-scene/tdd-the-rite-way-53c9b46f45e3)
> 纯函数是一种总是为相同的输入返回相同输出的函数。相反地,不纯的函数是一种可能会有副作用,或者取决于来自外部的条件来决定产生对应的输出值的函数。这使得它不那么可预测。[更多请阅读...](https://hackernoon.com/structure-your-javascript-code-for-testability-9bc93d9c72dc)
* 使用静态类型检查器
_为什么_
> 有时您可能需要一个静态类型检查器。它为您的代码带来一定程度的可靠性。[更多请阅读...](https://medium.freecodecamp.org/why-use-static-types-in-javascript-part-1-8382da1e0adb)
* 先在本地 `develop` 分支运行测试待测试通过后再进行pull请求。
_为什么_
> 您不想成为一个导致生产分支构建失败的人吧。在您的`rebase`之后运行测试,然后再将您改动的功能分支推送到远程仓库。
* 记录您的测试,包括在 `README.md` 文件中的相关说明部分。
_为什么_
> 这是您为其他开发者或者 DevOps 专家或者 QA 或者其他如此幸运能和您一起协作的人留下的便捷笔记。
<a name="structure-and-naming"></a>
## 6. 结构布局与命名
![结构布局与命名](/images/folder-tree.png)
* 请围绕产品功能/页面/组件,而不是围绕角色来组织文件。此外,请将测试文件放在他们对应实现的旁边。
**不规范**
```
.
├── controllers
| ├── product.js
| └── user.js
├── models
| ├── product.js
| └── user.js
```
**规范**
```
.
├── product
| ├── index.js
| ├── product.js
| └── product.test.js
├── user
| ├── index.js
| ├── user.js
| └── user.test.js
```
_为什么_
> 比起一个冗长的列表文件,创建一个单一责权封装的小模块,并在其中包括测试文件。将会更容易浏览,更一目了然。
* 将其他测试文件放在单独的测试文件夹中以避免混淆。
_为什么_
> 这样可以节约您的团队中的其他开发人员或DevOps专家的时间。
* 使用 `./config` 文件夹,不要为不同的环境制作不同的配置文件。
_为什么_
> 当您为不同的目的数据库API等分解不同的配置文件;将它们放在具有容易识别名称(如 `config` )的文件夹中才是有意义的。请记住不要为不同的环境制作不同的配置文件。这样并不是具有扩展性的做法,如果这样,就会导致随着更多应用程序部署被创建出来,新的环境名称也会不断被创建,非常混乱。
> 配置文件中使用的值应通过环境变量提供。 [更多请阅读...](https://medium.com/@fedorHK/no-config-b3f1171eecd5)
* 将脚本文件放在`./scripts`文件夹中。包括 `bash` 脚本和 `node` 脚本。
_为什么_
> 很可能最终会出现很多脚本文件比如生产构建开发构建数据库feeders数据库同步等。
* 将构建输出结果放在`./build`文件夹中。将`build/`添加到`.gitignore`中以便忽略此文件夹。
_为什么_
> 命名为您最喜欢的就行,`dist`看起来也蛮酷的。但请确保与您的团队保持一致性。放置在该文件夹下的东西应该是已经生成(打包、编译、转换)或者被移到这里的。您产生什么编译结果,您的队友也可以生成同样的结果,所以没有必要将这些结果提交到远程仓库中。除非您故意希望提交上去。
* 文件名和目录名请使用 `PascalCase` `camelCase` 风格。组件请使用 `PascalCase` 风格。
* `CheckBox/index.js` 应该代表 `CheckBox` 组件,也可以写成 `CheckBox.js` ,但是**不能**写成冗长的 `CheckBox/CheckBox.js``checkbox/CheckBox.js`
* 理想情况下,目录名称应该和 `index.js` 的默认导出名称相匹配。
_为什么_
> 这样您就可以通过简单地导入其父文件夹直接使用您预期的组件或模块。
<a name="code-style"></a>
## 7. 代码风格
![代码风格](/images/code-style.png)
<a name="code-style-check"></a>
### 7.1 若干个代码风格指导
* 对新项目请使用 Stage2 和更高版本的 JavaScript现代化语法。对于老项目保持与老的语法一致除非您打算把老的项目也更新为现代化风格。
_为什么_
> 这完全取决于您的选择。我们使用转换器来使用新的语法糖。Stage2更有可能最终成为规范的一部分而且仅仅只需经过小版本的迭代就会成为规范。
* 在构建过程中包含代码风格检查。
_为什么_
> 在构建时中断下一步操作是一种强制执行代码风格检查的方法。强制您认真对待代码。请确保在客户端和服务器端代码都执行代码检查。 [更多请阅读...](https://www.robinwieruch.de/react-eslint-webpack-babel/)
* 使用 [ESLint - Pluggable JavaScript linter](http://eslint.org/) 去强制执行代码检查。
_为什么_
> 我们个人很喜欢 `eslint` ,不强制您也喜欢。它拥有支持更多的规则,配置规则的能力和添加自定义规则的能力。
* 针对 JavaScript 我们使用[Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript) , [更多请阅读](https://www.gitbook.com/book/duk/airbnb-javascript-guidelines/details)。 请依据您的项目和您的团队选择使用所需的JavaScript 代码风格。
* 当使用[FlowType](https://flow.org/)的时候,我们使用 [ESLint的Flow样式检查规则。](https://github.com/gajus/eslint-plugin-flowtype)。
_为什么_
> Flow 引入了很少的语法,而这些语法仍然需要遵循代码风格并进行检查。
* 使用 `.eslintignore` 将某些文件或文件夹从代码风格检查中排除。
_为什么_
> 当您需要从风格检查中排除几个文件时,就再也不需要通过 `eslint-disable` 注释来污染您的代码了。
* 在Pull Request之前请删除任何 `eslint` 的禁用注释。
_为什么_
> 在处理代码块时禁用风格检查是正常现象,这样就可以关注在业务逻辑。请记住把那些 `eslint-disable` 注释删除并遵循风格规则。
* 根据任务的大小使用 `//TODO` 注释或做一个标签ticket
_为什么_
> 这样您就可以提醒自己和他人有这样一个小的任务需要处理如重构一个函数或更新一个注释。对于较大的任务可以使用由一个lint规则`no-warning-comments`)强制要求其完成(并移除注释)的`//TODO3456`,其中的`#3456`号码是一个标签ticket方便查找且防止相似的注释堆积导致混乱。
* 随着代码的变化,始终保持注释的相关性。删除那些注释掉的代码块。
_为什么_
> 代码应该尽可能的可读,您应该摆脱任何分心的事情。如果您在重构一个函数,就不要注释那些旧代码,直接把要注释的代码删除吧。
* 避免不相关的和搞笑的的注释,日志或命名。
_为什么_
> 虽然您的构建过程中可能(应该)移除它们,但有可能您的源代码会被移交给另一个公司/客户,您的这些笑话应该无法逗乐您的客户。
* 请使用有意义容易搜索的命名,避免缩写名称。对于函数使用长描述性命名。功能命名应该是一个动词或动词短语,需要能清楚传达意图的命名。
_为什么_
> 它使读取源代码变得更加自然。
* 依据《代码整洁之道》的step-down规则对您的源代码文件中的函数的声明进行组织。高抽象级别的函数调用了低级别函数的函数在上低抽象级别函数在下保证了阅读代码时遇到未出现的函数仍然是从上往下的顺序而不会打断阅读顺序地往前查找并且函数的抽象层次依次递减
_为什么_
> 它使源代码的可读性更好。
<a name="enforcing-code-style-standards"></a>
### 7.2 强制的代码风格标准
* 让您的编辑器提示您关于代码风格方面的错误。 请将 [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) 与 [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) 和您目前的ESLint配置一起搭配使用。 [更多请阅读...](https://github.com/prettier/eslint-config-prettier#installation)
* 考虑使用Git钩子。
_为什么_
> Git的钩子能大幅度地提升开发者的生产力。在做出改变、提交、推送至暂存区或者生产环境的过程中充分检验代码再也不需要担心推送的代码会导致构建失败。 [更多请阅读...](http://githooks.com/)
* 将Git的precommit钩子与Prettier结合使用。
_为什么_
> 虽然`prettier`自身已经非常强大但是每次将其作为单独的一个npm任务去格式化代码并不是那么地高效。 这正是`lint-staged`(还有`husky`)可以解决的地方。关于如何配置 `lint-staged` 请阅读[这里](https://github.com/okonet/lint-staged#configuration) 以及如何配置 `husky` 请阅读[这里](https://github.com/typicode/husky)。
<a name="logging"></a>
## 8. 日志
![日志](/images/logging.png)
* 避免在生产环境中使用客户端的控制台日志。
_为什么_
> 您在构建过程可以把(应该)它们去掉,但是请确保您在代码风格检查中提供了有关控制台日志的警告信息。
* 产出生产环境的可读生产日志记录。一般使用在生产模式下所使用的日志记录库 (比如 [winston](https://github.com/winstonjs/winston) 或者
[node-bunyan](https://github.com/trentm/node-bunyan))。
_为什么_
> 它通过添加着色、时间戳、log到控制台或者文件中甚至是夜以继日地轮流log到文件来减少故障排除中那些令人不愉快的事情。[更多请阅读...](https://blog.risingstack.com/node-js-logging-tutorial/)
<a name="api"></a>
## 9. API
![API](/images/api.png)
<a name="api-design"></a>
### 9.1 API 设计
_为什么_
> 因为我们试图实施开发出结构稳健的 Restful 接口,让团队成员和客户可以简单而一致地使用它们。
_为什么_
> 缺乏一致性和简单性会大大增加集成和维护的成本。这就是为什么`API设计`这部分会包含在这个文档中的原因
* 我们主要遵循资源导向的设计方式。它有三个主要要素:资源,集合和 URLs。
* 资源具有数据,嵌套,和一些操作方法。
* 一组资源称为一个集合。
* URL标识资源或集合的线上位置。
_为什么_
> 这是针对开发人员您的主要API使用者非常著名的设计方式。除了可读性和易用性之外它还允许我们在无需了解API细节的情况下编写通用库和一些连接器。
* 使用`kebab-case`短横线分割的URL。
* 在查询字符串或资源字段中使用`camelCase`模式。
* 在URL中使用多个`kebab-case`作为资源名称。
* 总是使用复数名词来命名指向一个集合的url`/users`.
_为什么_
> 基本上它可读性会更好并可以保持URL的一致性。 [更多请阅读...](https://apigee.com/about/blog/technology/restful-api-design-plural-nouns-and-concrete-names)
* 在源代码中,将复数转换为具有列表后缀名描述的变量和属性。
_为什么_
> 复数形式的URL非常好但在源代码中使用它却很微妙而且容易出错所以要小心谨慎。
* 坚持这样一个概念:始终以集合名起始并以标识符结束。
```
/students/245743
/airports/kjfk
```
* 避免这样的网址:
```
GET /blogs/:blogId/posts/:postId/summary
```
_为什么_
> 这不是在指向资源,而是在指向属性。您完全可以将属性作为参数传递,以减少响应。
* URLs里面请尽量少用动词
_为什么_
> 因为如果您为每个资源操作使用一个动词您很快就会维护一个很大的URL列表而且没有一致的使用模式这会使开发人员难以学习。此外我们还要使用动词做别的事情。
* 为非资源型请求使用动词。在这种情况下您的API并不需要返回任何资源。而是去执行一个操作并返回执行结果。这些**不是** CRUD创建查询更新和删除操作
```
/translate?text=Hallo
```
_为什么_
> 因为对于 CRUD我们在`资源``集合`URL上使用 HTTP 自己带的方法。我们所说的动词实际上是指`Controllers`。您通常不会开发这些东西。[更多请阅读...](https://github.com/byrondover/api-guidelines/blob/master/Guidelines.md#controller)
* 请求体或响应类型如果是JSON那么请遵循`camelCase`规范为`JSON`属性命名来保持一致性。
_为什么_
> 这是一个 JavaScript 项目指南其中用于生成JSON的编程语言以及用于解析JSON的编程语言被假定为 JavaScript。
* 即使资源类似于对象实例或数据库记录这样的单一概念,您也不应该将`table_name`用作资源名称或将`column_name`作为资源属性。
_为什么_
> 因为您的目的是分析资源,而不是分析数据库模式。
* 再次只有在您的URL上面命名资源时才使用名词不要尝试解释其功能。
_为什么_
> 只能在资源URL中使用名词避免像`/addNewUser``/updateUser`这样的结束点。也避免使用参数作为发送资源的操作。
* 如何使用HTTP方法来操作CRUD功能
_怎么做_
> `GET`: 查询资源的表示法
> `POST`: 创建一些新的资源或者子资源
> `PUT`: 更新一个存在的资源
> `PATCH`: 更新现有资源。它只更新所提供的字段,不管其他字段
> `DELETE`: 删除一个存在的资源
* 对于嵌套资源请在URL中把他们的关系表现出来。例如使用`id`将员工与公司联系起来。
_为什么_
> 这是一种自然的方式,方便资源的认知。
_怎么做_
> `GET /schools/2/students ` , 应该从学校2得到所有学生的名单
> `GET /schools/2/students/31` , 应该得到学生31的详细信息且此学生属于学校2
> `DELETE /schools/2/students/31` , 应删除属于学校2的学生31
> `PUT /schools/2/students/31` , 应该更新学生31的信息仅在资源URL上使用PUT方式而不要用收集
> `POST /schools` , 应该创建一所新学校并返回创建的新学校的细节。在集合URL上使用POST
* 对于具有`v`前缀v1v2的版本使用简单的序数。并将其移到URL的左侧使其具有最高的范围表述
```
http://api.domain.com/v1/schools/3/students
```
_为什么_
> 当您的 API 为第三方公开时升级API会导致发生一些意料之外的影响也可能导致使用您API的人无法使用您的服务和产品。而这时使用URL中版本化可以防止这种情况的发生。 [更多请阅读...](https://apigee.com/about/blog/technology/restful-api-design-tips-versioning)
* 响应消息必须是自我描述的。一个很好的错误消息响应可能如下所示:
```json
{
"code": 1234,
"message" : "Something bad happened",
"description" : "More details"
}
```
或验证错误:
```json
{
"code" : 2314,
"message" : "Validation Failed",
"errors" : [
{
"code" : 1233,
"field" : "email",
"message" : "Invalid email"
},
{
"code" : 1234,
"field" : "password",
"message" : "No password provided"
}
]
}
```
_为什么_
> 开发人员在使用这些由API构建的应用程序时难免会需要在故障排除和解决问题的关键时刻使用到这些精心设计的错误消息。好的错误消息设计能节约大量的问题排查时间。
_注意尽可能保持安全异常消息的通用性。例如别说`不正确的密码`,您可以换成`无效的用户名或密码`,以免我们不知不觉地通知用户他的用户名确实是正确的,只有密码不正确。这会让用户很懵逼。
* 只使用这8个状态代码并配合您自定义的响应描述来表述程序工作**一切是否正常****客户端应用程序发生了什么错误**或**API发生错误**。
_选谁呢_
> `200 OK` `GET`, `PUT``POST` 请求响应成功.
> `201 Created` 标识一个新实例创建成功。当创建一个新的实例,请使用`POST`方法并返回`201`状态码。
> `304 Not Modified` 发现资源已经缓存在本地,浏览器会自动减少请求次数。
> `400 Bad Request` 请求未被处理,因为服务器不能理解客户端是要什么。
> `401 Unauthorized` 因为请求缺少有效的凭据,应该使用所需的凭据重新发起请求。
> `403 Forbidden` 意味着服务器理解本次请求,但拒绝授权。
> `404 Not Found` 表示未找到请求的资源。
> `500 Internal Server Error` 表示请求本身是有效,但由于某些意外情况,服务器无法实现,服务器发生了故障。
_为什么_
> 大多数 API 提供程序仅仅只使用一小部分 HTTP 状态代码而已。例如Google GData API 仅使用了10个状态代码Netflix 使用了9个而 Digg 只使用了8个。当然这些响应作为响应主体的附加信息。一共有超过 70 个 HTTP 状态代码。然而,大多数开发者不可能全部记住这 70 个状态码。因此,如果您选择不常用的状态代码,您将使应用程序开发人员厌烦构建应用程序,然后您还要跑到维基百科上面找出您要告诉他们的内容,多累啊。 [更多请阅读...](https://apigee.com/about/blog/technology/restful-api-design-what-about-errors)
* 在您的响应中提供资源的总数
* 接受`limit``offset`参数
* 还应考虑资源暴露的数据量。 API消费者并不总是需要资源的完整表述。可以使用一个字段查询参数该参数用逗号分隔的字段列表来包括
```
GET /student?fields=id,name,age,class
```
* 分页,过滤和排序功能并不需要从所有资源一开始就要得到支持。记录下那些提供过滤和排序的资源。
<a name="api-security"></a>
### 9.2 API 安全
这些是一些基本的安全最佳实践:
* 除非通过安全的连接HTTPS否则不要只使用基本认证。不要在URL中传输验证令牌`GET /users/123?token=asdf....`
_为什么_
> 因为令牌、用户ID和密码通过网络是明文传递的它是base64编码而base64是可逆编码所以基本认证方案是不安全的。 [更多请阅读...](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication)
* 必须使用授权请求头在每个请求上发送令牌:`Authorization: Bearer xxxxxx, Extra yyyyy`
* 授权代码应该是短暂的。
* 通过不响应任何HTTP请求来拒绝任何非TLS请求以避免任何不安全的数据交换。响应`403 Forbidden`的HTTP请求。
* 考虑使用速率限制
_为什么_
> 保护您的API免受每小时数千次的机器人扫描威胁。您应该在早期就考虑实施流控。
* 适当地设置HTTP请求头可以帮助锁定和保护您的Web应用程序。[更多请阅读...](https://github.com/helmetjs/helmet)
* 您的API应将收到的数据转换为规范形式或直接拒绝响应并返回400错误请求400 Bad Request的错误并在其中包含有关错误或丢失数据的详细信息。
* 所有通过Rest API交换的数据必须由API来校验。
* 序列化JSON
_为什么_
> JSON编码器的一个关键问题是阻止任意的可执行代码在浏览器或在服务器中如果您用nodejs的话执行。您必须使用适当的JSON序列化程序对用户输入的数据进行正确编码以防止在浏览器上执行用户提供的输入这些输入可能会包含恶意代码而不是正常的用户数据。
* 验证内容类型,主要使用`application/*.json`Content-Type 头字段).
_为什么_
> 例如,接受`application/x-www-form-urlencoded`MIME类型可以允许攻击者创建一个表单并触发一个简单的POST请求。服务器不应该假定`Content-Type`。缺少`Content-Type`请求头或异常的`Content-Type`请求头,应该让服务器直接以`4XX`响应内容去拒绝请求。
<a name="api-documentation"></a>
### 9.3 API 文档
* 在[README.md模板](./README.sample.md)为 API 填写 `API Reference` 段落。
* 尽量使用示例代码来描述 API 授权方法
* 解释 URL 的结构(仅 path不包括根 URL包括请求类型方法
对于每个端点endpoint说明
* 如果存在 URL 参数就使用 URL 参数并根据URL中使用到的名称来指定它们
```
Required: id=[integer]
Optional: photo_id=[alphanumeric]
```
* 如果请求类型为 POST请提供如何使用的示例。上述的URL参数规则在这也可以适用。分为`可选``必需`
* 响应成功,应该对应什么样的状态代码,返回了哪些数据?当人们需要知道他们的回调应该是期望的样子,这很有用:
```
Code: 200
Content: { id : 12 }
```
* 错误响应,大多数端点都存在许多失败的可能。从未经授权的访问到错误参数等。所有的(错误描述信息)都应该列在这里。虽然有可能会重复,但它却有助于防止别人的猜想(,减少使用时的排错时间)。例如
```json
{
"code": 403,
"message" : "Authentication failed",
"description" : "Invalid username or password"
}
```
* 使用API设计工具有很多开源工具可用于提供良好的文档例如 [API Blueprint](https://apiblueprint.org/) and [Swagger](https://swagger.io/).
<a name="licensing"></a>
## 10. 证书
![证书](/images/licensing.png)
确保您有权使用的这些资源。如果您使用其中的软件库请记住先查询MITApache或BSD以更好地了解您所能够拥有的权限但如果您打算修改它们请查看许可证详细信息。图像和视频的版权可能会导致法律问题。
---
资源:
[RisingStack Engineering](https://blog.risingstack.com/),
[Mozilla Developer Network](https://developer.mozilla.org/),
[Heroku Dev Center](https://devcenter.heroku.com),
[Airbnb/javascript](https://github.com/airbnb/javascript),
[Atlassian Git tutorials](https://www.atlassian.com/git/tutorials),
[Apigee](https://apigee.com/about/blog),
[Wishtack](https://blog.wishtack.com)
本文件图标来自 [icons8](https://icons8.com/)

823
README.md
View File

@ -1,58 +1,815 @@
[Português](./README-pt-PT.md)
[<img src="https://git.sthope.dev/sthope/.gitea/raw/branch/master/avatar-sthope.png" align="right" width="13%" height="13%">](https://www.sthope.dev/)
# Project_Name &middot; [![Build Status](https://img.shields.io/drone/build/sthope/DockerContainer-RandomPort?server=https%3A%2F%2Fdrone.sthope.dev&style=plastic)](../../..) [![MIT license](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=plastic&logo=gitea)](LICENSE)
[中文版](./README-zh.md)
| [日本語版](./README-ja.md)
| [한국어](./README-ko.md)
| [Русский](./README-ru.md)
| [Português](./README-pt-BR.md)
> 🔥[Sthope](https://www.sthope.dev)
[<img src="./images/elsewhen-logo.png" width="180" height="180">](https://www.elsewhen.com/)
A brief description of your project, what it is used for.
## :construction_worker: Installing / Getting started
# Project Guidelines &middot; [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
> While developing a new project is like rolling on a green field for you, maintaining it is a potential dark twisted nightmare for someone else.
Here's a list of guidelines we've found, written and gathered that (we think) works really well with most JavaScript projects here at [elsewhen](https://www.elsewhen.com).
If you want to share a best practice, or think one of these guidelines should be removed, [feel free to share it with us](http://makeapullrequest.com).
A quick introduction of the minimal setup you need to get a hello world up &
running.
<hr>
```shell
commands here
```
- [Git](#git)
- [Some Git rules](#some-git-rules)
- [Git workflow](#git-workflow)
- [Writing good commit messages](#writing-good-commit-messages)
- [Documentation](#documentation)
- [Environments](#environments)
- [Consistent dev environments](#consistent-dev-environments)
- [Consistent dependencies](#consistent-dependencies)
- [Dependencies](#dependencies)
- [Testing](#testing)
- [Structure and Naming](#structure-and-naming)
- [Code style](#code-style)
- [Some code style guidelines](#code-style-check)
- [Enforcing code style standards](#enforcing-code-style-standards)
- [Logging](#logging)
- [API](#api)
- [API design](#api-design)
- [API security](#api-security)
- [API documentation](#api-documentation)
- [Accessability](#a11y)
- [Licensing](#licensing)
Here you should say what actually happens when you execute the code above.
<a name="git"></a>
## 1. Git
![Git](/images/branching.png)
<a name="some-git-rules"></a>
## :trophy: Versioning
### 1.1 Some Git rules
There are a set of rules to keep in mind:
* Perform work in a feature branch.
_Why:_
>Because this way all work is done in isolation on a dedicated branch rather than the main branch. It allows you to submit multiple pull requests without confusion. You can iterate without polluting the master branch with potentially unstable, unfinished code. [read more...](https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow)
This project uses [semantic releases](https://github.com/cenk1cenk2/drone-semantic-release) for versioning. For the versions available, see the [Tags](../../../tags).
* Branch out from `develop`
_Why:_
>This way, you can make sure that code in master will almost always build without problems, and can be mostly used directly for releases (this might be overkill for some projects).
## 📥 Configuration
* Never push into `develop` or `master` branch. Make a Pull Request.
_Why:_
> It notifies team members that they have completed a feature. It also enables easy peer-review of the code and dedicates forum for discussing the proposed feature.
example_how_it_works
* Update your local `develop` branch and do an interactive rebase before pushing your feature and making a Pull Request.
## :bug: Issues
_Why:_
> Rebasing will merge in the requested branch (`master` or `develop`) and apply the commits that you have made locally to the top of the history without creating a merge commit (assuming there were no conflicts). Resulting in a nice and clean history. [read more ...](https://www.atlassian.com/git/tutorials/merging-vs-rebasing)
Feel free to **file a new issue** with a respective title and description on the the [repository](../../../issues). If you already found a solution to your problem, [**i would love to review your pull request**](../../../pulls)!
* Resolve potential conflicts while rebasing and before making a Pull Request.
* Delete local and remote feature branches after merging.
_Why:_
> It will clutter up your list of branches with dead branches. It ensures you only ever merge the branch back into (`master` or `develop`) once. Feature branches should only exist while the work is still in progress.
## :tada: Contributing
* Before making a Pull Request, make sure your feature branch builds successfully and passes all tests (including code style checks).
_Why:_
> You are about to add your code to a stable branch. If your feature-branch tests fail, there is a high chance that your destination branch build will fail too. Additionally, you need to apply code style check before making a Pull Request. It aids readability and reduces the chance of formatting fixes being mingled in with actual changes.
First of all, thank you for being interested in helping out, your time is always appreciated in every way. :100:
* Use [this](./.gitignore) `.gitignore` file.
_Why:_
> It already has a list of system files that should not be sent with your code into a remote repository. In addition, it excludes setting folders and files for most used editors, as well as most common dependency folders.
Here's some tips:
* Protect your `develop` and `master` branch.
_Why:_
> It protects your production-ready branches from receiving unexpected and irreversible changes. read more... [Github](https://help.github.com/articles/about-protected-branches/), [Bitbucket](https://confluence.atlassian.com/bitbucketserver/using-branch-permissions-776639807.html) and [GitLab](https://docs.gitlab.com/ee/user/project/protected_branches.html)
* Check the [issues page](../../../issues) for already opened issues (or maybe even closed ones) that might already address your question/bug/feature request.
* Feature requests are welcomed! Provide some details on why it would be helpful for you and others, explain how you're using bull-board and if possible even some screenshots if you are willing to mock something!
<a name="git-workflow"></a>
### 1.2 Git workflow
Because of most of the reasons above, we use [Feature-branch-workflow](https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow) with [Interactive Rebasing](https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing) and some elements of [Gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows#gitflow-workflow) (naming and having a develop branch). The main steps are as follows:
Check out the [contributing](./CONTRIBUTING.md) page to see the best places to file issues, start discussions and begin contributing.
* For a new project, initialize a git repository in the project directory. __For subsequent features/changes this step should be ignored__.
```sh
cd <project directory>
git init
```
## Support
* Checkout a new feature/bug-fix branch.
```sh
git checkout -b <branchname>
```
* Make Changes.
```sh
git add <file1> <file2> ...
git commit
```
_Why:_
> `git add <file1> <file2> ... ` - you should add only files that make up a small and coherent change.
> `git commit` will start an editor which lets you separate the subject from the body.
> Read more about it in *section 1.3*.
_Tip:_
> You could use `git add -p` instead, which will give you chance to review all of the introduced changes one by one, and decide whether to include them in the commit or not.
Reach out to the maintainer at one of the following places:
* Sync with remote to get changes youve missed.
```sh
git checkout develop
git pull
```
_Why:_
> This will give you a chance to deal with conflicts on your machine while rebasing (later) rather than creating a Pull Request that contains conflicts.
* Update your feature branch with latest changes from develop by interactive rebase.
```sh
git checkout <branchname>
git rebase -i --autosquash develop
```
_Why:_
> You can use --autosquash to squash all your commits to a single commit. Nobody wants many commits for a single feature in develop branch. [read more...](https://robots.thoughtbot.com/autosquashing-git-commits)
* If you dont have conflicts, skip this step. If you have conflicts, [resolve them](https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/) and continue rebase.
```sh
git add <file1> <file2> ...
git rebase --continue
```
* Push your branch. Rebase will change history, so you'll have to use `-f` to force changes into the remote branch. If someone else is working on your branch, use the less destructive `--force-with-lease`.
```sh
git push -f
```
_Why:_
> When you do a rebase, you are changing the history on your feature branch. As a result, Git will reject normal `git push`. Instead, you'll need to use the -f or --force flag. [read more...](https://developer.atlassian.com/blog/2015/04/force-with-lease/)
* Make a Pull Request.
* Pull request will be accepted, merged and close by a reviewer.
* Remove your local feature branch if you're done.
* [Discord chat](1256)
* The email which is located [in Github profile](12345)
```sh
git branch -d <branchname>
```
to remove all branches which are no longer on remote
```sh
git fetch -p && for branch in `git branch -vv --no-color | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done
```
## :closed_book: License
<a name="writing-good-commit-messages"></a>
### 1.3 Writing good commit messages
Released in 2021 :closed_book: License
Having a good guideline for creating commits and sticking to it makes working with Git and collaborating with others a lot easier. Here are some rules of thumb ([source](https://chris.beams.io/posts/git-commit/#seven-rules)):
Made with :heart: by [Sthope](https://www.sthope.dev)
For more information, please refer to the [LICENSE](LICENSE) file.
* Separate the subject from the body with a newline between the two.
_Why:_
> Git is smart enough to distinguish the first line of your commit message as your summary. In fact, if you try git shortlog, instead of git log, you will see a long list of commit messages, consisting of the id of the commit, and the summary only.
* Limit the subject line to 50 characters and Wrap the body at 72 characters.
_why_
> Commits should be as fine-grained and focused as possible, it is not the place to be verbose. [read more...](https://medium.com/@preslavrachev/what-s-with-the-50-72-rule-8a906f61f09c)
* Capitalize the subject line.
* Do not end the subject line with a period.
* Use [imperative mood](https://en.wikipedia.org/wiki/Imperative_mood) in the subject line.
_Why:_
> Rather than writing messages that say what a committer has done. It's better to consider these messages as the instructions for what is going to be done after the commit is applied on the repository. [read more...](https://news.ycombinator.com/item?id=2079612)
* Use the body to explain **what** and **why** as opposed to **how**.
<a name="documentation"></a>
## 2. Documentation
![Documentation](/images/documentation.png)
* Use this [template](./README.sample.md) for `README.md`, Feel free to add uncovered sections.
* For projects with more than one repository, provide links to them in their respective `README.md` files.
* Keep `README.md` updated as a project evolves.
* Comment your code. Try to make it as clear as possible what you are intending with each major section.
* If there is an open discussion on github or stackoverflow about the code or approach you're using, include the link in your comment.
* Don't use comments as an excuse for a bad code. Keep your code clean.
* Don't use clean code as an excuse to not comment at all.
* Keep comments relevant as your code evolves.
<a name="environments"></a>
## 3. Environments
![Environments](/images/laptop.png)
* Define separate `development`, `test` and `production` environments if needed.
_Why:_
> Different data, tokens, APIs, ports etc... might be needed in different environments. You may want an isolated `development` mode that calls fake API which returns predictable data, making both automated and manual testing much easier. Or you may want to enable Google Analytics only on `production` and so on. [read more...](https://stackoverflow.com/questions/8332333/node-js-setting-up-environment-specific-configs-to-be-used-with-everyauth)
* Load your deployment specific configurations from environment variables and never add them to the codebase as constants, [look at this sample](./config.sample.js).
_Why:_
> You have tokens, passwords and other valuable information in there. Your config should be correctly separated from the app internals as if the codebase could be made public at any moment.
_How:_
>
`.env` files to store your variables and add them to `.gitignore` to be excluded. Instead, commit a `.env.example` which serves as a guide for developers. For production, you should still set your environment variables in the standard way.
[read more](https://medium.com/@rafaelvidaurre/managing-environment-variables-in-node-js-2cb45a55195f)
* Its recommended to validate environment variables before your app starts. [Look at this sample](./configWithTest.sample.js) using `joi` to validate provided values.
_Why:_
> It may save others from hours of troubleshooting.
<a name="consistent-dev-environments"></a>
### 3.1 Consistent dev environments:
* Set your node version in `engines` in `package.json`.
_Why:_
> It lets others know the version of node the project works on. [read more...](https://docs.npmjs.com/files/package.json#engines)
* Additionally, use `nvm` and create a `.nvmrc` in your project root. Don't forget to mention it in the documentation.
_Why:_
> Any one who uses `nvm` can simply use `nvm use` to switch to the suitable node version. [read more...](https://github.com/creationix/nvm)
* It's a good idea to setup a `preinstall` script that checks node and npm versions.
_Why:_
> Some dependencies may fail when installed by newer versions of npm.
* Use Docker image if you can.
_Why:_
> It can give you a consistent environment across the entire workflow. Without much need to fiddle with dependencies or configs. [read more...](https://hackernoon.com/how-to-dockerize-a-node-js-application-4fbab45a0c19)
* Use local modules instead of using globally installed modules.
_Why:_
> Lets you share your tooling with your colleague instead of expecting them to have it globally on their systems.
<a name="consistent-dependencies"></a>
### 3.2 Consistent dependencies:
* Make sure your team members get the exact same dependencies as you.
_Why:_
> Because you want the code to behave as expected and identical in any development machine [read more...](https://kostasbariotis.com/consistent-dependencies-across-teams/)
_how:_
> Use `package-lock.json` on `npm@5` or higher
_I don't have npm@5:_
> Alternatively you can use `Yarn` and make sure to mention it in `README.md`. Your lock file and `package.json` should have the same versions after each dependency update. [read more...](https://yarnpkg.com/en/)
_I don't like the name `Yarn`:_
> Too bad. For older versions of `npm`, use `—save --save-exact` when installing a new dependency and create `npm-shrinkwrap.json` before publishing. [read more...](https://docs.npmjs.com/files/package-locks)
<a name="dependencies"></a>
## 4. Dependencies
![Github](/images/modules.png)
* Keep track of your currently available packages: e.g., `npm ls --depth=0`. [read more...](https://docs.npmjs.com/cli/ls)
* See if any of your packages have become unused or irrelevant: `depcheck`. [read more...](https://www.npmjs.com/package/depcheck)
_Why:_
> You may include an unused library in your code and increase the production bundle size. Find unused dependencies and get rid of them.
* Before using a dependency, check its download statistics to see if it is heavily used by the community: `npm-stat`. [read more...](https://npm-stat.com/)
_Why:_
> More usage mostly means more contributors, which usually means better maintenance, and all of these result in quickly discovered bugs and quickly developed fixes.
* Before using a dependency, check to see if it has a good, mature version release frequency with a large number of maintainers: e.g., `npm view async`. [read more...](https://docs.npmjs.com/cli/view)
_Why:_
> Having loads of contributors won't be as effective if maintainers don't merge fixes and patches quickly enough.
* If a less known dependency is needed, discuss it with the team before using it.
* Always make sure your app works with the latest version of its dependencies without breaking: `npm outdated`. [read more...](https://docs.npmjs.com/cli/outdated)
_Why:_
> Dependency updates sometimes contain breaking changes. Always check their release notes when updates show up. Update your dependencies one by one, that makes troubleshooting easier if anything goes wrong. Use a cool tool such as [npm-check-updates](https://github.com/tjunnone/npm-check-updates).
* Check to see if the package has known security vulnerabilities with, e.g., [Snyk](https://snyk.io/test?utm_source=risingstack_blog).
<a name="testing"></a>
## 5. Testing
![Testing](/images/testing.png)
* Have a `test` mode environment if needed.
_Why:_
> While sometimes end to end testing in `production` mode might seem enough, there are some exceptions: One example is you may not want to enable analytical information on a 'production' mode and pollute someone's dashboard with test data. The other example is that your API may have rate limits in `production` and blocks your test calls after a certain amount of requests.
* Place your test files next to the tested modules using `*.test.js` or `*.spec.js` naming convention, like `moduleName.spec.js`.
_Why:_
> You don't want to dig through a folder structure to find a unit test. [read more...](https://hackernoon.com/structure-your-javascript-code-for-testability-9bc93d9c72dc)
* Put your additional test files into a separate test folder to avoid confusion.
_Why:_
> Some test files don't particularly relate to any specific implementation file. You have to put it in a folder that is most likely to be found by other developers: `__test__` folder. This name: `__test__` is also standard now and gets picked up by most JavaScript testing frameworks.
* Write testable code, avoid side effects, extract side effects, write pure functions
_Why:_
> You want to test a business logic as separate units. You have to "minimize the impact of randomness and nondeterministic processes on the reliability of your code". [read more...](https://medium.com/javascript-scene/tdd-the-rite-way-53c9b46f45e3)
> A pure function is a function that always returns the same output for the same input. Conversely, an impure function is one that may have side effects or depends on conditions from the outside to produce a value. That makes it less predictable. [read more...](https://hackernoon.com/structure-your-javascript-code-for-testability-9bc93d9c72dc)
* Use a static type checker
_Why:_
> Sometimes you may need a Static type checker. It brings a certain level of reliability to your code. [read more...](https://medium.freecodecamp.org/why-use-static-types-in-javascript-part-1-8382da1e0adb)
* Run tests locally before making any pull requests to `develop`.
_Why:_
> You don't want to be the one who caused production-ready branch build to fail. Run your tests after your `rebase` and before pushing your feature-branch to a remote repository.
* Document your tests including instructions in the relevant section of your `README.md` file.
_Why:_
> It's a handy note you leave behind for other developers or DevOps experts or QA or anyone who gets lucky enough to work on your code.
<a name="structure-and-naming"></a>
## 6. Structure and Naming
![Structure and Naming](/images/folder-tree.png)
* Organize your files around product features / pages / components, not roles. Also, place your test files next to their implementation.
**Bad**
```
.
├── controllers
| ├── product.js
| └── user.js
├── models
| ├── product.js
| └── user.js
```
**Good**
```
.
├── product
| ├── index.js
| ├── product.js
| └── product.test.js
├── user
| ├── index.js
| ├── user.js
| └── user.test.js
```
_Why:_
> Instead of a long list of files, you will create small modules that encapsulate one responsibility including its test and so on. It gets much easier to navigate through and things can be found at a glance.
* Put your additional test files to a separate test folder to avoid confusion.
_Why:_
> It is a time saver for other developers or DevOps experts in your team.
* Use a `./config` folder and don't make different config files for different environments.
_Why:_
>When you break down a config file for different purposes (database, API and so on); putting them in a folder with a very recognizable name such as `config` makes sense. Just remember not to make different config files for different environments. It doesn't scale cleanly, as more deploys of the app are created, new environment names are necessary.
Values to be used in config files should be provided by environment variables. [read more...](https://medium.com/@fedorHK/no-config-b3f1171eecd5)
* Put your scripts in a `./scripts` folder. This includes `bash` and `node` scripts.
_Why:_
>It's very likely you may end up with more than one script, production build, development build, database feeders, database synchronization and so on.
* Place your build output in a `./build` folder. Add `build/` to `.gitignore`.
_Why:_
>Name it what you like, `dist` is also cool. But make sure that keep it consistent with your team. What gets in there is most likely generated (bundled, compiled, transpiled) or moved there. What you can generate, your teammates should be able to generate too, so there is no point committing them into your remote repository. Unless you specifically want to.
<a name="code-style"></a>
## 7. Code style
![Code style](/images/code-style.png)
<a name="code-style-check"></a>
### 7.1 Some code style guidelines
* Use stage-2 and higher JavaScript (modern) syntax for new projects. For old project stay consistent with existing syntax unless you intend to modernise the project.
_Why:_
> This is all up to you. We use transpilers to use advantages of new syntax. stage-2 is more likely to eventually become part of the spec with only minor revisions.
* Include code style check in your build process.
_Why:_
> Breaking your build is one way of enforcing code style to your code. It prevents you from taking it less seriously. Do it for both client and server-side code. [read more...](https://www.robinwieruch.de/react-eslint-webpack-babel/)
* Use [ESLint - Pluggable JavaScript linter](http://eslint.org/) to enforce code style.
_Why:_
> We simply prefer `eslint`, you don't have to. It has more rules supported, the ability to configure the rules, and ability to add custom rules.
* We use [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript) for JavaScript, [Read more](https://www.gitbook.com/book/duk/airbnb-javascript-guidelines/details). Use the javascript style guide required by the project or your team.
* We use [Flow type style check rules for ESLint](https://github.com/gajus/eslint-plugin-flowtype) when using [FlowType](https://flow.org/).
_Why:_
> Flow introduces few syntaxes that also need to follow certain code style and be checked.
* Use `.eslintignore` to exclude files or folders from code style checks.
_Why:_
> You don't have to pollute your code with `eslint-disable` comments whenever you need to exclude a couple of files from style checking.
* Remove any of your `eslint` disable comments before making a Pull Request.
_Why:_
> It's normal to disable style check while working on a code block to focus more on the logic. Just remember to remove those `eslint-disable` comments and follow the rules.
* Depending on the size of the task use `//TODO:` comments or open a ticket.
_Why:_
> So then you can remind yourself and others about a small task (like refactoring a function or updating a comment). For larger tasks use `//TODO(#3456)` which is enforced by a lint rule and the number is an open ticket.
* Always comment and keep them relevant as code changes. Remove commented blocks of code.
_Why:_
> Your code should be as readable as possible, you should get rid of anything distracting. If you refactored a function, don't just comment out the old one, remove it.
* Avoid irrelevant or funny comments, logs or naming.
_Why:_
> While your build process may(should) get rid of them, sometimes your source code may get handed over to another company/client and they may not share the same banter.
* Make your names search-able with meaningful distinctions avoid shortened names. For functions use long, descriptive names. A function name should be a verb or a verb phrase, and it needs to communicate its intention.
_Why:_
> It makes it more natural to read the source code.
* Organize your functions in a file according to the step-down rule. Higher level functions should be on top and lower levels below.
_Why:_
> It makes it more natural to read the source code.
<a name="enforcing-code-style-standards"></a>
### 7.2 Enforcing code style standards
* Use a [.editorconfig](http://editorconfig.org/) file which helps developers define and maintain consistent coding styles between different editors and IDEs on the project.
_Why:_
> The EditorConfig project consists of a file format for defining coding styles and a collection of text editor plugins that enable editors to read the file format and adhere to defined styles. EditorConfig files are easily readable and they work nicely with version control systems.
* Have your editor notify you about code style errors. Use [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) and [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) with your existing ESLint configuration. [read more...](https://github.com/prettier/eslint-config-prettier#installation)
* Consider using Git hooks.
_Why:_
> Git hooks greatly increase a developer's productivity. Make changes, commit and push to staging or production environments without the fear of breaking builds. [read more...](http://githooks.com/)
* Use Prettier with a precommit hook.
_Why:_
> While `prettier` itself can be very powerful, it's not very productive to run it simply as an npm task alone each time to format code. This is where `lint-staged` (and `husky`) come into play. Read more on configuring `lint-staged` [here](https://github.com/okonet/lint-staged#configuration) and on configuring `husky` [here](https://github.com/typicode/husky).
<a name="logging"></a>
## 8. Logging
![Logging](/images/logging.png)
* Avoid client-side console logs in production
_Why:_
> Even though your build process can (should) get rid of them, make sure that your code style checker warns you about leftover console logs.
* Produce readable production logging. Ideally use logging libraries to be used in production mode (such as [winston](https://github.com/winstonjs/winston) or
[node-bunyan](https://github.com/trentm/node-bunyan)).
_Why:_
> It makes your troubleshooting less unpleasant with colorization, timestamps, log to a file in addition to the console or even logging to a file that rotates daily. [read more...](https://blog.risingstack.com/node-js-logging-tutorial/)
<a name="api"></a>
## 9. API
<a name="api-design"></a>
![API](/images/api.png)
### 9.1 API design
_Why:_
> Because we try to enforce development of sanely constructed RESTful interfaces, which team members and clients can consume simply and consistently.
_Why:_
> Lack of consistency and simplicity can massively increase integration and maintenance costs. Which is why `API design` is included in this document.
* We mostly follow resource-oriented design. It has three main factors: resources, collection, and URLs.
* A resource has data, gets nested, and there are methods that operate against it.
* A group of resources is called a collection.
* URL identifies the online location of resource or collection.
_Why:_
> This is a very well-known design to developers (your main API consumers). Apart from readability and ease of use, it allows us to write generic libraries and connectors without even knowing what the API is about.
* use kebab-case for URLs.
* use camelCase for parameters in the query string or resource fields.
* use plural kebab-case for resource names in URLs.
* Always use a plural nouns for naming a url pointing to a collection: `/users`.
_Why:_
> Basically, it reads better and keeps URLs consistent. [read more...](https://apigee.com/about/blog/technology/restful-api-design-plural-nouns-and-concrete-names)
* In the source code convert plurals to variables and properties with a List suffix.
_Why_:
> Plural is nice in the URL but in the source code, its just too subtle and error-prone.
* Always use a singular concept that starts with a collection and ends to an identifier:
```
/students/245743
/airports/kjfk
```
* Avoid URLs like this:
```
GET /blogs/:blogId/posts/:postId/summary
```
_Why:_
> This is not pointing to a resource but to a property instead. You can pass the property as a parameter to trim your response.
* Keep verbs out of your resource URLs.
_Why:_
> Because if you use a verb for each resource operation you soon will have a huge list of URLs and no consistent pattern which makes it difficult for developers to learn. Plus we use verbs for something else.
* Use verbs for non-resources. In this case, your API doesn't return any resources. Instead, you execute an operation and return the result. These **are not** CRUD (create, retrieve, update, and delete) operations:
```
/translate?text=Hallo
```
_Why:_
> Because for CRUD we use HTTP methods on `resource` or `collection` URLs. The verbs we were talking about are actually `Controllers`. You usually don't develop many of these. [read more...](https://github.com/byrondover/api-guidelines/blob/master/Guidelines.md#controller)
* The request body or response type is JSON then please follow `camelCase` for `JSON` property names to maintain the consistency.
_Why:_
> This is a JavaScript project guideline, where the programming language for generating and parsing JSON is assumed to be JavaScript.
* Even though a resource is a singular concept that is similar to an object instance or database record, you should not use your `table_name` for a resource name and `column_name` resource property.
_Why:_
> Because your intention is to expose Resources, not your database schema details.
* Again, only use nouns in your URL when naming your resources and dont try to explain their functionality.
_Why:_
> Only use nouns in your resource URLs, avoid endpoints like `/addNewUser` or `/updateUser` . Also avoid sending resource operations as a parameter.
* Explain the CRUD functionalities using HTTP methods:
_How:_
> `GET`: To retrieve a representation of a resource.
> `POST`: To create new resources and sub-resources.
> `PUT`: To update existing resources.
> `PATCH`: To update existing resources. It only updates the fields that were supplied, leaving the others alone.
> `DELETE`: To delete existing resources.
* For nested resources, use the relation between them in the URL. For instance, using `id` to relate an employee to a company.
_Why:_
> This is a natural way to make resources explorable.
_How:_
> `GET /schools/2/students ` , should get the list of all students from school 2.
> `GET /schools/2/students/31` , should get the details of student 31, which belongs to school 2.
> `DELETE /schools/2/students/31` , should delete student 31, which belongs to school 2.
> `PUT /schools/2/students/31` , should update info of student 31, Use PUT on resource-URL only, not collection.
> `POST /schools` , should create a new school and return the details of the new school created. Use POST on collection-URLs.
* Use a simple ordinal number for a version with a `v` prefix (v1, v2). Move it all the way to the left in the URL so that it has the highest scope:
```
http://api.domain.com/v1/schools/3/students
```
_Why:_
> When your APIs are public for other third parties, upgrading the APIs with some breaking change would also lead to breaking the existing products or services using your APIs. Using versions in your URL can prevent that from happening. [read more...](https://apigee.com/about/blog/technology/restful-api-design-tips-versioning)
* Response messages must be self-descriptive. A good error message response might look something like this:
```json
{
"code": 1234,
"message" : "Something bad happened",
"description" : "More details"
}
```
or for validation errors:
```json
{
"code" : 2314,
"message" : "Validation Failed",
"errors" : [
{
"code" : 1233,
"field" : "email",
"message" : "Invalid email"
},
{
"code" : 1234,
"field" : "password",
"message" : "No password provided"
}
]
}
```
_Why:_
> developers depend on well-designed errors at the critical times when they are troubleshooting and resolving issues after the applications they've built using your APIs are in the hands of their users.
_Note: Keep security exception messages as generic as possible. For instance, Instead of saying incorrect password, you can reply back saying invalid username or password so that we dont unknowingly inform user that username was indeed correct and only the password was incorrect._
* Use these status codes to send with your response to describe whether **everything worked**,
The **client app did something wrong** or The **API did something wrong**.
_Which ones:_
> `200 OK` response represents success for `GET`, `PUT` or `POST` requests.
> `201 Created` for when a new instance is created. Creating a new instance, using `POST` method returns `201` status code.
> `204 No Content` response represents success but there is no content to be sent in the response. Use it when `DELETE` operation succeeds.
> `304 Not Modified` response is to minimize information transfer when the recipient already has cached representations.
> `400 Bad Request` for when the request was not processed, as the server could not understand what the client is asking for.
> `401 Unauthorized` for when the request lacks valid credentials and it should re-request with the required credentials.
> `403 Forbidden` means the server understood the request but refuses to authorize it.
> `404 Not Found` indicates that the requested resource was not found.
> `500 Internal Server Error` indicates that the request is valid, but the server could not fulfill it due to some unexpected condition.
_Why:_
> Most API providers use a small subset HTTP status codes. For example, the Google GData API uses only 10 status codes, Netflix uses 9, and Digg, only 8. Of course, these responses contain a body with additional information. There are over 70 HTTP status codes. However, most developers don't have all 70 memorized. So if you choose status codes that are not very common you will force application developers away from building their apps and over to wikipedia to figure out what you're trying to tell them. [read more...](https://apigee.com/about/blog/technology/restful-api-design-what-about-errors)
* Provide total numbers of resources in your response.
* Accept `limit` and `offset` parameters.
* The amount of data the resource exposes should also be taken into account. The API consumer doesn't always need the full representation of a resource. Use a fields query parameter that takes a comma separated list of fields to include:
```
GET /students?fields=id,name,age,class
```
* Pagination, filtering, and sorting dont need to be supported from start for all resources. Document those resources that offer filtering and sorting.
<a name="api-security"></a>
### 9.2 API security
These are some basic security best practices:
* Don't use basic authentication unless over a secure connection (HTTPS). Authentication tokens must not be transmitted in the URL: `GET /users/123?token=asdf....`
_Why:_
> Because Token, or user ID and password are passed over the network as clear text (it is base64 encoded, but base64 is a reversible encoding), the basic authentication scheme is not secure. [read more...](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication)
* Tokens must be transmitted using the Authorization header on every request: `Authorization: Bearer xxxxxx, Extra yyyyy`.
* Authorization Code should be short-lived.
* Reject any non-TLS requests by not responding to any HTTP request to avoid any insecure data exchange. Respond to HTTP requests by `403 Forbidden`.
* Consider using Rate Limiting.
_Why:_
> To protect your APIs from bot threats that call your API thousands of times per hour. You should consider implementing rate limit early on.
* Setting HTTP headers appropriately can help to lock down and secure your web application. [read more...](https://github.com/helmetjs/helmet)
* Your API should convert the received data to their canonical form or reject them. Return 400 Bad Request with details about any errors from bad or missing data.
* All the data exchanged with the REST API must be validated by the API.
* Serialize your JSON.
_Why:_
> A key concern with JSON encoders is preventing arbitrary JavaScript remote code execution within the browser... or, if you're using node.js, on the server. It's vital that you use a proper JSON serializer to encode user-supplied data properly to prevent the execution of user-supplied input on the browser.
* Validate the content-type and mostly use `application/*json` (Content-Type header).
_Why:_
> For instance, accepting the `application/x-www-form-urlencoded` mime type allows the attacker to create a form and trigger a simple POST request. The server should never assume the Content-Type. A lack of Content-Type header or an unexpected Content-Type header should result in the server rejecting the content with a `4XX` response.
* Check the API Security Checklist Project. [read more...](https://github.com/shieldfy/API-Security-Checklist)
<a name="api-documentation"></a>
### 9.3 API documentation
* Fill the `API Reference` section in [README.md template](./README.sample.md) for API.
* Describe API authentication methods with a code sample.
* Explaining The URL Structure (path only, no root URL) including The request type (Method).
For each endpoint explain:
* URL Params If URL Params exist, specify them in accordance with name mentioned in URL section:
```
Required: id=[integer]
Optional: photo_id=[alphanumeric]
```
* If the request type is POST, provide working examples. URL Params rules apply here too. Separate the section into Optional and Required.
* Success Response, What should be the status code and is there any return data? This is useful when people need to know what their callbacks should expect:
```
Code: 200
Content: { id : 12 }
```
* Error Response, Most endpoints have many ways to fail. From unauthorized access to wrongful parameters etc. All of those should be listed here. It might seem repetitive, but it helps prevent assumptions from being made. For example
```json
{
"code": 401,
"message" : "Authentication failed",
"description" : "Invalid username or password"
}
```
* Use API design tools, There are lots of open source tools for good documentation such as [API Blueprint](https://apiblueprint.org/) and [Swagger](https://swagger.io/).
<a name="a11y"></a>
## 10. Accessibility ([a11y](https://www.a11yproject.com/))
![Accessibility](/images/accessibility.png)
* Take the following steps **at the start of your project** to ensure an intentional level of accessibility is sustained:
_Why:_
> Web content is [accessibile by default](https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML). We compromise this when we build complex features. It's much easier to reduce this impact by considering accessibility from the start, rather than having to re-implement these features later.
* Arrange to do regular audits using [lighthouse](https://www.notion.so/elsewhen/Accessibility-at-Elsewhen-5e495685b508402bad209b8804922922#1302363f87ac49bd9d3ffe9cd721ef1a) or the [axe DevTools extension](https://www.notion.so/elsewhen/Accessibility-at-Elsewhen-5e495685b508402bad209b8804922922#1302363f87ac49bd9d3ffe9cd721ef1a). Agree a minimum score based on your projects requirements. The scoring in both tools is based on [axe user impact assessments](https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md#wcag-21-level-a--aa-rules).
> **Note:** [some important checks](https://web.dev/lighthouse-accessibility/#additional-items-to-manually-check) must be done manually, eg logical tab order. The above tools list these as manual/guided tests alongside the automated results. With axe you have to save your automated results to view these.
* Install an a11y linter:
- React: [eslint-plugin-jsx-a11y](https://www.npmjs.com/package/eslint-plugin-jsx-a11y)
- Angular: [Angular Codelyzer](https://github.com/mgechev/codelyzer)
- Vue: [eslint-plugin-vuejs-accessibility](https://github.com/vue-a11y/eslint-plugin-vuejs-accessibility)
_Why:_
> A linter will automatically check that a basic level of accessibility is met by your project and is relatively easy to set up.
* Set up and use a11y testing using [axe-core](https://www.notion.so/elsewhen/Accessibility-at-Elsewhen-5e495685b508402bad209b8804922922#7e83a08d6a794cab8a2bfc8c9a6ed11f) or similar. If you're using storybook, do [this](https://storybook.js.org/blog/accessibility-testing-with-storybook/).
_Why:_
> Including a11y checks in your tests will help you to catch any changes that affect your projects accessibility and your audit score.
* Consider using an accessible design system such as [React Spectrum](https://react-spectrum.adobe.com/react-spectrum/) or [Material Design](https://material.io/design).
_Why:_
> These components are highly accessible out of the box
<a name="licensing"></a>
## 11. Licensing
![Licensing](/images/licensing.png)
Make sure you use resources that you have the rights to use. If you use libraries, remember to look for MIT, Apache or BSD but if you modify them, then take a look at the license details. Copyrighted images and videos may cause legal problems.
---
Sources:
[RisingStack Engineering](https://blog.risingstack.com/),
[Mozilla Developer Network](https://developer.mozilla.org/),
[Heroku Dev Center](https://devcenter.heroku.com),
[Airbnb/javascript](https://github.com/airbnb/javascript),
[Atlassian Git tutorials](https://www.atlassian.com/git/tutorials),
[Apigee](https://apigee.com/about/blog),
[Wishtack](https://blog.wishtack.com)
Icons by [icons8](https://icons8.com/)
<small>Give a ⭐️ if this project helped you!</small>

100
README.sample.md Normal file
View File

@ -0,0 +1,100 @@
<img src="./images/logo.sample.png" alt="Logo of the project" align="right">
# Name of the project &middot; [![Build Status](https://img.shields.io/travis/npm/npm/latest.svg?style=flat-square)](https://travis-ci.org/npm/npm) [![npm](https://img.shields.io/npm/v/npm.svg?style=flat-square)](https://www.npmjs.com/package/npm) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://github.com/your/your-project/blob/master/LICENSE)
> Additional information or tag line
A brief description of your project, what it is used for.
## Installing / Getting started
A quick introduction of the minimal setup you need to get a hello world up &
running.
```shell
commands here
```
Here you should say what actually happens when you execute the code above.
## Developing
### Built With
List main libraries, frameworks used including versions (React, Angular etc...)
### Prerequisites
What is needed to set up the dev environment. For instance, global dependencies or any other tools. include download links.
### Setting up Dev
Here's a brief intro about what a developer must do in order to start developing
the project further:
```shell
git clone https://github.com/your/your-project.git
cd your-project/
packagemanager install
```
And state what happens step-by-step. If there is any virtual environment, local server or database feeder needed, explain here.
### Building
If your project needs some additional steps for the developer to build the
project after some code changes, state them here. for example:
```shell
./configure
make
make install
```
Here again you should state what actually happens when the code above gets
executed.
### Deploying / Publishing
give instructions on how to build and release a new version
In case there's some step you have to take that publishes this project to a
server, this is the right time to state it.
```shell
packagemanager deploy your-project -s server.com -u username -p password
```
And again you'd need to tell what the previous code actually does.
## Versioning
We can maybe use [SemVer](http://semver.org/) for versioning. For the versions available, see the [link to tags on this repository](/tags).
## Configuration
Here you should write what are all of the configurations a user can enter when using the project.
## Tests
Describe and show how to run the tests with code examples.
Explain what these tests test and why.
```shell
Give an example
```
## Style guide
Explain your code style and show how to check it.
## Api Reference
If the api is external, link to api documentation. If not describe your api including authentication methods as well as explaining all the endpoints with their required parameters.
## Database
Explaining what database (and version) has been used. Provide download links.
Documents your database design and schemas, relations etc...
## Licensing
State what the license is and how to find the text version of the license.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

1545
emoji.md

File diff suppressed because it is too large Load Diff

BIN
images/accessibility.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
images/elsewhen-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

73
ols
View File

@ -1,73 +0,0 @@
release.config.js
---
branch: master
preset: "angular"
tagFormat: "${version}"
plugins:
- "@semantic-release/commit-analyzer"
- "@semantic-release/release-notes-generator"
- "@semantic-release/changelog"
- "@saithodev/semantic-release-gitea"
- "@saithodev/semantic-release-gitea"
verifyConditions:
- '@saithodev/semantic-release-gitea'
- "@saithodev/semantic-release-gitea"
analyzeCommits:
- path: "@semantic-release/commit-analyzer"
releaseRules:
- type: "feat"
release: "patch"
- type: "hotfix"
release: "patch"
- type: "patch"
release: "patch"
- type: "minor"
release: "minor"
- type: "breaking"
release: "major"
generateNotes:
- path: "@semantic-release/release-notes-generator"
writerOpts:
groupBy: "type"
commitGroupsSort:
- "feat"
- "perf"
- "fix"
commitsSort: "header"
types:
- type: "feat"
- section: "Features"
# Tracked bug fix with a hotfix branch
- type: "hotfix"
- section: "Bug Fixes"
# Uninmportent fix (CI testing, etc)
- type: "fix"
- hidden: true
- type: "chore"
- hidden: true
- type: "docs"
- hidden: true
- type: "doc"
- hidden: true
- type: "style"
- hidden: true
- type: "refactor"
- hidden: true
- type: "perf"
- hidden: true
- type: "test"
- hidden: true
presetConfig: true
prepare:
- path: "@saithodev/semantic-release-gitea"
- path: "@semantic-release/changelog"
changelogFile: "docs/CHANGELOG.md"
publish:
- path: "@saithodev/semantic-release-gitea"
success:
- "@saithodev/semantic-release-gitea"
fail:
- "@saithodev/semantic-release-gitea"

View File

@ -1,34 +0,0 @@
module.exports = {
"branches": [
"master",
{
"name": "alpha",
"prerelease": true
},
{
"name": "beta",
"prerelease": true
},
{
"name": "rc",
"prerelease": true
}
],
"verifyConditions": [
"@semantic-release/changelog",
"@semantic-release/git"
],
"prepare": [
"@semantic-release/changelog",
{
"path": "@semantic-release/git",
"assets": [
"CHANGELOG.md",
process.env.README_LOCATION ? process.env.README_LOCATION : 'README.md' ,
"yarn.lock",
"npm-shrinkwrap.json"
],
"message": "chore(release): <%= nextRelease.version %> - <%= new Date().toISOString().slice(0,10).replace(/-/g,'') %> [skip ci]\n\n<%= nextRelease.notes %>"
}
]
}