ESLint plugin for AWS CDK.
# npm
npm install -D @nigg/eslint-plugin-cdk
# yarn
yarn add -D @nigg/eslint-plugin-cdk
# pnpm
pnpm install -D @nigg/eslint-plugin-cdk
// eslint.config.mjs
import eslintPluginCdk from "@nigg/eslint-plugin-cdk";
export default [
{
plugins: {
cdk: eslintPluginCdk,
},
rules: {
...eslintPluginCdk.configs.recommended.rules,
},
},
];
// eslint.config.mjs
import eslintPluginCdk from "@nigg/eslint-plugin-cdk";
export default [
{
plugins: {
cdk: eslintPluginCdk,
},
rules: {
...eslintPluginCdk.configs.recommended.rules,
"cdk/no-public-class-fields": "warn",
},
},
];
This rule enforces PascalCase for construct IDs.
const bucket = new Bucket(this, "MyBucket");
const bucket = new Bucket(this, "myBucket");
This rule disallows using the parent class name as the construct IDs.
It is not good to specify a string that matches the parent class name for construct ID, as it makes the CloudFormation resource hierarchy unclear.
export class MyConstruct extends Construct {
constructor(scope: Construct, id: string) {
super(scope, id);
const bucket = new Bucket(this, "MyBucket");
}
}
export class MyConstruct extends Construct {
constructor(scope: Construct, id: string) {
super(scope, id);
const bucket = new Bucket(this, "MyConstruct");
}
}
This rule is to disallow using the Construct
or Stack
suffix in construct IDs and stack IDs.
If the Construct ID includes "Construct," the issues that should be stopped in the CDK world will leak into the CloudFormation template and the AWS world, so not good.(the same for Stack ID )
export class MyConstruct extends Construct {
constructor(scope: Construct, id: string) {
super(scope, id);
const bucket = new Bucket(this, "MyBucket");
}
}
export class MyConstruct extends Construct {
constructor(scope: Construct, id: string) {
super(scope, id);
const bucket = new Bucket(this, "BucketConstruct");
}
}
This rule disallows using class types in interface properties.
When class types are used in interface properties, it creates tight coupling between the interface and the class implementation.
Additionally, classes are mutable by nature, which can lead to unexpected behavior when used as interface property types.
So not good.
import { IBucket } from "aws-cdk-lib/aws-s3";
interface MyConstructProps {
bucket: IBucket;
}
import { Bucket } from "aws-cdk-lib/aws-s3";
interface MyConstructProps {
bucket: Bucket;
}
This rule disallows using class types for public class fields.
When class types are used in public fields, it creates tight coupling and exposes mutable state, so not good.
import { IBucket } from "aws-cdk-lib/aws-s3";
class MyConstruct extends Construct {
public readonly bucket: IBucket;
constructor(scope: Construct, id: string) {
super(scope, id);
this.bucket = new Bucket(this, "MyBucket");
}
}
import { Bucket } from "aws-cdk-lib/aws-s3";
class MyConstruct extends Construct {
public readonly bucket: Bucket;
constructor(scope: Construct, id: string) {
super(scope, id);
this.bucket = new Bucket(this, "MyBucket");
}
}
This rule disallows importing modules from private
directories at different hierarchical levels.
Note: This rule is not included in the recommended
rules.
When setting it, you need to write the following:
// eslint.config.mjs
import eslintPluginCdk from "@nigg/eslint-plugin-cdk";
export default [
{
plugins: {
cdk: eslintPluginCdk,
},
rules: {
...cdkPlugin.configs.recommended.rules,
"cdk/no-import-private": "error",
},
},
];
The private directory is intended to contain internal implementation that should only be used within its parent directory.
By disallowing imports from a different hierarchy, it promotes proper modularization and encapsulation.
// src/constructs/my-construct.ts
import { MyConstruct } from "./private/my-construct";
// src/constructs/my-construct.ts
import { MyConstruct } from "../private/my-construct";
import { MyConstruct } from "../my-app/private/my-construct";
If you have any requests or suggestions, please open an issue.