Skip to content

Conversation

@jpolavar
Copy link
Contributor

@jpolavar jpolavar commented Oct 7, 2025

Closes #135

@jpolavar jpolavar self-assigned this Oct 7, 2025
Copilot AI review requested due to automatic review settings October 7, 2025 17:45
@jpolavar jpolavar added the MINOR label Oct 7, 2025
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a new ESLint rule 'require-aws-bare-bones' that enforces the use of bare-bones AWS SDK v3 client patterns (Client + Command) instead of aggregated clients to improve tree-shaking and reduce bundle size.

  • Added a new ESLint rule that detects and prevents imports of aggregated AWS SDK v3 clients
  • Integrated the rule into the plugin's configuration and rule exports
  • Created comprehensive test coverage for valid and invalid usage patterns

Reviewed Changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/require-aws-bare-bones.ts Implements the core rule logic to detect aggregated AWS SDK client imports
src/require-aws-bare-bones.spec.ts Provides comprehensive test cases for both valid and invalid usage patterns
src/index.ts Integrates the new rule into the plugin's rule registry and configurations
package.json Updates version number to reflect the new rule addition
docs/rules/require-aws-bare-bones.md Documents the rule with examples of correct and incorrect usage

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 22 to 25
import { DynamoDB } from '@aws-sdk/client-dynamodb';

const ddb = new DynamoDB({});
await ddb.putItem({});
Copy link

Copilot AI Oct 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation shows incorrect 'Pass' example. This code imports the aggregated DynamoDB client which should fail according to the rule. It should be 'import { DynamoDBClient, PutItemCommand }' instead.

Suggested change
import { DynamoDB } from '@aws-sdk/client-dynamodb';
const ddb = new DynamoDB({});
await ddb.putItem({});
import { DynamoDBClient, PutItemCommand } from '@aws-sdk/client-dynamodb';
const ddb = new DynamoDBClient({});
await ddb.send(new PutItemCommand({}));

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings October 7, 2025 18:02
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 6 out of 7 changed files in this pull request and generated 3 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

// require-aws-bare-bones.ts

import { AST_NODE_TYPES, ESLintUtils, TSESTree } from '@typescript-eslint/utils';
import getDocumentationUrl from './get-documentation-url.ts';
Copy link

Copilot AI Oct 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import statement includes a .ts extension which is not typically needed in TypeScript imports and may cause issues with module resolution in some environments.

Suggested change
import getDocumentationUrl from './get-documentation-url.ts';
import getDocumentationUrl from './get-documentation-url';

Copilot uses AI. Check for mistakes.
// require-aws-bare-bones.spec.ts

import rule, { MESSAGE_ID_AGGREGATED_CLIENT, ruleId } from './require-aws-bare-bones.ts';
import createTester from './ts-tester.test.ts';
Copy link

Copilot AI Oct 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import statements include .ts extensions which are not typically needed in TypeScript imports and may cause issues with module resolution in some environments.

Suggested change
import createTester from './ts-tester.test.ts';
import createTester from './ts-tester.test';

Copilot uses AI. Check for mistakes.
src/index.ts Outdated
ruleId as requireServiceCallResponseDeclarationRuleId,
} from './require-service-call-response-declaration.ts';
import requireAwsConfig, { ruleId as requireAwsConfigRuleId } from './require-aws-config.ts';
import requireAWSBareBones, { ruleId as requireAWSBareBonesRuleId } from './require-aws-bare-bones.ts';
Copy link

Copilot AI Oct 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import statement includes a .ts extension which is not typically needed in TypeScript imports and may cause issues with module resolution in some environments.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We always use .ts extension targeting ESM output in TypeScript

@jpolavar jpolavar requested review from carlansley and le-cong October 7, 2025 18:10
@jpolavar jpolavar marked this pull request as draft October 7, 2025 18:32
Copilot AI review requested due to automatic review settings October 7, 2025 18:53
@jpolavar jpolavar marked this pull request as ready for review October 7, 2025 18:53
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 6 out of 7 changed files in this pull request and generated no new comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@jpolavar
Copy link
Contributor Author

jpolavar commented Oct 7, 2025

Tested with internal services

Copy link
Contributor

@carlansley carlansley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a merge conflict. Also, how does this relate to @le-cong's PR #134? No overlap?

@jpolavar
Copy link
Contributor Author

There is a merge conflict. Also, how does this relate to @le-cong's PR #134? No overlap?

There should be no direct overlap: one is about import patterns, the other about configuration usage.
require-aws-bare-bones enforces using the bare-bones AWS SDK v3 pattern (Client + Command), preventing imports of aggregated clients.
require-aws-config likely enforces correct usage or presence of AWS SDK configuration (e.g., requiring explicit config when instantiating clients).

