@cumulusds/aws-apig-bypass 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc.js +15 -0
- package/.eslintrc.js +15 -0
- package/.flowconfig +14 -0
- package/.github/dependabot.yml +15 -0
- package/.github/pull_request_template.md +18 -0
- package/.github/workflows/ci-cd.yml +86 -0
- package/LICENSE +9 -0
- package/README.md +68 -0
- package/doc/CreateAccessKey.png +0 -0
- package/doc/development.md +244 -0
- package/doc/prettier-watchers-pc.xml +222 -0
- package/doc/prettier-watchers-unix.xml +222 -0
- package/doc/webstorm-file-watcher-prettier.png +0 -0
- package/doc/webstorm-flow.png +0 -0
- package/flow-typed/npm/jest_v26.x.x.js +1218 -0
- package/lib/create-api-gateway-event.js +50 -0
- package/lib/create-api-gateway-event.js.flow +57 -0
- package/lib/create-client.js +25 -0
- package/lib/create-client.js.flow +30 -0
- package/lib/create-lambda-client.js +33 -0
- package/lib/create-lambda-client.js.flow +35 -0
- package/lib/index.js +23 -0
- package/lib/index.js.flow +4 -0
- package/lib/json-stringify.js +23 -0
- package/lib/json-stringify.js.flow +16 -0
- package/lib/lambda-invoke.js +1 -0
- package/lib/lambda-invoke.js.flow +10 -0
- package/lib/parse-payload.js +31 -0
- package/lib/parse-payload.js.flow +25 -0
- package/lib/response.js +1 -0
- package/lib/response.js.flow +15 -0
- package/package.json +86 -0
- package/prettier.config.js +3 -0
- package/src/create-api-gateway-event.js +57 -0
- package/src/create-client.js +30 -0
- package/src/create-lambda-client.js +35 -0
- package/src/index.js +4 -0
- package/src/json-stringify.js +16 -0
- package/src/lambda-invoke.js +10 -0
- package/src/parse-payload.js +25 -0
- package/src/response.js +15 -0
- package/test/unit/index.test.js +142 -0
package/.babelrc.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
presets: [
|
|
3
|
+
[
|
|
4
|
+
"@babel/preset-env",
|
|
5
|
+
{
|
|
6
|
+
targets: {
|
|
7
|
+
node: "10.15.0"
|
|
8
|
+
},
|
|
9
|
+
exclude: ["proposal-async-generator-functions"] // Do not transform async generator functions, since they are supported natively in Node 10 & 12.
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"@babel/preset-flow"
|
|
13
|
+
],
|
|
14
|
+
plugins: ["@babel/plugin-proposal-nullish-coalescing-operator", "@babel/plugin-proposal-optional-chaining"]
|
|
15
|
+
};
|
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
extends: ["airbnb-base", "plugin:prettier/recommended", "plugin:flowtype/recommended"],
|
|
3
|
+
rules: {
|
|
4
|
+
"linebreak-style": "off",
|
|
5
|
+
"no-console": "off",
|
|
6
|
+
"no-restricted-syntax": "off"
|
|
7
|
+
},
|
|
8
|
+
plugins: ["jest", "flowtype"],
|
|
9
|
+
env: {
|
|
10
|
+
"jest/globals": true
|
|
11
|
+
},
|
|
12
|
+
parserOptions: {
|
|
13
|
+
ecmaVersion: 2020
|
|
14
|
+
}
|
|
15
|
+
};
|
package/.flowconfig
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
What does this PR do?
|
|
3
|
+
|
|
4
|
+
## Dependencies
|
|
5
|
+
- [Name of the change](https://link-to-PR-or-commit)
|
|
6
|
+
|
|
7
|
+
## Changes
|
|
8
|
+
### Interface
|
|
9
|
+
- Is there a change to the package's interface?
|
|
10
|
+
|
|
11
|
+
### Developer
|
|
12
|
+
- What are the other changes that are not directly visible to the user ?
|
|
13
|
+
|
|
14
|
+
## Details
|
|
15
|
+
Why did you make this change? What does it affect?
|
|
16
|
+
|
|
17
|
+
## Testing
|
|
18
|
+
How can the other reviewers check that your change works?
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
name: ci-cd
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- '**/*'
|
|
7
|
+
pull_request:
|
|
8
|
+
release:
|
|
9
|
+
types: [released]
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
unit:
|
|
13
|
+
runs-on: ubuntu-18.04
|
|
14
|
+
strategy:
|
|
15
|
+
matrix:
|
|
16
|
+
node: [10, 12, 13, 14, 15]
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout
|
|
19
|
+
uses: actions/checkout@v2
|
|
20
|
+
- name: Install Node ${{ matrix.node }}
|
|
21
|
+
uses: actions/setup-node@v2.1.4
|
|
22
|
+
with:
|
|
23
|
+
node-version: ${{ matrix.node }}
|
|
24
|
+
- name: Install NPM credentials
|
|
25
|
+
run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
|
|
26
|
+
env:
|
|
27
|
+
NPM_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
|
|
28
|
+
- name: Get yarn cache
|
|
29
|
+
id: yarn-cache
|
|
30
|
+
run: echo "::set-output name=dir::$(yarn cache dir)"
|
|
31
|
+
- uses: actions/cache@v2.1.3
|
|
32
|
+
with:
|
|
33
|
+
path: ${{ steps.yarn-cache.outputs.dir }}
|
|
34
|
+
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
|
35
|
+
restore-keys: |
|
|
36
|
+
${{ runner.os }}-yarn-
|
|
37
|
+
- name: Install NPM Packages
|
|
38
|
+
run: yarn install --frozen-lockfile
|
|
39
|
+
- name: Check licenses
|
|
40
|
+
run: yarn build:license-checker
|
|
41
|
+
- name: Test
|
|
42
|
+
run: yarn test
|
|
43
|
+
- uses: 8398a7/action-slack@v2
|
|
44
|
+
with:
|
|
45
|
+
status: ${{ job.status }}
|
|
46
|
+
author_name: ${{ github.repository }} ${{ github.workflow }}
|
|
47
|
+
env:
|
|
48
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
49
|
+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
|
|
50
|
+
if: always()
|
|
51
|
+
- name: Upload artifacts
|
|
52
|
+
uses: actions/upload-artifact@v2.2.1
|
|
53
|
+
with:
|
|
54
|
+
name: var
|
|
55
|
+
path: var
|
|
56
|
+
if: always()
|
|
57
|
+
publish:
|
|
58
|
+
runs-on: ubuntu-18.04
|
|
59
|
+
needs: unit
|
|
60
|
+
if: github.event_name == 'release'
|
|
61
|
+
steps:
|
|
62
|
+
- name: Checkout
|
|
63
|
+
uses: actions/checkout@v2
|
|
64
|
+
- name: Install Node 14
|
|
65
|
+
uses: actions/setup-node@v2.1.4
|
|
66
|
+
with:
|
|
67
|
+
node-version: 14
|
|
68
|
+
- name: Install NPM credentials
|
|
69
|
+
run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
|
|
70
|
+
env:
|
|
71
|
+
NPM_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
|
|
72
|
+
- name: Get yarn cache
|
|
73
|
+
id: yarn-cache
|
|
74
|
+
run: echo "::set-output name=dir::$(yarn cache dir)"
|
|
75
|
+
- uses: actions/cache@v2.1.3
|
|
76
|
+
with:
|
|
77
|
+
path: ${{ steps.yarn-cache.outputs.dir }}
|
|
78
|
+
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
|
79
|
+
restore-keys: |
|
|
80
|
+
${{ runner.os }}-yarn-
|
|
81
|
+
- name: Install NPM Packages
|
|
82
|
+
run: yarn install --frozen-lockfile
|
|
83
|
+
- name: Build
|
|
84
|
+
run: yarn build
|
|
85
|
+
- name: Publish
|
|
86
|
+
run: npm publish
|
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020, Cumulus Digital Systems
|
|
4
|
+
|
|
5
|
+
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:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# AWS APIG Bypass
|
|
2
|
+
|
|
3
|
+
Bypass the API Gateway by directly invoking the Lambda handler that backs an endpoint.
|
|
4
|
+
|
|
5
|
+
We often build externally accessible REST endpoints using API Gateway and Lambda. Sometimes we have an endpoint with both internal and external (outside of AWS) clients. The API Gateway provides some value to external clients, since it helps authorize and rate-limit requests. However, it is a hinderance to internal clients, where we have other means of rate-limiting. Access control is often more consistent if we rely on IAM policies. The API Gateway adds cost and reduces convenience for internal clients.
|
|
6
|
+
|
|
7
|
+
This library provides an adapter for the Lambda SDK to make it easy to directly invoke the handler.
|
|
8
|
+
|
|
9
|
+
```flow js
|
|
10
|
+
import { Lambda } from "aws-sdk";
|
|
11
|
+
|
|
12
|
+
function getLunches(location: string, category: string): Promise<Array<Lunch>> {
|
|
13
|
+
const getLunchIndex = createClient<LunchIndex>({ Lambda: new Lambda(), FunctionName: `LunchService-dev-index` });
|
|
14
|
+
const { data, status } = getLunchIndex(createAPIGatewayEvent({ pathParameters: { location, category } }));
|
|
15
|
+
if (status !== 200) {
|
|
16
|
+
throw new Error("unexpected status");
|
|
17
|
+
}
|
|
18
|
+
return data;
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
# Domain Distillation
|
|
23
|
+
|
|
24
|
+
## APIG Bypass Client
|
|
25
|
+
|
|
26
|
+
The APIG Bypass Client adapts the AWS Lambda SDK to more conveniently invoke the handler that backs an API Gateway endpoint. The client encapsulates packing and unpacking of the API Gateway event interface. Use the `createClient` factory function to get a client. The following options are supported:
|
|
27
|
+
```flow js
|
|
28
|
+
// AWS SDK Lambda client. Only the invoke function is needed.
|
|
29
|
+
Lambda: LambdaInvoke,
|
|
30
|
+
|
|
31
|
+
// Name (or ARN) of the AWS Lambda function to invoke.
|
|
32
|
+
FunctionName: string,
|
|
33
|
+
|
|
34
|
+
// Function to validate the parsed response body. The function should throw an exception if the response is invalid.
|
|
35
|
+
Validate?: T => void
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The client is a function that takes one argument, an API Gateway Event. The client synchronously invokes the handler and returns a promise with the response. The response is like this:
|
|
40
|
+
```js
|
|
41
|
+
{
|
|
42
|
+
// the decoded response provided by the handler
|
|
43
|
+
data: {},
|
|
44
|
+
|
|
45
|
+
// status code provided by the handler
|
|
46
|
+
status: 200,
|
|
47
|
+
|
|
48
|
+
// `headers` the HTTP headers that the server responded with
|
|
49
|
+
// All header names are lower cased and can be accessed using the bracket notation.
|
|
50
|
+
// Example: `response.headers['content-type']`
|
|
51
|
+
headers: {}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## API Gateway Event
|
|
56
|
+
|
|
57
|
+
Use the createAPIGatewayEvent function to format an event to pass to the APIG Bypass Client.
|
|
58
|
+
|
|
59
|
+
# Development
|
|
60
|
+
|
|
61
|
+
- [Package Structure](doc/development.md#package-structure)
|
|
62
|
+
- [Development Environment](doc/development.md#development-environment)
|
|
63
|
+
- [Quality](doc/development.md#quality)
|
|
64
|
+
- [Release](doc/development.md#release)
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
This package is not licensed.
|
|
Binary file
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# Package Structure
|
|
2
|
+
|
|
3
|
+
- `bin/` is for any executable scripts, or compiled binaries used with, or built from your module.
|
|
4
|
+
- `build/` is for any scripts or tooling needed to build the project
|
|
5
|
+
- `dist/` is for compiled modules that can be used with other systems.
|
|
6
|
+
- `doc/` is for markdown documentation of the project and related concepts.
|
|
7
|
+
- `env/` is for any environment that is needed for testing
|
|
8
|
+
- `flow-typed/` has library definitions for flow. The `flow-typed/npm` files are generated or community-supplied files. Nevertheless, these files must be included in source control.
|
|
9
|
+
- `lib/` is the compiled (portable) library code that will be linked into dependent projects.
|
|
10
|
+
- `scripts/` is for any utility scripts used for development of the module.
|
|
11
|
+
- `src/` has the production source files. The files will be compiled by babel.
|
|
12
|
+
- `test/` has the project's tests
|
|
13
|
+
- `test/unit` is for unit tests. Its structure should parallel `/src`.
|
|
14
|
+
- `test/integration` is for integration tests.
|
|
15
|
+
- `var` collects build artifacts to be archived with the GitHub actions build, but not committed to source control or included with the release package.
|
|
16
|
+
- `var/coverage/test` istanbul code-coverage output, produced by `yarn test:unit`. Open `var/coverage/test/lcov-report/index.html` to see the detailed code-coverage report from the most recent test run.
|
|
17
|
+
- `var/coverage/flow` flow-coverage-report output, produced by `yarn flow:coverage-report`. Open `var/coverage/flow/index.html` to see the detailed code-coverage report from the most recent test run.
|
|
18
|
+
|
|
19
|
+
Prefer to organize subdirectories of `/src` as modules with cohesive purposes, instead of organizing by software design pattern. We should have "plant", "maintenance", "settings" modules instead of buckets of "components", "containers" and "reducers".
|
|
20
|
+
|
|
21
|
+
## Rationale
|
|
22
|
+
|
|
23
|
+
[The CommonJS package format outlines the directory structure of Node packages.](http://wiki.commonjs.org/wiki/Packages/1.0#Package_Directory_Layout) We follow the [convention](https://gist.github.com/tracker1/59f2c13044315f88bee9#lib--src) of organizing non-executable code in `/src`, reserving `/lib` for directly executable code. The `/lib` folder is not needed in this project.
|
|
24
|
+
|
|
25
|
+
Using a separate `src` and `test` directories aligns with our convention for `serverless` projects. While placing test files alongside production code is attractive because it improves cohesion within the project, the layout is incompatible with serverless-webpack.
|
|
26
|
+
|
|
27
|
+
Organization of the source tree into modules helps to reinforce the need for a cohesive code-base.
|
|
28
|
+
|
|
29
|
+
# Development Environment
|
|
30
|
+
|
|
31
|
+
## Chocolatey (Windows only)
|
|
32
|
+
|
|
33
|
+
The Chocolatey package manager ensures consistent development environment
|
|
34
|
+
construction in Windows. Chocolatey works with Powershell. Powershell must always be
|
|
35
|
+
started with administrator privilege. To install Chocolatey:
|
|
36
|
+
|
|
37
|
+
1. Press the windows button and type "powershell".
|
|
38
|
+
2. Right-click on "Windows PowerShell" and select "Run as Administrator".
|
|
39
|
+
3. Check the execution policy by running `Get-ExecutionPolicy`.
|
|
40
|
+
4. Set the policy by running `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned`.
|
|
41
|
+
5. Install Chocolatey:
|
|
42
|
+
`iwr https://chocolatey.org/install.ps1 -UseBasicParsing | iex`.
|
|
43
|
+
|
|
44
|
+
## Node
|
|
45
|
+
|
|
46
|
+
This project supports all current and active Node Releases (Node 10, 12, 13 and 14). The same version should be used in each development environment, to minimize any friction due to differences between Node releases. The project uses babel to transform the source code for the target version of Node.
|
|
47
|
+
|
|
48
|
+
In Windows, install Node using Chocolatey from an administrator-privileged PowerShell terminal.
|
|
49
|
+
|
|
50
|
+
```ps
|
|
51
|
+
choco install nodejs --version 12.16.0 -y
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
In unix development environments, use the `n` node version manager. To install n:
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
curl -L https://git.io/n-install | bash
|
|
58
|
+
n 12
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
If you use zsh, add ~/n/bin to the PATH exported in zshrc.
|
|
62
|
+
|
|
63
|
+
[Node Releases]: https://nodejs.org/en/about/releases/
|
|
64
|
+
|
|
65
|
+
## Yarn
|
|
66
|
+
|
|
67
|
+
The development environment requires the yarn package manager. This package manager provides a stable lock file
|
|
68
|
+
format when doing development work on multiple operating systems. Yarn ensure deterministic node package installation on
|
|
69
|
+
each platform. It is also faster than npm.
|
|
70
|
+
|
|
71
|
+
To install yarn in Windows, install yarn using choco: `choco install yarn -y` from an administrator-privileged
|
|
72
|
+
PowerShell terminal.
|
|
73
|
+
|
|
74
|
+
On OSX, [install yarn] using its installation script `curl -o- -L https://yarnpkg.com/install.sh | bash`. We do not use homebrew, since it does not work well with node version managers.
|
|
75
|
+
|
|
76
|
+
After checking out this repo and installing yarn, run `yarn` from the command-line to install the node package
|
|
77
|
+
dependencies.
|
|
78
|
+
|
|
79
|
+
[install yarn]: https://yarnpkg.com/en/docs/install#mac-stable
|
|
80
|
+
|
|
81
|
+
## WebStorm
|
|
82
|
+
|
|
83
|
+
WebStorm is our standard IDE due to its ability to debug and its seamlessly integration with ESLint. By standardizing the IDE, we can less focus on development environment and increase our productivity. Feel free to use VS Code, Sublime, or any editor of your choice as long as the configurations are consistent.
|
|
84
|
+
|
|
85
|
+
## Lint
|
|
86
|
+
|
|
87
|
+
We have standardized our linting practice using ESLint built on top of [Airbnb](https://github.com/airbnb/javascript) and Google's recommendations. See the ESLint file. We are constantly working to update the rules so feel free to update to this repo as you work on your projects.
|
|
88
|
+
|
|
89
|
+
## Prettier
|
|
90
|
+
|
|
91
|
+
Prettier is great at standardizing style, and since people will use different IDEs and editors, we included two setup files for prettier.
|
|
92
|
+
|
|
93
|
+
For WebStorm, you can import Prettier as a file watcher that triggers Prettier manually when you save with `cmd+S` by using the `watcher.xml` file.
|
|
94
|
+
|
|
95
|
+
For others, we've included a .prettierrc. It has not been extensively tested against different editors and IDEs, so feel free to add your experience here.
|
|
96
|
+
|
|
97
|
+
## Scripts
|
|
98
|
+
|
|
99
|
+
Several commands are defined by the package.json scripts.
|
|
100
|
+
|
|
101
|
+
`yarn test` runs the comprehensive set of automated tests. This includes the jest unit test, flow and eslint checks.
|
|
102
|
+
|
|
103
|
+
`yarn flow:status` checks for flow type and lint errors. It is one of the checks included in `yarn test`.
|
|
104
|
+
|
|
105
|
+
`yarn git:push` pushes commits and tags to GitHub.
|
|
106
|
+
|
|
107
|
+
`yarn test:unit` runs the jest unit tests. It is one of the checks included in `yarn test`.
|
|
108
|
+
|
|
109
|
+
`yarn lint` runs the ESLint check. It is one of the checks included in `yarn test`. Some lint errors can be automatically fixed by running `yarn lint --fix`.
|
|
110
|
+
|
|
111
|
+
`yarn publish:patch` publishes a "patch" release. It bumps the patch version number, tags the release and pushes the version and tag to GitHub. `yarn publish:minor` publishes a minor release. Similarly, `yarn publish:major` publishes a major release.
|
|
112
|
+
|
|
113
|
+
`yarn version:path` creates an unpublished patch release. The minor version number is bumped, committed and tagged, but not pushed to GitHub. `yarn version:minor` creates a minor release. Similarly, `yarn versio:major` creates an unpublished major release.
|
|
114
|
+
|
|
115
|
+
### Add Prettier to WebStorm
|
|
116
|
+
|
|
117
|
+
Open the WebStorm / Preferences dialog. Search for "File Watcher". Click the Import icon (with a green arrow). Add doc/prettier-watchers-pc.xml or -unix.xml depending on your operating system. Prettier will be triggered on JS files as you do `cmd+S` or switch focus to another window.
|
|
118
|
+
|
|
119
|
+
#### Manually configure Prettier to WebStorm
|
|
120
|
+
|
|
121
|
+
While **ESLint** can notify you about both code-quality and code-style within WebStorm, its fixing tool by itself is not quite fit for auto-formatting. This is why the project is also integrated **Prettier**, a code-formatting tool with strong auto-formatting feature.
|
|
122
|
+
|
|
123
|
+
Although **Prettier** can format through **ESLint**, having Prettier to automatically format file upon saving would definitely be a plus. You can do that in WebStorm by follow steps below:
|
|
124
|
+
|
|
125
|
+
First, ensure that all dependencies are installed:
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
yarn
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Next, go to WebStorm > Preferences > Tools > File Watchers, and press the import icon. Load the file watchers from [prettier-watchers-unix.xml](prettier-watchers-unix.xml) or [prettier-watchers-pc.xml](prettier-watchers-pc.xml), depending on your system. Finally, save the changes. This configuration should apply Prettier to all supported file types.
|
|
132
|
+
|
|
133
|
+
Alternatively, add File Watchers one-by-one by pressing the "+" button and setting the following properties:
|
|
134
|
+
|
|
135
|
+
- Name: Prettier JS
|
|
136
|
+
- File Type: JavaScript
|
|
137
|
+
- Scope: Project Files
|
|
138
|
+
- Program:
|
|
139
|
+
For Mac OS X or Linux: `$ProjectFileDir$/node_modules/.bin/prettier`
|
|
140
|
+
For Windows: `$ProjectFileDir$/node_modules/.bin/prettier.cmd`
|
|
141
|
+
- Arguments: `--write $FilePathRelativeToProjectRoot$`
|
|
142
|
+
- Working Directory: `$ProjectFileDir$`
|
|
143
|
+
- Output Paths to Refresh: `$FilePathRelativeToProjectRoot$`
|
|
144
|
+
- Advanced Options: only select "Trigger the watcher on external change"
|
|
145
|
+

|
|
146
|
+
|
|
147
|
+
Then click "Apply".
|
|
148
|
+
|
|
149
|
+
To run Prettier on all supported files, run `yarn prettier`
|
|
150
|
+
|
|
151
|
+
For more information on the dependencies:
|
|
152
|
+
[eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier),
|
|
153
|
+
[eslint-config-prettier](https://github.com/prettier/eslint-config-prettier),
|
|
154
|
+
[Prettier](https://prettier.io/docs/en/webstorm.html),
|
|
155
|
+
[airbnb-base](https://www.npmjs.com/package/eslint-config-airbnb-base)
|
|
156
|
+
|
|
157
|
+
### Rationale
|
|
158
|
+
|
|
159
|
+
Prettier can be run as a pre-commit hook instead of a File Watcher. This can ensure formatting consistency while allowing developers the freedom to choose different IDEs. However, the pre-commit hook technique causes too much commit latency for larger projects (the pre-commit hook for TorqueDashboardApp with 160k sloc would add 10 seconds to the commit process). Therefore, we prefer to use the Webstorm file watcher via project-specific configuration.
|
|
160
|
+
|
|
161
|
+
A project-local installation is used, instead of a global installation. [Prettier recommends pinning an exact package version, because each patch release introduces new stylistic changes.](https://prettier.io/docs/en/install.html) The project-local installation of prettier avoids style thrashing when developing projects pinned to different versions of prettier.
|
|
162
|
+
|
|
163
|
+
The project Prettier configuration file is consistently used, instead of command-line configuration. Centralizing follows the "don't repeat yourself" rule of thumb. Centralization ensures that scripts, IDE configuration and any future method for invoking Prettier stay synchronized with the project's style standard.
|
|
164
|
+
|
|
165
|
+
## Flow
|
|
166
|
+
|
|
167
|
+
Flow is configured to use [flow-typed](https://github.com/flowtype/flow-typed) repository of libdefs (type definitions). These libdefs are be checked-into this repository because flow-typed libdefs are not pinned by a package version. It is undesirable to receive a new libdef for a dependency that has not changed, because [it could introduce a spurrious type-check failure.](https://github.com/flowtype/flow-typed/wiki/FAQs#why-do-i-need-to-commit-the-libdefs-that-flow-typed-installs-for-my-project) To maintain the flow-typed libdefs, run `yarn flow-typed install` after changing the package dependencies.
|
|
168
|
+
|
|
169
|
+
The eslint-plugin-flowtype package integrates ESLint with Flow.
|
|
170
|
+
|
|
171
|
+
The WebStorm IDE uses flow to improve navigation, code completion and type hinting. It can also show type-checking errors inline, just like syntax or lint errors. [Configure WebStorm for Flow](https://blog.jetbrains.com/webstorm/2016/11/using-flow-in-webstorm/) by using Preferences / Languages & Frameworks / Javascript. Set the language version to Flow and enable "Type checking". 
|
|
172
|
+
|
|
173
|
+
### Lint
|
|
174
|
+
|
|
175
|
+
[Flow’s linter](https://flow.org/en/docs/linting/) encourages developers to add tight type annotations. For example, it can be convenient to use the `any` type when a mock will only satisfy part of an interface. In this case, the tested function has an `Axios` instance argument, but we know that the function only really depends on a single method, `post`. When listing is enabled, we see a diagnostic for `any`. In this case, we can confirm that we think that we know what we’re doing by suppressing the lint diagnostic with a `flowlint-line` directive.
|
|
176
|
+
|
|
177
|
+
```js
|
|
178
|
+
const client: any = { post }; // flowlint-line unclear-type:off
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Build
|
|
182
|
+
|
|
183
|
+
Babel compiles the project to prepares Node-compatible javascript. The [babelrc](.babelrc.js) file configures the flow compiler and the target Node version, 10.15.0.
|
|
184
|
+
|
|
185
|
+
# Quality
|
|
186
|
+
|
|
187
|
+
High unit test coverage is essential for the sustainability of the software systems that we create. Unit test coverage gives us the ability to confidently refactor our software modules. High unit test coverage is a good indication that SOLID principles are being adhered to in the code-base; when getting test coverage for a module is hard, then it’s usually a sign that the module is serving more than one concern or is too tightly coupled to other modules. Test coverage is essential for software modules that will be reused in more than one context.
|
|
188
|
+
|
|
189
|
+
[Flow](https://flow.org/en/) is used to declare interface types. Libraries should use static type checking, because it provides users with helpful auto-completions in the IDE. These hints reduce typos and make it easier to discover the library's functionality and correctly use its interface. Type checking can also expose interface errors that are undetected in unit testing due to mocks.
|
|
190
|
+
|
|
191
|
+
To invoke the test suite, run `yarn test`. This runs ESLint, the Jest unit tests and the Flow type checker.
|
|
192
|
+
|
|
193
|
+
## ESLint
|
|
194
|
+
|
|
195
|
+
ESLint is used to enforce the [Airbnb Style Guid](https://github.com/airbnb/javascript). The burden of the style guidelines are eased through automated correction. The Prettier package helps the IDE automatically improve the formatting of the source code. The husky git hook automatically corrects some other ESLint issues when adding.
|
|
196
|
+
|
|
197
|
+
## Flow
|
|
198
|
+
|
|
199
|
+
The eslint-plugin-flowtype package integrates ESLint with Flow.
|
|
200
|
+
|
|
201
|
+
The WebStorm IDE uses flow to improve navigation, code completion and type hinting. It can also show type-checking errors inline, just like syntax or lint errors. [Configure WebStorm for Flow](https://blog.jetbrains.com/webstorm/2016/11/using-flow-in-webstorm/) by using Preferences / Languages & Frameworks / Javascript. Set the language version to Flow and enable "Type checking". 
|
|
202
|
+
|
|
203
|
+
### flow-typed
|
|
204
|
+
|
|
205
|
+
Community-built library definitions are provided by the [flow-typed](https://github.com/flowtype/flow-typed) package. These library definitions are be checked-into this repository under flow-typed/npm because flow-typed libdefs are not pinned by a package version. It is undesirable to receive a new libdef for a dependency that has not changed, because [it could introduce a spurrious type-check failure.](https://github.com/flowtype/flow-typed/wiki/FAQs#why-do-i-need-to-commit-the-libdefs-that-flow-typed-installs-for-my-project) To maintain the flow-typed libdefs, run `yarn flow-typed install` after changing the package dependencies.
|
|
206
|
+
|
|
207
|
+
### Lint
|
|
208
|
+
|
|
209
|
+
[Flow’s linter](https://flow.org/en/docs/linting/) encourages developers to add tight type annotations. For example, it can be convenient to use the `any` type when a mock will only satisfy part of an interface. In this case, the tested function has an `Axios` instance argument, but we know that the function only really depends on a single method, `post`. When listing is enabled, we see a diagnostic for `any`. In this case, we can confirm that we think that we know what we’re doing by suppressing the lint diagnostic with a `flowlint-line` directive.
|
|
210
|
+
|
|
211
|
+
```js
|
|
212
|
+
const client: any = { post }; // flowlint-line unclear-type:off
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
By default, lint is not enabled. Enable lint using [.flowconfig](.flowconfig):
|
|
216
|
+
|
|
217
|
+
```ini
|
|
218
|
+
[lints]
|
|
219
|
+
all=error
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Rationale
|
|
223
|
+
|
|
224
|
+
A problem with javascript is that unit tests are often narrowly mocked. This can keep the unit tests easy to write, very fast and avoids introducing too many details of the partners of the test subject. But the downside is that compliance to interfaces ends up not being checked until runtime. So flow type annotations allow the compiler to check whether the program adheres to a consistent set of interfaces.
|
|
225
|
+
|
|
226
|
+
It is relatively easy to learn to write the type annotations, and the diagnostic output of the flow compiler is helpful. This baseline configuration is quite picky, because the flow "linter" is enabled. Also, tests are type-checked and linted (working from the perspective that interface agreement is quite important in tests). The flow linter strongly encourages the developers to add type annotations everywhere where the type cannot be inferred. We'll need to reconsider whether the pickiness is tolerable after living with it for a few weeks. Since type-checking is not a native part of javascript, there tends to be more type friction around external libraries than there would be in a strongly typed language. The flow-typed library partially mitigates this friction.
|
|
227
|
+
|
|
228
|
+
## Jest
|
|
229
|
+
|
|
230
|
+
Jest is used to run tests. To execute the jest-based unit tests, run `yarn test:unit`. Complete unit test coverage is expected, and Jest is configured to fail if coverage is less than 100%. The tests should be written in a literate style, so that they help to document the intended behavior of the software. High test coverage gives confidence that the software works as intended.
|
|
231
|
+
|
|
232
|
+
The project is configured with a Continuous Integration server. The Continuous Integration server runs the tests and lint using the command yarn test. When AppVeyor is used for CI, the jest tests are reported to the test result collector.
|
|
233
|
+
|
|
234
|
+
## Continuous Integration
|
|
235
|
+
|
|
236
|
+
The project is required to be configured with a Continuous Integration server. The Continuous Integration server runs
|
|
237
|
+
the tests and lint using the command `yarn test`. When AppVeyor is used for CI, the jest tests are reported to the
|
|
238
|
+
[test result collector](https://ci.appveyor.com/project/shelltechworks/serverless/build/tests).
|
|
239
|
+
|
|
240
|
+
# Release
|
|
241
|
+
|
|
242
|
+
A deployment is started when a version tag (like "v1.2.3") is pushed to GitHub. The CI process is triggered by the tag. If the build passes, then CI creates a pre-release on GitHub. The new version is published to the npm registry when the version is promoted to _latest release_ by clearing the pre-release flag.
|
|
243
|
+
|
|
244
|
+
Normal releases are made from the master branch. To bump the version number and start the process of publishing a release, run `yarn publish:patch`. This will set the package.json version to the next patch number and push a tagged commit, triggering the deployment process.
|