From cb2b3349f040deb6ccd8afcb4586f64415d3dd6a Mon Sep 17 00:00:00 2001 From: shivlaks <32604953+shivlaks@users.noreply.github.com> Date: Fri, 31 May 2019 06:49:19 -0700 Subject: [PATCH] refactor: Construct props must not use the 'any' type (awslint:props-no-any) (#2701) Adds a new awslint:props-no-any rule which validates that props do not use the "any" type. This is in accordance with the new AWS Construct Library guidelines. BREAKING CHANGE: * SNS - Subscription `endpoint` is now type `string` (previously `any`) * Step Functions - `result` in the Pass state is now type `map` (previously `any`) **Fixes #2673** --- packages/@aws-cdk/aws-sns/lib/subscription.ts | 2 +- .../aws-stepfunctions/lib/states/pass.ts | 2 +- packages/@aws-cdk/cdk/package.json | 3 ++ packages/@aws-cdk/runtime-values/package.json | 5 +++ tools/awslint/lib/rules/construct.ts | 38 +++++++++++++------ 5 files changed, 37 insertions(+), 13 deletions(-) diff --git a/packages/@aws-cdk/aws-sns/lib/subscription.ts b/packages/@aws-cdk/aws-sns/lib/subscription.ts index 93efac028d294..184227aac4b90 100644 --- a/packages/@aws-cdk/aws-sns/lib/subscription.ts +++ b/packages/@aws-cdk/aws-sns/lib/subscription.ts @@ -16,7 +16,7 @@ export interface SubscriptionProps { * * The meaning of this value depends on the value for 'protocol'. */ - readonly endpoint: any; + readonly endpoint: string; /** * The topic to subscribe to. diff --git a/packages/@aws-cdk/aws-stepfunctions/lib/states/pass.ts b/packages/@aws-cdk/aws-stepfunctions/lib/states/pass.ts index 70e4eee290f0d..4bb97d4374f39 100644 --- a/packages/@aws-cdk/aws-stepfunctions/lib/states/pass.ts +++ b/packages/@aws-cdk/aws-stepfunctions/lib/states/pass.ts @@ -51,7 +51,7 @@ export interface PassProps { * * @default No injected result */ - readonly result?: any; + readonly result?: {[key: string]: any}; } /** diff --git a/packages/@aws-cdk/cdk/package.json b/packages/@aws-cdk/cdk/package.json index 47d514b7b1bc3..542fb3a61b6ca 100644 --- a/packages/@aws-cdk/cdk/package.json +++ b/packages/@aws-cdk/cdk/package.json @@ -36,6 +36,9 @@ "construct-ctor:@aws-cdk/cdk.App.", "construct-ctor:@aws-cdk/cdk.Root.", "construct-ctor:@aws-cdk/cdk.Stack..params*", + "props-no-any:@aws-cdk/cdk.CfnOutputProps.value", + "props-no-any:@aws-cdk/cdk.CfnParameterProps.default", + "props-no-any:@aws-cdk/cdk.CfnResourceProps.properties", "props-no-cfn-types:@aws-cdk/cdk.CfnOutputProps*", "props-no-cfn-types:@aws-cdk/cdk.StringListCfnOutputProps*" ] diff --git a/packages/@aws-cdk/runtime-values/package.json b/packages/@aws-cdk/runtime-values/package.json index 439c71b0bd410..4a30f275eb9a1 100644 --- a/packages/@aws-cdk/runtime-values/package.json +++ b/packages/@aws-cdk/runtime-values/package.json @@ -76,5 +76,10 @@ }, "engines": { "node": ">= 8.10.0" + }, + "awslint": { + "exclude": [ + "props-no-any:@aws-cdk/runtime-values.RuntimeValueProps.value" + ] } } \ No newline at end of file diff --git a/tools/awslint/lib/rules/construct.ts b/tools/awslint/lib/rules/construct.ts index 6329ad133bb4d..341b005bdfa4b 100644 --- a/tools/awslint/lib/rules/construct.ts +++ b/tools/awslint/lib/rules/construct.ts @@ -189,12 +189,12 @@ constructLinter.add({ constructLinter.add({ code: 'props-no-unions', - message: 'props should not use TypeScript unions', + message: 'props must not use TypeScript unions', eval: e => { if (!e.ctx.propsType) { return; } if (!e.ctx.hasPropsArgument) { return; } - // this rule only applies to L2 constructs + // this rule does not apply to L1 constructs if (CoreTypes.isCfnResource(e.ctx.classType)) { return; } for (const property of e.ctx.propsType.ownProperties) { @@ -205,12 +205,12 @@ constructLinter.add({ constructLinter.add({ code: 'props-no-arn-refs', - message: 'props should use strong types instead of attributes. props should not have "arn" suffix', + message: 'props must use strong types instead of attributes. props should not have "arn" suffix', eval: e => { if (!e.ctx.propsType) { return; } if (!e.ctx.hasPropsArgument) { return; } - // this rule only applies to L2 constructs + // this rule does not apply to L1 constructs if (CoreTypes.isCfnResource(e.ctx.classType)) { return; } for (const property of e.ctx.propsType.ownProperties) { @@ -221,12 +221,12 @@ constructLinter.add({ constructLinter.add({ code: 'props-no-tokens', - message: 'props should not use the "Token" type', + message: 'props must not use the "Token" type', eval: e => { if (!e.ctx.propsType) { return; } if (!e.ctx.hasPropsArgument) { return; } - // this rule only applies to L2 constructs + // this rule does not apply to L1 constructs if (CoreTypes.isCfnResource(e.ctx.classType)) { return; } for (const property of e.ctx.propsType.allProperties) { @@ -242,12 +242,12 @@ constructLinter.add({ constructLinter.add({ code: 'props-no-cfn-types', - message: 'props should not expose L1 types (types which start with "Cfn")', + message: 'props must not expose L1 types (types which start with "Cfn")', eval: e => { if (!e.ctx.propsType) { return; } if (!e.ctx.hasPropsArgument) { return; } - // this rule only applies to L2 constructs + // this rule does not apply to L1 constructs if (CoreTypes.isCfnResource(e.ctx.classType)) { return; } for (const property of e.ctx.propsType.ownProperties) { @@ -263,12 +263,12 @@ constructLinter.add({ constructLinter.add({ code: 'props-default-doc', - message: 'All optional props should have @default documentation', + message: 'All optional props must have @default documentation', eval: e => { if (!e.ctx.propsType) { return; } if (!e.ctx.hasPropsArgument) { return; } - // this rule only applies to L2 constructs + // this rule does not apply to L1 constructs if (CoreTypes.isCfnResource(e.ctx.classType)) { return; } for (const property of e.ctx.propsType.allProperties) { @@ -276,4 +276,20 @@ constructLinter.add({ e.assert(property.docs.docs.default !== undefined, `${e.ctx.propsFqn}.${property.name}`); } } - }); \ No newline at end of file + }); + +constructLinter.add({ + code: 'props-no-any', + message: 'props must not use Typescript "any" type', + eval: e => { + if (!e.ctx.propsType) { return; } + if (!e.ctx.hasPropsArgument) { return; } + + // this rule does not apply to L1 constructs + if (CoreTypes.isCfnResource(e.ctx.classType)) { return; } + + for (const property of e.ctx.propsType.ownProperties) { + e.assert(!property.type.isAny, `${e.ctx.propsFqn}.${property.name}`); + } + } +}); \ No newline at end of file