diff --git a/meta-schema.json b/meta-schema.json index 87c23d9..41a53d6 100644 --- a/meta-schema.json +++ b/meta-schema.json @@ -130,7 +130,7 @@ "properties": { "loop": { "type": "object", - "required": ["over", "as", "step"], + "required": ["over", "as"], "properties": { "over": { "type": "string", @@ -152,6 +152,13 @@ "step": { "$ref": "#/definitions/Step", "description": "The step to execute for each item in the iteration. Can be any primitive step type." + }, + "steps": { + "type": "array", + "description": "An array of steps to execute for each item in the iteration.", + "items": { + "$ref": "#/definitions/Step" + } } } } diff --git a/src/__tests__/dependency-resolver.test.ts b/src/__tests__/dependency-resolver.test.ts index 1dc0336..8b80c49 100644 --- a/src/__tests__/dependency-resolver.test.ts +++ b/src/__tests__/dependency-resolver.test.ts @@ -541,4 +541,61 @@ describe('DependencyResolver', () => { expect(deps).toContain('step2'); expect(deps).toContain('step3'); }); + + it('correctly identifies dependencies in loop steps with multiple steps', () => { + const flow: Flow = { + name: 'Test Flow', + description: 'Test flow for loop step dependencies with multiple steps', + steps: [ + { + name: 'getUser', + request: { + method: 'user.get', + params: { id: 1 }, + }, + }, + { + name: 'getFriends', + request: { + method: 'user.getFriends', + params: { userId: '${getUser.id}' }, + }, + }, + { + name: 'notifyFriends', + loop: { + over: '${getFriends}', + as: 'friend', + steps: [ + { + name: 'validateFriend', + request: { + method: 'friend.validate', + params: { id: '${friend.id}' }, + }, + }, + { + name: 'sendNotification', + request: { + method: 'notification.send', + params: { + userId: '${friend.id}', + message: 'Hello from ${getUser.name}!', + }, + }, + }, + ], + }, + }, + ], + }; + + const resolver = new DependencyResolver(flow, expressionEvaluator, testLogger); + expect(resolver.getDependencies('notifyFriends')).toEqual(['getFriends', 'getUser']); + expect(resolver.getExecutionOrder().map((s) => s.name)).toEqual([ + 'getUser', + 'getFriends', + 'notifyFriends', + ]); + }); }); diff --git a/src/dependency-resolver.ts b/src/dependency-resolver.ts index d25bd32..a91d7fb 100644 --- a/src/dependency-resolver.ts +++ b/src/dependency-resolver.ts @@ -129,6 +129,21 @@ export class DependencyResolver { this.loopVars.delete(loopVar); } } + + // Process the loop's steps if present + if (step.loop.steps) { + // Add the loop variable to loopVars temporarily + const loopVar = step.loop.as; + this.loopVars.add(loopVar); + + // Find dependencies in each step + for (const subStep of step.loop.steps) { + this.findStepDependencies(subStep).forEach((dep) => deps.add(dep)); + } + + // Remove the loop variable from loopVars + this.loopVars.delete(loopVar); + } } // Extract references from condition steps