├── .eslintrc.js
├── .github
├── CODEOWNERS
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── PULL_REQUEST_TEMPLATE.md
├── dependabot.yml
├── mergify.yml
├── renovate.json5
└── workflows
│ ├── SUBSTRATE_CODEQL.yml
│ ├── commitlint.yml
│ ├── pr-success.yml
│ └── release.yml
├── .gitignore
├── .mergify.yml
├── .nvmrc
├── .prettierrc
├── .releaserc.json
├── CHANGELOG.md
├── README.md
├── commitlint.config.js
├── docs
└── rules
│ ├── instrument-aws-clients.md
│ ├── instrument-document-clients.md
│ ├── no-aws-import.md
│ └── no-direct-lambda-invoke.md
├── lib
├── index.js
└── rules
│ ├── instrument-aws-clients.js
│ ├── instrument-document-clients.js
│ ├── no-aws-import.js
│ └── no-direct-lambda-invoke.js
├── package-lock.json
├── package.json
└── tests
└── lib
└── rules
├── instrument-aws-clients.js
├── instrument-document-clients.js
├── no-aws-import.js
└── no-direct-lambda-invoke.js
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | node: true,
4 | es2021: true,
5 | },
6 | extends: "eslint:recommended",
7 | parserOptions: {
8 | ecmaVersion: 12,
9 | sourceType: "module",
10 | },
11 | rules: {},
12 | }
13 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @Stedi/cloud
2 |
3 | # Allow bots to modify and merge these files without explicit PR approval from the team
4 | package.json
5 | package-lock.json
6 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "🐛 Bug report"
3 | about: Create a bug report
4 | ---
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 | ⚠️⚠️ REPLACE WITH DESCRIPTION
16 |
17 |
20 |
21 |
22 | problem.js
23 |
24 | ```yaml
25 | # ⚠️⚠️ REPLACE THIS COMMENT WITH FULL CONTENT
26 | ```
27 |
28 |
29 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "🎉 Feature/rule request"
3 | about: Suggest an idea
4 | ---
5 |
6 |
7 |
8 |
9 |
12 |
13 | ### Rule name
14 |
15 | ```
16 | ⚠️ REPLACE WITH NAME
17 | ```
18 |
19 |
22 |
23 | ### Use case description
24 |
25 | ⚠️ REPLACE WITH DESCRIPTION
26 |
27 |
30 |
31 | ### Examples
32 |
33 | #### Incorrect
34 |
35 | ```js
36 | ⚠️ REPLACE WITH CODE
37 | ```
38 |
39 | #### Correct
40 |
41 | ```js
42 | ⚠️ REPLACE WITH CODE
43 | ```
44 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Closes: #{ISSUE_NUMBER}
2 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | registries:
3 | npm-registry-npm-pkg-github-com:
4 | url: https://githubproxy.dev.terminal.stedi.com
5 | type: npm-registry
6 | token: ${{secrets.DEPENDABOT_PACKAGE_TOKEN}}
7 | npm-registry-npm-pkg-github-com-stedi:
8 | url: https://githubproxy.dev.terminal.stedi.com/Stedi
9 | type: npm-registry
10 | token: ${{secrets.DEPENDABOT_PACKAGE_TOKEN}}
11 | updates:
12 | - package-ecosystem: npm
13 | directory: /
14 | schedule:
15 | interval: daily
16 | time: "07:00"
17 | ignore:
18 | registries: "*"
19 |
--------------------------------------------------------------------------------
/.github/mergify.yml:
--------------------------------------------------------------------------------
1 | # https://github.com/Stedi/renovate-config/blob/main/.mergify.yml
2 | extends: renovate-config
3 |
4 | defaults:
5 | actions:
6 | request_reviews:
7 | teams:
8 | - cloud
9 |
10 | pull_request_rules:
11 | - name: auto-approve release
12 | conditions:
13 | - author=release-please[bot]
14 | - label~=autorelease
15 | actions:
16 | review:
17 | type: APPROVE
18 | message: Automatically approving release
19 |
20 | - name: Team member approval
21 | conditions:
22 | - author=@cloud
23 | - label=auto-approve
24 | actions:
25 | review:
26 | type: APPROVE
27 | message: Auto-approving based on team member request.
--------------------------------------------------------------------------------
/.github/renovate.json5:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": ["local>Stedi/renovate-config", ":semanticCommits"],
4 | "schedule": "after 10:00 and before 16:00 every weekday",
5 | "commitMessageExtra": "from {{displayFrom}} to {{#if isPinDigest}}{{{newDigestShort}}}{{else}}{{#if isMajor}}{{prettyNewMajor}}{{else}}{{#if isSingleVersion}}{{prettyNewVersion}}{{else}}{{#if newValue}}{{{newValue}}}{{else}}{{{newDigestShort}}}{{/if}}{{/if}}{{/if}}{{/if}}",
6 | "ignorePaths": ["generated-sdk/**"]
7 | }
8 |
--------------------------------------------------------------------------------
/.github/workflows/SUBSTRATE_CODEQL.yml:
--------------------------------------------------------------------------------
1 | name: "CodeQL"
2 |
3 | on:
4 | push:
5 | branches: [main]
6 | pull_request:
7 | # The branches below must be a subset of the branches above
8 | branches: [main]
9 | schedule:
10 | - cron: "27 2 * * 1"
11 |
12 | jobs:
13 | analyze:
14 | name: Analyze
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - name: Checkout repository
19 | uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2
20 |
21 | # Initializes the CodeQL tools for scanning.
22 | - name: Initialize CodeQL
23 | uses: github/codeql-action/init@231aa2c8a89117b126725a0e11897209b7118144 # v1
24 | # If you wish to specify custom queries, you can do so here or in a config file.
25 | # By default, queries listed here will override any specified in a config file.
26 | # Prefix the list here with "+" to use these queries and those in the config file.
27 | # queries: ./path/to/local/query, your-org/your-repo/queries@main
28 |
29 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
30 | # If this step fails, then you should remove it and run the build manually (see below)
31 | - name: Autobuild
32 | uses: github/codeql-action/autobuild@231aa2c8a89117b126725a0e11897209b7118144 # v1
33 |
34 | # ℹ️ Command-line programs to run using the OS shell.
35 | # 📚 https://git.io/JvXDl
36 |
37 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
38 | # and modify them (or add more) to build your code if your project
39 | # uses a compiled language
40 |
41 | #- run: |
42 | # make bootstrap
43 | # make release
44 |
45 | - name: Perform CodeQL Analysis
46 | uses: github/codeql-action/analyze@231aa2c8a89117b126725a0e11897209b7118144 # v1
47 |
--------------------------------------------------------------------------------
/.github/workflows/commitlint.yml:
--------------------------------------------------------------------------------
1 | name: Lint Commit Messages
2 | on: [pull_request]
3 |
4 | jobs:
5 | commitlint:
6 | runs-on: ubuntu-latest
7 | steps:
8 | - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2
9 | with:
10 | fetch-depth: 0
11 | - uses: wagoid/commitlint-github-action@4b1bcb1c72f99fbd6aa6b34cc3fb59200f01f993 # v2
12 |
--------------------------------------------------------------------------------
/.github/workflows/pr-success.yml:
--------------------------------------------------------------------------------
1 | name: pr-success
2 | on:
3 | pull_request: {}
4 | merge_group:
5 | types: [ checks_requested ]
6 |
7 | jobs:
8 | pr-success:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1
12 | - name: Install Deps
13 | run: npm ci
14 | - name: Test
15 | run: npm test
16 | reviewdog:
17 | runs-on: ubuntu-latest
18 | steps:
19 | - uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1
20 | - name: Lint
21 | run: npm run lint
22 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 | on:
3 | push:
4 | branches:
5 | - main
6 | jobs:
7 | release:
8 | name: Release
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout
12 | uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2
13 | with:
14 | fetch-depth: 0
15 | - name: Setup Node.js
16 | uses: actions/setup-node@f1f314fca9dfce2769ece7d933488f076716723e # v1
17 | with:
18 | node-version: 14
19 | - name: Install dependencies
20 | run: npm ci
21 | env:
22 | GITHUB_TOKEN: ${{ secrets.ENG_GITHUB_TOKEN }}
23 | - name: Release
24 | env:
25 | GITHUB_TOKEN: ${{ secrets.ENG_GITHUB_TOKEN }}
26 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
27 | run: npm run release
28 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .history
3 | .idea
4 |
--------------------------------------------------------------------------------
/.mergify.yml:
--------------------------------------------------------------------------------
1 | pull_request_rules:
2 | - name: Dependabot
3 | conditions:
4 | - author=dependabot[bot]
5 | - status-success=Test
6 | actions:
7 | merge:
8 | method: squash
9 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 6.17.1
2 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "all",
3 | "tabWidth": 2,
4 | "semi": false,
5 | "singleQuote": false
6 | }
7 |
--------------------------------------------------------------------------------
/.releaserc.json:
--------------------------------------------------------------------------------
1 | {
2 | "branches": ["main"],
3 | "plugins": [
4 | "@semantic-release/commit-analyzer",
5 | "@semantic-release/release-notes-generator",
6 | [
7 | "@semantic-release/changelog",
8 | {
9 | "changelogFile": "CHANGELOG.md"
10 | }
11 | ],
12 | [
13 | "@semantic-release/git",
14 | {
15 | "assets": ["CHANGELOG.md"]
16 | }
17 | ],
18 | ["@semantic-release/npm"]
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [1.5.2](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/compare/v1.5.1...v1.5.2) (2022-04-20)
2 |
3 |
4 | ### Bug Fixes
5 |
6 | * allow newer versions of eslint ([773aa06](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/773aa06fdbd49bf65253b3329ec9e83394b5731f))
7 |
8 | ## [1.5.1](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/compare/v1.5.0...v1.5.1) (2020-10-30)
9 |
10 |
11 | ### Bug Fixes
12 |
13 | * fix issue with direct call expressions, add test ([#25](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/issues/25)) ([dfb63bc](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/dfb63bc71c4366cdd23cdd0b7516f1ebd416d26d))
14 |
15 | # [1.5.0](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/compare/v1.4.0...v1.5.0) (2020-10-30)
16 |
17 |
18 | ### Features
19 |
20 | * publish plugin to the [@stedi-oss](https://github.com/stedi-oss) namespace instead of [@stedi](https://github.com/stedi) ([fe0f4c8](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/fe0f4c8ab0686f400bc71ec79aa28b9c49a2fc6b))
21 |
22 | # [1.4.0](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/compare/v1.3.1...v1.4.0) (2020-10-30)
23 |
24 |
25 | ### Features
26 |
27 | * new rule no-direct-lambda-invoke ([#23](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/issues/23)) ([112c42d](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/112c42d3a6f3c0f4f7a7ecf0f0e909192a7f17b1))
28 |
29 | ## [1.3.1](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/compare/v1.3.0...v1.3.1) (2020-10-29)
30 |
31 |
32 | ### Bug Fixes
33 |
34 | * undefined case in instrument-aws-clients rule ([#21](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/issues/21)) ([fd2591a](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/fd2591ae4c67f72d059a6af3f29e37fac38436e4))
35 |
36 | # [1.3.0](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/compare/v1.2.0...v1.3.0) (2020-10-29)
37 |
38 |
39 | ### Features
40 |
41 | * extend instrumented-document-clients rule, add tests ([#19](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/issues/19)) ([abb165a](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/abb165a965676a45ba48986d823864abb0d20c38))
42 |
43 | # [1.2.0](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/compare/v1.1.2...v1.2.0) (2020-10-22)
44 |
45 |
46 | ### Features
47 |
48 | * extend instrumented-aws-clients rule to support more cases ([#16](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/issues/16)) ([0599729](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/0599729ddb0b7bd6c46d7a262432a64af4b4e24a))
49 |
50 | ## [1.1.2](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/compare/v1.1.1...v1.1.2) (2020-10-09)
51 |
52 |
53 | ### Bug Fixes
54 |
55 | * add access=public flag to npm's publishConfig ([b3c15d7](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/b3c15d7cca19f6c362e909a6d4f7552eb004b195))
56 |
57 | ## [1.1.1](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/compare/v1.1.0...v1.1.1) (2020-10-09)
58 |
59 |
60 | ### Bug Fixes
61 |
62 | * point publishConfig to npmjs ([d5aee29](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/d5aee291f6fb21d9ef9492e551bd31df5f3a49c8))
63 | * remove publishConfig.registry from package.json in order to publish to NPM ([49735b0](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/49735b0bdf86112e17302562dcf45d22caa6e268))
64 | * update secret reference ([6f820e0](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/6f820e0ad839780339ec038889f00a8e3bdf9b2d))
65 |
66 | # [1.1.0](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/compare/v1.0.0...v1.1.0) (2020-10-08)
67 |
68 |
69 | ### Features
70 |
71 | * publish to npmjs ([1c1c611](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/1c1c6111716eb9c7479f32b05ea301b452945d69))
72 |
73 | # 1.0.0 (2020-10-03)
74 |
75 |
76 | ### Bug Fixes
77 |
78 | * **build:** add .releaserc.json ([074e47d](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/074e47da97f25e232046fa6a5d6bd04ddbf8bdf0))
79 | * **release:** add .npmrc ([bfab475](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/bfab4758f0bb370d84ea4bdb26c2cb86c2ee97c0))
80 | * **release:** copy ENG_GITHUB_TOKEN to GITHUB_TOKEN ([1677469](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/1677469239dc7abf6b594cfdc19fb05c87bcd2bb))
81 | * links to supported rules ([df8ce29](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/df8ce29807ab77bed2ab047f5bd238574e9e9519))
82 | * prefix package name with stedi scope ([ba37b84](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/ba37b8452e3b79e31cc0518dcdde8ef711faa742))
83 | * release action syntax ([0b99cb8](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/0b99cb8006c6125312823c10652fb48a99fbf5ad))
84 |
85 |
86 | ### Features
87 |
88 | * add gpr-publish workflow ([e9b5c65](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/e9b5c658ac261821925e195b674cfc75d2e1842d))
89 | * add linting ([c114a69](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/c114a6969fbf2e377675a2b78cb908f5c5cc507b))
90 | * add release action ([55056d7](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/55056d7b5f3f8d5bc98285a84ee9a49ffc5fba99))
91 | * initial commit ([e43c318](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/e43c31836775e60b14666bae95a73670e2879211))
92 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # eslint-plugin-stedi-aws-rules
2 |
3 | Best practices around using AWS SDK in Javascript & Typescript projects.
4 |
5 | [](https://github.com/semantic-release/semantic-release)
6 |
7 | References:
8 |
9 | - https://pages.awscloud.com/rs/112-TZM-766/images/2020_0316-SRV_Slide-Deck.pdf
10 |
11 | ## Installation
12 |
13 | You'll first need to install [ESLint](http://eslint.org):
14 |
15 | ```
16 | $ npm i eslint --save-dev
17 | ```
18 |
19 | Next, install `@stedi-oss/eslint-plugin-stedi-aws-rules`:
20 |
21 | ```
22 | npm install @stedi-oss/eslint-plugin-stedi-aws-rules --save-dev
23 | ```
24 |
25 | ## Usage
26 |
27 | Add `stedi` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix:
28 |
29 | ```json
30 | {
31 | "plugins": ["@stedi-oss/stedi-aws-rules"]
32 | }
33 | ```
34 |
35 | Then configure the rules you want to use under the rules section.
36 |
37 | ```json
38 | {
39 | "rules": {
40 | "@stedi-oss/stedi-aws-rules/no-aws-import": "error",
41 | "@stedi-oss/stedi-aws-rules/instrument-aws-clients": "error",
42 | "@stedi-oss/stedi-aws-rules/instrument-document-clients": "error"
43 | }
44 | }
45 | ```
46 |
47 | ## Supported Rules
48 |
49 | - [@stedi-oss/stedi-aws-rules/no-aws-import](docs/rules/no-aws-import.md)
50 | - [@stedi-oss/stedi-aws-rules/instrument-aws-clients](docs/rules/instrument-aws-clients.md)
51 | - [@stedi-oss/stedi-aws-rules/instrument-document-clients](docs/rules/instrument-document-clients.md)
52 | - [@stedi-oss/stedi-aws-rules/no-direct-lambda-invoke.md](docs/rules/no-direct-lambda-invoke.md)
53 |
54 | ## Contributing
55 |
56 | As Stedi uses this for own projects, we know this might not be the perfect approach for all the projects out there. If you have any ideas, just open an issue and tell us you think.
57 |
58 | If you'd like to contribute, please fork the repository and make changes as you'd like. Pull requests are warmly welcome.
59 |
60 | ### Adding a new rule
61 |
62 | To follow our structure, when bootstraping new rule please use [generator-eslint](https://github.com/eslint/generator-eslint) to do so.
63 |
64 | Make sure you're in the top-level directory of this repo and type:
65 |
66 | ```sh
67 | $ yo eslint:rule
68 | ```
69 |
70 | ## Releases
71 |
72 | New releases are generated with each commit to the master using [semantic-release](https://github.com/semantic-release/semantic-release)
73 |
74 | ## License
75 |
76 | [MIT License](https://opensource.org/licenses/MIT) © [Stedi](https://stedi.com)
77 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = { extends: ["@commitlint/config-conventional"] }
2 |
--------------------------------------------------------------------------------
/docs/rules/instrument-aws-clients.md:
--------------------------------------------------------------------------------
1 | # Always instrument AWS SDK code with X-Ray (instrument-aws-clients)
2 |
3 | Please describe the origin of the rule here.
4 |
5 | ## Rule Details
6 |
7 | This rule aims to make sure all your AWS SDK client instances are instrumented using AWS X-Ray. This allows you to investigate which parts of your application are bottlenecks.
8 |
9 | Examples of **incorrect** code for this rule:
10 |
11 | ```js
12 | import SecretsManager from "aws-sdk/clients/secretsmanager"
13 |
14 | const ssm = new SecretsManager()
15 | ```
16 |
17 | Examples of **correct** code for this rule:
18 |
19 | ```js
20 | import SecretsManager from "aws-sdk/clients/secretsmanager"
21 |
22 | const ssm = new SecretsManager()
23 | AWSXRay.captureAWSClient(ssm)
24 | ```
25 |
26 | ## When Not To Use It
27 |
28 | Turn off this rule if you're using other instrumentation tools.
29 |
30 | ## Further Reading
31 |
32 | - [https://aws.amazon.com/xray/](https://aws.amazon.com/xray/)
33 | - [https://docs.aws.amazon.com/xray-sdk-for-nodejs/latest/reference/index.html](https://docs.aws.amazon.com/xray-sdk-for-nodejs/latest/reference/index.html)
34 | - [https://github.com/aws/aws-xray-sdk-node](https://github.com/aws/aws-xray-sdk-node)
35 | - [https://www.youtube.com/watch?v=JBOo2L4sqt8](https://www.youtube.com/watch?v=JBOo2L4sqt8)
36 |
--------------------------------------------------------------------------------
/docs/rules/instrument-document-clients.md:
--------------------------------------------------------------------------------
1 | # Always instrument DynamoDB.DocumentClient code with X-Ray (instrument-document-clients)
2 |
3 | `DocumentClient` is a special case in AWS SDK. It has to be treated differently than the rest of AWS SDK services.
4 |
5 | ## Rule Details
6 |
7 | This rule aims to make sure all your AWS DynamoDB DocumentClient instances are instrumented using AWS X-Ray. This allows you to investigate which calls to DynamoDB are bottlenecks.
8 |
9 | Examples of **incorrect** code for this rule:
10 |
11 | ```js
12 | import DynamoDB from "aws-sdk/clients/dynamodb"
13 |
14 | const dynamoClient = new DynamoDB.DocumentClient()
15 | ```
16 |
17 | Examples of **correct** code for this rule:
18 |
19 | ```js
20 | import DynamoDB from "aws-sdk/clients/dynamodb"
21 |
22 | const dynamoClient = new DynamoDB.DocumentClient()
23 | AWSXRay.captureAWSClient(dynamoClient.service)
24 | ```
25 |
26 | ## When Not To Use It
27 |
28 | Turn off this rule if you're using other instrumentation tools.
29 |
30 | ## Further Reading
31 |
32 | - [https://aws.amazon.com/xray/](https://aws.amazon.com/xray/)
33 | - [https://docs.aws.amazon.com/xray-sdk-for-nodejs/latest/reference/index.html](https://docs.aws.amazon.com/xray-sdk-for-nodejs/latest/reference/index.html)
34 | - [https://github.com/aws/aws-xray-sdk-node](https://github.com/aws/aws-xray-sdk-node)
35 | - [https://www.youtube.com/watch?v=JBOo2L4sqt8](https://www.youtube.com/watch?v=JBOo2L4sqt8)
36 |
--------------------------------------------------------------------------------
/docs/rules/no-aws-import.md:
--------------------------------------------------------------------------------
1 | # Don't import AWS directly, use clients instead. (no-aws-import)
2 |
3 | ## Rule Details
4 |
5 | This rule aims to reduce cold starts of Lambda functions by reducing the bundle size by only including relevant pieces of AWS SDK.
6 |
7 | Examples of **incorrect** code for this rule:
8 |
9 | ```js
10 | import { DynamoDB } from "aws-sdk"
11 | ```
12 |
13 | Examples of **correct** code for this rule:
14 |
15 | ```js
16 | import DynamoDB from "aws-sdk/clients/dynamodb"
17 | ```
18 |
19 | ### Options
20 |
21 | None.
22 |
23 | ## When Not To Use It
24 |
25 | Give a short description of when it would be appropriate to turn off this rule.
26 |
27 | ## Further Reading
28 |
29 | - [https://pages.awscloud.com/rs/112-TZM-766/images/2020_0316-SRV_Slide-Deck.pdf](https://pages.awscloud.com/rs/112-TZM-766/images/2020_0316-SRV_Slide-Deck.pdf)
30 | - [https://theburningmonk.com/2019/03/just-how-expensive-is-the-full-aws-sdk/](https://theburningmonk.com/2019/03/just-how-expensive-is-the-full-aws-sdk/)
31 |
--------------------------------------------------------------------------------
/docs/rules/no-direct-lambda-invoke.md:
--------------------------------------------------------------------------------
1 | # Do not invoke Lambdas directly (no-direct-lambda-invoke)
2 |
3 | ## Rule Details
4 |
5 | In most cases invoking Lambda functions directly inside Lambda functions can be considered as an antipattern.
6 |
7 | Examples of **incorrect** code for this rule:
8 |
9 | ```js
10 | new AWS.Lambda().invoke({ ... });
11 |
12 | new AWS.Lambda().invokeAsync({ ... });
13 | ```
14 |
15 | Examples of **correct** code for this rule:
16 |
17 | ```js
18 | // no such code at all
19 | ```
20 |
21 | ## When Not To Use It
22 |
23 | Turn off this rule if you're using other instrumentation tools.
24 |
25 | ## Further Reading
26 |
27 | - [https://twitter.com/benjamin_l_s/status/1310571746559496198](https://twitter.com/benjamin_l_s/status/1310571746559496198)
28 | - [https://twitter.com/brianleroux/status/1309864339889741824](https://twitter.com/brianleroux/status/1309864339889741824)
29 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview Stedi coding style
3 | * @author Rafal Wilinski
4 | */
5 | "use strict";
6 |
7 | //------------------------------------------------------------------------------
8 | // Requirements
9 | //------------------------------------------------------------------------------
10 |
11 | var requireIndex = require("requireindex");
12 |
13 | //------------------------------------------------------------------------------
14 | // Plugin Definition
15 | //------------------------------------------------------------------------------
16 |
17 |
18 | // import all rules in lib/rules
19 | module.exports.rules = requireIndex(__dirname + "/rules");
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/lib/rules/instrument-aws-clients.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview Ensure AWS services clients instances are instrumented.
3 | * @author Tyler van Hensbergen
4 | */
5 | "use strict"
6 |
7 | //------------------------------------------------------------------------------
8 | // Rule Definition
9 | //------------------------------------------------------------------------------
10 |
11 | module.exports = {
12 | meta: {
13 | type: "suggestion",
14 | docs: {
15 | description: "Ensure AWS services clients instances are instrumented.",
16 | category: "Tracing",
17 | recommended: true,
18 | },
19 | messages: {
20 | clientNotInstrumented: "AWS client not instrumented: {{client}}",
21 | },
22 |
23 | fixable: null, // or "code" or "whitespace"
24 | schema: [
25 | // fill in your schema
26 | ],
27 | },
28 |
29 | create: function (context) {
30 | const code = context.getSourceCode()
31 | let awsClients
32 | let awsClientInstances
33 |
34 | /**
35 | * Reports an AST node as a rule violation.
36 | * @param {ASTNode} node The node to report.
37 | * @param {ASTNode|undefined} data The service client instance to report, defaults to `node`
38 | * @returns {void}
39 | */
40 | function report(node, data) {
41 | data = data || node
42 | context.report({
43 | node,
44 | messageId: "clientNotInstrumented",
45 | data: { client: code.getText(data) },
46 | })
47 | }
48 |
49 | /**
50 | * Returns a variable for the current scope if exists.
51 | * @param {string} name The node to report.
52 | * @returns {Variable|undefined}
53 | */
54 | function varInScope(name) {
55 | return context.getScope().set.get(name)
56 | }
57 |
58 | return {
59 | Program: () => {
60 | awsClients = new Set()
61 | awsClientInstances = new Map()
62 | },
63 |
64 | ImportDeclaration: (node) => {
65 | if (node.source.value.startsWith("aws-sdk/clients/")) {
66 | node.specifiers.map((o) => awsClients.add(o.local.name))
67 | }
68 | },
69 |
70 | "CallExpression[callee.property.name!='captureAWSClient'][callee.object.type='NewExpression'][callee.object.callee]": (
71 | node,
72 | ) => {
73 | const name = node.callee.object.callee.name
74 | if (name && awsClients.has(name)) {
75 | report(node)
76 | }
77 | },
78 |
79 | "VariableDeclarator[init.callee]:has(NewExpression)": (node) => {
80 | const name = node.init.callee.name
81 | if (name && awsClients.has(name)) {
82 | const scopeVar = varInScope(node.id.name)
83 | awsClientInstances.set(scopeVar, node)
84 | }
85 | },
86 |
87 | "Program:exit": () => {
88 | awsClientInstances.forEach((node) => report(node))
89 | },
90 |
91 | "CallExpression[callee.object]": (node) => {
92 | const scopeVar = varInScope(node.callee.object.name)
93 | if (scopeVar && awsClientInstances.has(scopeVar)) {
94 | report(node, awsClientInstances.get(scopeVar))
95 | awsClientInstances.delete(scopeVar)
96 | }
97 | },
98 |
99 | "CallExpression[callee.property.name='captureAWSClient'][arguments.length=1][arguments.0.type=Identifier]": (
100 | node,
101 | ) => {
102 | const scopeVar = varInScope(node.arguments[0].name)
103 | if (scopeVar && awsClientInstances.has(scopeVar)) {
104 | awsClientInstances.delete(scopeVar)
105 | }
106 | },
107 | }
108 | },
109 | }
110 |
--------------------------------------------------------------------------------
/lib/rules/instrument-document-clients.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview Ensure AWS DynamoDB Document client instances are instrumented.
3 | * @author Tyler van Hensbergen
4 | */
5 | "use strict"
6 |
7 | //------------------------------------------------------------------------------
8 | // Rule Definition
9 | //------------------------------------------------------------------------------
10 |
11 | module.exports = {
12 | meta: {
13 | type: "suggestion",
14 | docs: {
15 | description:
16 | "Ensure AWS DynamoDB Document client instances are instrumented.",
17 | category: "Tracing",
18 | recommended: true,
19 | },
20 | messages: {
21 | notInstrumented: "Called {{name}} before it was instrumented.",
22 | instrumentService:
23 | "DocumentClient should be instrumented using `service` property.",
24 | },
25 | fixable: null, // or "code" or "whitespace"
26 | schema: [
27 | // fill in your schema
28 | ],
29 | },
30 |
31 | create: function (context) {
32 | let trackedVariables = new Set()
33 |
34 | /**
35 | * Returns a variable for the current scope if exists.
36 | * @param {string} name The node to report.
37 | * @returns {Variable|undefined}
38 | */
39 | function varInScope(name) {
40 | return context.getScope().set.get(name)
41 | }
42 |
43 | /**
44 | * Checks whether a variable is being tracked
45 | * @param {string} name Variable name
46 | * @returns {Boolean}
47 | */
48 | function isTracked(name) {
49 | return trackedVariables.has(varInScope(name))
50 | }
51 |
52 | function reportInstrumentService(node) {
53 | context.report({
54 | node,
55 | messageId: "instrumentService",
56 | })
57 | }
58 |
59 | function checkMemberExpression(node) {
60 | const noProperty = !node.property
61 | const wrongProperty = node.property && node.property.name !== "service"
62 |
63 | if (noProperty || wrongProperty) {
64 | reportInstrumentService(node)
65 | }
66 | }
67 |
68 | function checkIdentifier(node) {
69 | if (node.name) {
70 | reportInstrumentService(node)
71 | }
72 | }
73 |
74 | return {
75 | "VariableDeclarator > NewExpression[callee.property.name='DocumentClient']": (
76 | node,
77 | ) => {
78 | if (node.parent.id && node.parent.id.name) {
79 | trackedVariables.add(varInScope(node.parent.id.name))
80 | }
81 | },
82 |
83 | "CallExpression[callee.property.name='captureAWSClient']:has(NewExpression[callee.property.name='DocumentClient']) .arguments": (
84 | node,
85 | ) => {
86 | checkMemberExpression(node)
87 | },
88 |
89 | "CallExpression[callee.property.name='captureAWSClient'][arguments.length=1] .arguments[type!='NewExpression']": (
90 | node,
91 | ) => {
92 | const name = node.name || node.object.name
93 | if (!isTracked(name)) return
94 |
95 | switch (node.type) {
96 | case "MemberExpression":
97 | return checkMemberExpression(node)
98 | case "Identifier":
99 | return checkIdentifier(node)
100 | }
101 | },
102 |
103 | "CallExpression[callee.object.name]": (node) => {
104 | const name = node.callee.object.name
105 | if (!isTracked(name)) return
106 |
107 | context.report({
108 | node,
109 | messageId: "notInstrumented",
110 | data: { name: name },
111 | })
112 | },
113 | }
114 | },
115 | }
116 |
--------------------------------------------------------------------------------
/lib/rules/no-aws-import.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview Don't import AWS directly, use clients instead.
3 | * @author Tyler van Hensbergen
4 | */
5 | "use strict"
6 |
7 | //------------------------------------------------------------------------------
8 | // Rule Definition
9 | //------------------------------------------------------------------------------
10 |
11 | module.exports = {
12 | meta: {
13 | type: "problem",
14 |
15 | docs: {
16 | description: "Don't import AWS directly, use clients instead.",
17 | category: "Cold-start optimization",
18 | recommended: true,
19 | },
20 |
21 | messages: {
22 | directImport: "'{{modules}}' imported directly. Use clients instead.",
23 | },
24 |
25 | fixable: null, // or "code" or "whitespace"
26 | schema: [
27 | // fill in your schema
28 | ],
29 | },
30 |
31 | create: function (context) {
32 | return {
33 | ImportDeclaration: (node) => {
34 | if (node.source.value == "aws-sdk") {
35 | const modules = node.specifiers.map((o) => o.local.name).join(", ")
36 | context.report({
37 | node,
38 | messageId: "directImport",
39 | data: { modules },
40 | })
41 | }
42 | },
43 | }
44 | },
45 | }
46 |
--------------------------------------------------------------------------------
/lib/rules/no-direct-lambda-invoke.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview Do not invoke Lambdas directly
3 | * @author Marcin Jan Puhacz
4 | */
5 | "use strict"
6 |
7 | //------------------------------------------------------------------------------
8 | // Rule Definition
9 | //------------------------------------------------------------------------------
10 |
11 | module.exports = {
12 | meta: {
13 | docs: {
14 | description: "Do not invoke Lambdas directly",
15 | category: "Best practices",
16 | recommended: true,
17 | },
18 | messages: {
19 | directInvocation: "Lambdas should not be invoked directly",
20 | },
21 | },
22 |
23 | create: function (context) {
24 | let trackedVariables = new Set()
25 |
26 | /**
27 | * Returns a variable for the current scope if exists.
28 | * @param {string} name The node to report.
29 | * @returns {Variable|undefined}
30 | */
31 | function varInScope(name) {
32 | return context.getScope().set.get(name)
33 | }
34 |
35 | /**
36 | * Checks whether a variable is being tracked
37 | * @param {string} name Variable name
38 | * @returns {Boolean}
39 | */
40 | function isTracked(name) {
41 | return trackedVariables.has(varInScope(name))
42 | }
43 |
44 | function reportDirectInvocation(node) {
45 | context.report({
46 | node,
47 | messageId: "directInvocation",
48 | })
49 | }
50 |
51 | return {
52 | "VariableDeclarator > NewExpression[callee.property.name='Lambda']": (
53 | node,
54 | ) => {
55 | if (node.parent.id && node.parent.id.name) {
56 | trackedVariables.add(varInScope(node.parent.id.name))
57 | }
58 | },
59 |
60 | "CallExpression[callee.property.type='Identifier'][callee.property.name=/^invoke$|^invokeAsync$/][callee.object.type='Identifier']": (
61 | node,
62 | ) => {
63 | if (isTracked(node.callee.object.name)) reportDirectInvocation(node)
64 | },
65 |
66 | "CallExpression[callee.property.type='Identifier'][callee.property.name=/^invoke$|^invokeAsync$/] NewExpression[callee.property.name='Lambda']": (
67 | node,
68 | ) => {
69 | reportDirectInvocation(node)
70 | },
71 |
72 | "CallExpression[callee.property.type='Identifier'][callee.property.name=/^invoke$|^invokeAsync$/] NewExpression[callee.name='Lambda']": (
73 | node,
74 | ) => {
75 | reportDirectInvocation(node)
76 | },
77 | }
78 | },
79 | }
80 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@stedi-oss/eslint-plugin-stedi-aws-rules",
3 | "version": "0.0.1",
4 | "description": "AWS coding best practices by Stedi",
5 | "keywords": [
6 | "eslint",
7 | "eslintplugin",
8 | "eslint-plugin",
9 | "aws",
10 | "rules"
11 | ],
12 | "author": "Stedi (https://stedi.com/)",
13 | "main": "lib/index.js",
14 | "files": [
15 | "index.js",
16 | "lib"
17 | ],
18 | "scripts": {
19 | "test": "npx mocha tests --recursive",
20 | "lint": "npx eslint .",
21 | "release": "semantic-release"
22 | },
23 | "dependencies": {
24 | "requireindex": "~1.2.0"
25 | },
26 | "peerDependencies": {
27 | "eslint": ">=7.0.0"
28 | },
29 | "devDependencies": {
30 | "@commitlint/cli": "^16.2.3",
31 | "@commitlint/config-conventional": "^16.2.1",
32 | "@semantic-release/changelog": "^6.0.1",
33 | "@semantic-release/git": "^10.0.1",
34 | "eslint": "^8.13.0",
35 | "husky": "^7.0.4",
36 | "mocha": "^9.2.2",
37 | "npm-check-updates": "^12.5.9",
38 | "semantic-release": "^19.0.2"
39 | },
40 | "license": "MIT",
41 | "publishConfig": {
42 | "registry": "https://registry.npmjs.org/",
43 | "access": "public"
44 | },
45 | "config": {
46 | "commitizen": {
47 | "path": "./node_modules/cz-conventional-changelog"
48 | }
49 | },
50 | "husky": {
51 | "hooks": {
52 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/tests/lib/rules/instrument-aws-clients.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview Always instrument AWS SDK code with X-Ray
3 | * @author Tyler van Hensbergen
4 | */
5 | "use strict"
6 |
7 | //------------------------------------------------------------------------------
8 | // Requirements
9 | //------------------------------------------------------------------------------
10 |
11 | var rule = require("../../../lib/rules/instrument-aws-clients"),
12 | RuleTester = require("eslint").RuleTester
13 |
14 | //------------------------------------------------------------------------------
15 | // Tests
16 | //------------------------------------------------------------------------------
17 |
18 | var ruleTester = new RuleTester({
19 | parserOptions: {
20 | ecmaVersion: 12,
21 | sourceType: "module",
22 | },
23 | })
24 |
25 | ruleTester.run("instrument-aws-clients", rule, {
26 | valid: [
27 | "import SecretsManager from 'aws-sdk/clients/secretsmanager'\n" +
28 | "const ssm = new SecretsManager()\n" +
29 | "AWSXRay.captureAWSClient(ssm)",
30 |
31 | "import { SecretsManager, DynamoDB } from 'aws-sdk/clients/secretsmanager'\n" +
32 | "let ddb = new DynamoDB()\n" +
33 | "AWSXRay.captureAWSClient(ddb)\n" +
34 | "AWSXRay.captureAWSClient(new SecretsManager())",
35 |
36 | "import S3 from 'aws-sdk/clients/s3'\n" +
37 | "async function fn() { await AWSXRay.captureAWSClient(new S3()).getObject({}) }",
38 | ],
39 |
40 | invalid: [
41 | {
42 | code:
43 | "import SecretsManager from 'aws-sdk/clients/secretsmanager'\n" +
44 | "const sm = new SecretsManager()",
45 | errors: [
46 | {
47 | messageId: "clientNotInstrumented",
48 | data: { client: "sm = new SecretsManager()" },
49 | },
50 | ],
51 | },
52 |
53 | {
54 | code:
55 | "import S3 from 'aws-sdk/clients/s3'\n" +
56 | "async function fn() { await new S3().getObject({}) }",
57 | errors: [
58 | {
59 | messageId: "clientNotInstrumented",
60 | data: { client: "new S3().getObject({})" },
61 | },
62 | ],
63 | },
64 |
65 | {
66 | code:
67 | "import SecretsManager from 'aws-sdk/clients/secretsmanager'\n" +
68 | "const sm = new SecretsManager().cancelRotateSecret()",
69 | errors: [
70 | {
71 | messageId: "clientNotInstrumented",
72 | data: { client: "new SecretsManager().cancelRotateSecret()" },
73 | },
74 | ],
75 | },
76 |
77 | {
78 | code:
79 | "import SecretsManager from 'aws-sdk/clients/secretsmanager'\n" +
80 | "var ssm = new SecretsManager()\n" +
81 | "function test() {\n" +
82 | " const ssm = new SecretsManager()\n" +
83 | " AWSXRay.captureAWSClient(ssm)\n" +
84 | "}\n" +
85 | "ssm.cancelRotateSecret()",
86 | errors: [
87 | {
88 | messageId: "clientNotInstrumented",
89 | data: { client: "ssm = new SecretsManager()" },
90 | },
91 | ],
92 | },
93 |
94 | {
95 | code:
96 | "import SecretsManager from 'aws-sdk/clients/secretsmanager'\n" +
97 | "const ssm = new SecretsManager()\n" +
98 | "ssm.cancelRotateSecret()\n" +
99 | "AWSXRay.captureAWSClient(ssm)",
100 | errors: [
101 | {
102 | messageId: "clientNotInstrumented",
103 | data: { client: "ssm = new SecretsManager()" },
104 | },
105 | ],
106 | },
107 | ],
108 | })
109 |
--------------------------------------------------------------------------------
/tests/lib/rules/instrument-document-clients.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview Always instrument DynamoDB.DocumentClient code with X-Ray
3 | * @author Tyler van Hensbergen
4 | */
5 | "use strict"
6 |
7 | //------------------------------------------------------------------------------
8 | // Requirements
9 | //------------------------------------------------------------------------------
10 |
11 | var rule = require("../../../lib/rules/instrument-document-clients"),
12 | RuleTester = require("eslint").RuleTester
13 |
14 | //------------------------------------------------------------------------------
15 | // Tests
16 | //------------------------------------------------------------------------------
17 |
18 | var ruleTester = new RuleTester({
19 | parserOptions: {
20 | ecmaVersion: 12,
21 | sourceType: "module",
22 | },
23 | })
24 | ruleTester.run("instrument-document-clients", rule, {
25 | valid: [
26 | "const dynamoClient = new DynamoDB.DocumentClient()\n" +
27 | "let ddb = AWSXRay.captureAWSClient(dynamoClient.service)\n" +
28 | "ddb.scan()",
29 | "let ddb = AWSXRay.captureAWSClient((new DynamoDB.DocumentClient()).service)\n" +
30 | "ddb.scan()",
31 | ],
32 |
33 | invalid: [
34 | {
35 | code:
36 | "const dynamoClient = new DynamoDB.DocumentClient()\n" +
37 | "let ddb = AWSXRay.captureAWSClient(dynamoClient.wrong)\n" +
38 | "ddb.scan()",
39 | errors: [{ messageId: "instrumentService" }],
40 | },
41 | {
42 | code:
43 | "const dynamoClient = new DynamoDB.DocumentClient()\n" +
44 | "let ddb = AWSXRay.captureAWSClient(dynamoClient)\n" +
45 | "ddb.scan()",
46 | errors: [{ messageId: "instrumentService" }],
47 | },
48 | {
49 | code: "const ddb = new DynamoDB.DocumentClient(); ddb.scan()",
50 | errors: [{ messageId: "notInstrumented", data: { name: "ddb" } }],
51 | },
52 | {
53 | code:
54 | "const ddb = AWSXRay.captureAWSClient(new DynamoDB.DocumentClient()); ddb.scan()",
55 | errors: [{ messageId: "instrumentService" }],
56 | },
57 | ],
58 | })
59 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-aws-import.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview Don't import AWS directly, use clients instead.
3 | * @author Tyler van Hensbergen
4 | */
5 | "use strict"
6 |
7 | //------------------------------------------------------------------------------
8 | // Requirements
9 | //------------------------------------------------------------------------------
10 |
11 | var rule = require("../../../lib/rules/no-aws-import"),
12 | RuleTester = require("eslint").RuleTester
13 |
14 | //------------------------------------------------------------------------------
15 | // Tests
16 | //------------------------------------------------------------------------------
17 |
18 | var ruleTester = new RuleTester({
19 | parserOptions: {
20 | ecmaVersion: 12,
21 | sourceType: "module",
22 | },
23 | })
24 | ruleTester.run("no-aws-import", rule, {
25 | valid: [
26 | {
27 | code: "import { DynamoDB } from 'aws-sdk/clients/dynamodb'",
28 | },
29 | {
30 | code: "const DynamoDB = require('aws-sdk/clients/dynamodb')",
31 | },
32 | ],
33 |
34 | invalid: [
35 | {
36 | code: 'import { S3 } from "aws-sdk"',
37 | errors: [{ messageId: "directImport", data: { modules: "S3" } }],
38 | },
39 | {
40 | code: "import { S3, DynamoDB } from 'aws-sdk'",
41 | errors: [
42 | { messageId: "directImport", data: { modules: "S3, DynamoDB" } },
43 | ],
44 | },
45 | ],
46 | })
47 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-direct-lambda-invoke.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview Do not invoke Lambdas directly
3 | * @author Marcin Jan Puhacz
4 | */
5 | "use strict"
6 |
7 | //------------------------------------------------------------------------------
8 | // Requirements
9 | //------------------------------------------------------------------------------
10 |
11 | var rule = require("../../../lib/rules/no-direct-lambda-invoke"),
12 | RuleTester = require("eslint").RuleTester
13 |
14 | //------------------------------------------------------------------------------
15 | // Tests
16 | //------------------------------------------------------------------------------
17 |
18 | var ruleTester = new RuleTester({
19 | parserOptions: {
20 | ecmaVersion: 12,
21 | sourceType: "module",
22 | },
23 | })
24 | ruleTester.run("no-direct-lambda-invoke", rule, {
25 | valid: [
26 | "new SomeClass().invoke({})",
27 | "let obj = new SomeClass(); obj.invoke()",
28 | "let obj = new SomeClass(); obj.invokeAsync()",
29 | ],
30 |
31 | invalid: [
32 | {
33 | code: "new Lambda().invoke({});",
34 | errors: [{ messageId: "directInvocation" }],
35 | },
36 | {
37 | code: "new AWS.Lambda().invoke({});",
38 | errors: [{ messageId: "directInvocation" }],
39 | },
40 | {
41 | code: "let lbd = new AWS.Lambda(); lbd.invoke()",
42 | errors: [{ messageId: "directInvocation" }],
43 | },
44 | {
45 | code: "let lbd = new AWS.Lambda(); lbd.invokeAsync()",
46 | errors: [{ messageId: "directInvocation" }],
47 | },
48 | ],
49 | })
50 |
--------------------------------------------------------------------------------