@jpolavar jpolavar requested a review from carlansley October 14, 2025 21:55
run: npm install -g npm@11.4.2
- name: Install Dependencies
run: npm ci --ignore-scripts
run: npm ci
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason "--ignore-scripts" is removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

publish beta fails Error: The package "@esbuild/linux-x64" could not be found, and is needed by esbuild. npm ci is allowing this binary to be installed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we were able to keep ignore-scripts in other repos though, are you sure that we have to remove it?

Copy link
Contributor Author

@jpolavar jpolavar Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rolled back this change

Copilot AI review requested due to automatic review settings October 15, 2025 17:05
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 9 out of 10 changed files in this pull request and generated 3 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

},
messages: {
[MESSAGE_ID_AGGREGATED_CLIENT]:
'Do not import aggregated AWS SDK v3 client "{{clientName}}". Use bare-bones pattern ({{clientName}}Client + Command) instead.',
Copy link

Copilot AI Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The message assumes the bare-bones client name is always {{clientName}}Client, which is incorrect for services like StepFunctions (actual client is SFNClient). Rephrase to a generic instruction (e.g., 'Use the service-specific *Client class plus Command classes') or add logic to derive/display the correct client name for known exceptions.

Suggested change
'Do not import aggregated AWS SDK v3 client "{{clientName}}". Use bare-bones pattern ({{clientName}}Client + Command) instead.',
'Do not import aggregated AWS SDK v3 client "{{clientName}}". Use the service-specific *Client class plus Command classes instead.',

Copilot uses AI. Check for mistakes.
Comment on lines 47 to 52
const isException = specifier.local.name.endsWith('Exception');

if (
specifier.type === AST_NODE_TYPES.ImportSpecifier &&
!isTypeImport &&
!isException &&
Copy link

Copilot AI Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The isException guard is redundant because names ending with 'Exception' already satisfy BARE_BONES_SUFFIXES and make isAggregatedClient return false. You can remove isException and its check to simplify the condition.

Suggested change
const isException = specifier.local.name.endsWith('Exception');
if (
specifier.type === AST_NODE_TYPES.ImportSpecifier &&
!isTypeImport &&
!isException &&
if (
specifier.type === AST_NODE_TYPES.ImportSpecifier &&
!isTypeImport &&

Copilot uses AI. Check for mistakes.
Comment on lines 1 to 3
# Enforce Bare-Bones AWS SDK v3 Client Usage

Ensure that only bare-bones AWS SDK v3 clients and commands are imported and used. Importing and using aggregated clients (e.g., `S3`, `DynamoDB`) is disallowed to promote modularization and enable better tree-shaking for reduced bundle size.
Copy link

Copilot AI Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider adding an example for a service where the bare-bones client name differs from the aggregated name (e.g., aggregated StepFunctions vs SFNClient) to clarify that the pattern is not always AggregatedName + Client.

Copilot uses AI. Check for mistakes.
@jpolavar jpolavar requested a review from le-cong October 15, 2025 17:15

function isAwsSdkClientModule(importDeclaration: TSESTree.ImportDeclaration): boolean {
return (
typeof importDeclaration.source.value === 'string' && importDeclaration.source.value.startsWith('@aws-sdk/client-')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we handle document related stuff from "@aws-sdk/lib-*" as well? e.g. DynamoDBDocument from '@aws-sdk/lib-dynamodb'


for (const specifier of node.specifiers) {
const isTypeImport = specifier.type === AST_NODE_TYPES.ImportSpecifier && specifier.importKind === 'type';
const isException = specifier.local.name.endsWith('Exception');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it duplicated with the above regexp?

run: npm install -g npm@11.4.2
- name: Install Dependencies
run: npm ci --ignore-scripts
run: npm ci
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we were able to keep ignore-scripts in other repos though, are you sure that we have to remove it?

@jpolavar jpolavar requested review from Copilot and le-cong October 15, 2025 23:13
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated 5 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 49 to 51
[MESSAGE_ID_AGGREGATED_CLIENT]:
'Do not import aggregated AWS SDK v3 client "{{clientName}}". Use bare-bones pattern ({{clientName}}Client/ Lib plus Command) instead.',
},
Copy link

Copilot AI Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The message suggests constructing {{clientName}}Client, which is incorrect for aggregated lib imports like DynamoDBDocument (correct base is DynamoDBClient). Also the fragment 'Client/ Lib' has an extra space and slash formatting issue. Recommend computing a baseClientName (derived from importSource) and changing the message to: 'Do not import aggregated AWS SDK v3 client "{{clientName}}". Use bare-bones pattern ({{baseClientName}}Client plus Command) instead.' Add baseClientName to data when reporting and remove the malformed 'Client/ Lib' formatting.

Copilot uses AI. Check for mistakes.
Comment on lines 90 to 95
code: `import { DynamoDBDocumentClient, PutCommand } from '@aws-sdk/lib-dynamodb';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import awsConfig from '@checkdigit/aws-config';
const dynamo = awsConfig(DynamoDBClient, { qualifier, environment });
const dynamoDocument = DynamoDBDocument.from(dynamo);
await dynamoDocument.send(new PutCommand({ TableName: 'foo', Item: { id: 1 } }));`,
Copy link

Copilot AI Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The snippet uses DynamoDBDocument.from but never imports DynamoDBDocument; instead it imports DynamoDBDocumentClient which is unused. This would produce an undefined reference. Replace DynamoDBDocumentClient with DynamoDBDocument in the import or change usage to DynamoDBDocumentClient.from if that API is intended.

Copilot uses AI. Check for mistakes.
Comment on lines 46 to 50
'Disallow importing aggregated AWS SDK v3 clients. Use bare-bones pattern (Client/Lib plus Command) for better tree-shaking.',
},
messages: {
[MESSAGE_ID_AGGREGATED_CLIENT]:
'Do not import aggregated AWS SDK v3 client "{{clientName}}". Use bare-bones pattern ({{clientName}}Client/ Lib plus Command) instead.',
Copy link

Copilot AI Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Description uses 'Client/Lib plus Command'; consider clarifying to 'Client (e.g., S3Client) plus specific Command(s)' to improve precision and remove the slash ambiguity.

Suggested change
'Disallow importing aggregated AWS SDK v3 clients. Use bare-bones pattern (Client/Lib plus Command) for better tree-shaking.',
},
messages: {
[MESSAGE_ID_AGGREGATED_CLIENT]:
'Do not import aggregated AWS SDK v3 client "{{clientName}}". Use bare-bones pattern ({{clientName}}Client/ Lib plus Command) instead.',
'Disallow importing aggregated AWS SDK v3 clients. Use bare-bones pattern (Client (e.g., S3Client) plus specific Command(s)) for better tree-shaking.',
},
messages: {
[MESSAGE_ID_AGGREGATED_CLIENT]:
'Do not import aggregated AWS SDK v3 client "{{clientName}}". Use bare-bones pattern ({{clientName}}Client (e.g., S3Client) plus specific Command(s)) instead.',

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@le-cong le-cong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a minor comment

return !endsWithAnySuffix(name, BARE_BONES_SUFFIXES);
}
if (importSource.startsWith(AWS_SDK_LIB)) {
const pkg = importSource.replace(AWS_SDK_LIB, '');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should BARE_BONES_SUFFIXES be checked for lib-* stuff as well?
btw the naming pattern matching for lib stuff feels a bit tricky, but hopefully it's good enough to cover what we normally use.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya pretty much it should be good for the ones we use, else we can extend to have other usages as well

@jpolavar jpolavar requested review from Copilot and le-cong October 16, 2025 14:57
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated 1 comment.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 90 to 95
code: `import { DynamoDBDocumentClient, PutCommand } from '@aws-sdk/lib-dynamodb';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import awsConfig from '@checkdigit/aws-config';
const dynamo = awsConfig(DynamoDBClient, { qualifier, environment });
const dynamoDocument = DynamoDBDocument.from(dynamo);
await dynamoDocument.send(new PutCommand({ TableName: 'foo', Item: { id: 1 } }));`,
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uses DynamoDBDocument without importing it (only DynamoDBDocumentClient is imported); update import to include DynamoDBDocument or change usage to DynamoDBDocumentClient.from to avoid an unresolved identifier.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@le-cong le-cong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hate to agree with some unsolved AI comments, otherwise lgtm

@jpolavar
Copy link
Contributor Author

hate to agree with some unsolved AI comments, otherwise lgtm

some of them are outdated and others are mostly pointing to spec file

@jpolavar jpolavar requested a review from le-cong October 16, 2025 16:08
@github-actions
Copy link

Beta Published - Install Command: npm install @checkdigit/eslint-plugin@7.17.0-PR.137-b418

@github-actions
Copy link

❌ PR review status - has 1 reviewer outstanding

@jpolavar jpolavar merged commit ab790d1 into main Oct 24, 2025
9 of 10 checks passed
@jpolavar jpolavar deleted the detect-aggregated-aws-commands branch October 24, 2025 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rule to detect and report imports of aggregated AWS SDK clients/commands

4 participants