Summary
compileIamRole.js has grown to ~1000 lines with 30+ functions, and its test file compileIamRole.test.js is now ~4700 lines. Both files are difficult to navigate and maintain as new AWS service integrations are added over time.
This is part of a broader refactoring roadmap tracked in #708.
We'd like to propose a refactor that splits this into a clean Strategy pattern, where each AWS service integration lives in its own focused module.
Proposed Structure
lib/deploy/stepFunctions/
iamRole/
index.js ← compileIamRole() entry point, consolidation, getIamStatements
dispatcher.js ← iterates strategies, calls matches() + getPermissions()
utils.js ← shared helpers (isJsonPathParameter, isJsonataArgument, getTaskStates, etc.)
strategies/
sns.js
sqs.js
dynamodb.js
redshift.js
lambda.js
stepFunctions.js
s3.js
batchGlueEcs.js
services.js ← CodeBuild, SageMaker, Bedrock, EventBridge, HTTP, Scheduler
Each strategy exports two functions:
matches(resource) — returns true if this strategy handles the given resource ARN pattern
getPermissions(state) — returns the IAM permission objects for this service
The dispatcher replaces the current large if/else if chain in getIamPermissions():
const strategies = [
require('./strategies/sqs'),
require('./strategies/sns'),
// ...
];
function getIamPermissions(state) {
const strategy = strategies.find(s => s.matches(state.Resource));
return strategy ? strategy.getPermissions(state) : [];
}
Tests mirror the source structure exactly, so strategies/dynamodb.js is covered by strategies/dynamodb.test.js etc.
Benefits
- Easier to navigate — finding the code for a specific service integration is obvious
- Easier to maintain — changes to one service can't accidentally break another
- Easier to extend — adding a new AWS service integration means dropping in a new strategy file with no changes to existing code
- Easier to review — PRs for new service integrations are focused and small
- Better test isolation — test failures point directly to the affected service module
Public interface
No changes to the plugin's public API or configuration. index.js continues to export compileIamRole() and is mixed in the same way as today.
Dependency on pending PRs
We have several open PRs that touch compileIamRole.js and compileIamRole.test.js. We'd like those to be merged before starting this refactor so the restructured code includes all current fixes:
Question for maintainers
Are you open to this refactor? We're happy to implement it incrementally (e.g. migrate one strategy at a time) or in a single PR — whichever you prefer.
Summary
compileIamRole.jshas grown to ~1000 lines with 30+ functions, and its test filecompileIamRole.test.jsis now ~4700 lines. Both files are difficult to navigate and maintain as new AWS service integrations are added over time.This is part of a broader refactoring roadmap tracked in #708.
We'd like to propose a refactor that splits this into a clean Strategy pattern, where each AWS service integration lives in its own focused module.
Proposed Structure
Each strategy exports two functions:
matches(resource)— returns true if this strategy handles the given resource ARN patterngetPermissions(state)— returns the IAM permission objects for this serviceThe dispatcher replaces the current large
if/else ifchain ingetIamPermissions():Tests mirror the source structure exactly, so
strategies/dynamodb.jsis covered bystrategies/dynamodb.test.jsetc.Benefits
Public interface
No changes to the plugin's public API or configuration.
index.jscontinues to exportcompileIamRole()and is mixed in the same way as today.Dependency on pending PRs
We have several open PRs that touch
compileIamRole.jsandcompileIamRole.test.js. We'd like those to be merged before starting this refactor so the restructured code includes all current fixes:Question for maintainers
Are you open to this refactor? We're happy to implement it incrementally (e.g. migrate one strategy at a time) or in a single PR — whichever you prefer.