@@ -47,49 +47,48 @@ describe('.array() method type constraints', () => {
4747 describe ( 'type inference' , ( ) => {
4848 it ( 'should provide correct input types for dependent steps' , ( ) => {
4949 new Flow < { count : number } > ( { slug : 'test' } )
50- . array ( { slug : 'items' } , ( { run } ) => Array ( run . count ) . fill ( 0 ) . map ( ( _ , i ) => i ) )
51- . step ( { slug : 'process' , dependsOn : [ 'items' ] } , ( input ) => {
52- expectTypeOf ( input ) . toMatchTypeOf < {
53- run : { count : number } ;
50+ . array ( { slug : 'items' } , ( flowInput ) => Array ( flowInput . count ) . fill ( 0 ) . map ( ( _ , i ) => i ) )
51+ . step ( { slug : 'process' , dependsOn : [ 'items' ] } , ( deps ) => {
52+ expectTypeOf ( deps ) . toMatchTypeOf < {
5453 items : number [ ] ;
5554 } > ( ) ;
56- return input . items . length ;
55+ return deps . items . length ;
5756 } ) ;
5857 } ) ;
5958
6059 it ( 'should correctly infer element types from arrays' , ( ) => {
6160 new Flow < { userId : string } > ( { slug : 'test' } )
6261 . array ( { slug : 'users' } , ( ) => [ { id : 1 , name : 'John' } , { id : 2 , name : 'Jane' } ] )
63- . step ( { slug : 'count_users' , dependsOn : [ 'users' ] } , ( input ) => {
64- expectTypeOf ( input . users ) . toEqualTypeOf < { id : number ; name : string } [ ] > ( ) ;
65- expectTypeOf ( input . users [ 0 ] ) . toMatchTypeOf < { id : number ; name : string } > ( ) ;
66- return input . users . length ;
62+ . step ( { slug : 'count_users' , dependsOn : [ 'users' ] } , ( deps ) => {
63+ expectTypeOf ( deps . users ) . toEqualTypeOf < { id : number ; name : string } [ ] > ( ) ;
64+ expectTypeOf ( deps . users [ 0 ] ) . toMatchTypeOf < { id : number ; name : string } > ( ) ;
65+ return deps . users . length ;
6766 } ) ;
6867 } ) ;
6968
7069 it ( 'should handle complex nested array types' , ( ) => {
7170 new Flow < { depth : number } > ( { slug : 'test' } )
72- . array ( { slug : 'matrix' } , ( { run } ) =>
73- Array ( run . depth ) . fill ( 0 ) . map ( ( ) => Array ( 3 ) . fill ( 0 ) . map ( ( ) => ( { value : Math . random ( ) } ) ) )
71+ . array ( { slug : 'matrix' } , ( flowInput ) =>
72+ Array ( flowInput . depth ) . fill ( 0 ) . map ( ( ) => Array ( 3 ) . fill ( 0 ) . map ( ( ) => ( { value : Math . random ( ) } ) ) )
7473 )
75- . step ( { slug : 'flatten' , dependsOn : [ 'matrix' ] } , ( input ) => {
76- expectTypeOf ( input . matrix ) . toEqualTypeOf < { value : number } [ ] [ ] > ( ) ;
77- expectTypeOf ( input . matrix [ 0 ] ) . toEqualTypeOf < { value : number } [ ] > ( ) ;
78- expectTypeOf ( input . matrix [ 0 ] [ 0 ] ) . toMatchTypeOf < { value : number } > ( ) ;
79- return input . matrix . flat ( ) ;
74+ . step ( { slug : 'flatten' , dependsOn : [ 'matrix' ] } , ( deps ) => {
75+ expectTypeOf ( deps . matrix ) . toEqualTypeOf < { value : number } [ ] [ ] > ( ) ;
76+ expectTypeOf ( deps . matrix [ 0 ] ) . toEqualTypeOf < { value : number } [ ] > ( ) ;
77+ expectTypeOf ( deps . matrix [ 0 ] [ 0 ] ) . toMatchTypeOf < { value : number } > ( ) ;
78+ return deps . matrix . flat ( ) ;
8079 } ) ;
8180 } ) ;
8281
8382 it ( 'should correctly type async array handlers' , ( ) => {
8483 new Flow < { url : string } > ( { slug : 'test' } )
85- . array ( { slug : 'data' } , async ( { run } ) => {
84+ . array ( { slug : 'data' } , async ( flowInput ) => {
8685 // Simulate async data fetching
8786 await new Promise ( resolve => setTimeout ( resolve , 1 ) ) ;
88- return [ { url : run . url , status : 200 } ] ;
87+ return [ { url : flowInput . url , status : 200 } ] ;
8988 } )
90- . step ( { slug : 'validate' , dependsOn : [ 'data' ] } , ( input ) => {
91- expectTypeOf ( input . data ) . toEqualTypeOf < { url : string ; status : number } [ ] > ( ) ;
92- return input . data . every ( item => item . status === 200 ) ;
89+ . step ( { slug : 'validate' , dependsOn : [ 'data' ] } , ( deps ) => {
90+ expectTypeOf ( deps . data ) . toEqualTypeOf < { url : string ; status : number } [ ] > ( ) ;
91+ return deps . data . every ( item => item . status === 200 ) ;
9392 } ) ;
9493 } ) ;
9594 } ) ;
@@ -106,33 +105,31 @@ describe('.array() method type constraints', () => {
106105 new Flow < string > ( { slug : 'test' } )
107106 . array ( { slug : 'items1' } , ( ) => [ 1 , 2 , 3 ] )
108107 . array ( { slug : 'items2' } , ( ) => [ 'a' , 'b' , 'c' ] )
109- . array ( { slug : 'combined' , dependsOn : [ 'items1' ] } , ( input ) => {
110- expectTypeOf ( input ) . toMatchTypeOf < {
111- run : string ;
108+ . array ( { slug : 'combined' , dependsOn : [ 'items1' ] } , ( deps ) => {
109+ expectTypeOf ( deps ) . toMatchTypeOf < {
112110 items1 : number [ ] ;
113111 } > ( ) ;
114112
115113 // Verify that items2 is not accessible
116- expectTypeOf ( input ) . not . toHaveProperty ( 'items2' ) ;
114+ expectTypeOf ( deps ) . not . toHaveProperty ( 'items2' ) ;
117115
118- return input . items1 . map ( String ) ;
116+ return deps . items1 . map ( String ) ;
119117 } ) ;
120118 } ) ;
121119
122120 it ( 'should correctly type multi-dependency array steps' , ( ) => {
123121 new Flow < { base : number } > ( { slug : 'test' } )
124- . array ( { slug : 'numbers' } , ( { run } ) => [ run . base , run . base + 1 ] )
122+ . array ( { slug : 'numbers' } , ( flowInput ) => [ flowInput . base , flowInput . base + 1 ] )
125123 . array ( { slug : 'letters' } , ( ) => [ 'a' , 'b' ] )
126- . array ( { slug : 'combined' , dependsOn : [ 'numbers' , 'letters' ] } , ( input ) => {
127- expectTypeOf ( input ) . toMatchTypeOf < {
128- run : { base : number } ;
124+ . array ( { slug : 'combined' , dependsOn : [ 'numbers' , 'letters' ] } , ( deps ) => {
125+ expectTypeOf ( deps ) . toMatchTypeOf < {
129126 numbers : number [ ] ;
130127 letters : string [ ] ;
131128 } > ( ) ;
132-
133- return input . numbers . map ( ( num , i ) => ( {
129+
130+ return deps . numbers . map ( ( num , i ) => ( {
134131 number : num ,
135- letter : input . letters [ i ] || 'z'
132+ letter : deps . letters [ i ] || 'z'
136133 } ) ) ;
137134 } ) ;
138135 } ) ;
@@ -142,13 +139,13 @@ describe('.array() method type constraints', () => {
142139 it ( 'should provide custom context via Flow type parameter' , ( ) => {
143140 // eslint-disable-next-line @typescript-eslint/no-explicit-any
144141 const flow = new Flow < { id : number } , { api : { get : ( id : number ) => Promise < any > } } > ( { slug : 'test' } )
145- . array ( { slug : 'fetch_data' } , ( input , context ) => {
142+ . array ( { slug : 'fetch_data' } , ( flowInput , context ) => {
146143 // No handler annotation needed! Type parameter provides context
147144 expectTypeOf ( context . api ) . toEqualTypeOf < { get : ( id : number ) => Promise < any > } > ( ) ;
148145 expectTypeOf ( context . env ) . toEqualTypeOf < Record < string , string | undefined > > ( ) ;
149146 expectTypeOf ( context . shutdownSignal ) . toEqualTypeOf < AbortSignal > ( ) ;
150147
151- return [ { id : input . run . id , data : 'mock' } ] ;
148+ return [ { id : flowInput . id , data : 'mock' } ] ;
152149 } ) ;
153150
154151 // ExtractFlowContext should include FlowContext & custom resources
@@ -164,11 +161,11 @@ describe('.array() method type constraints', () => {
164161
165162 it ( 'should share custom context across array and regular steps' , ( ) => {
166163 const flow = new Flow < { count : number } , { generator : ( ) => number ; processor : ( items : number [ ] ) => string } > ( { slug : 'test' } )
167- . array ( { slug : 'items' } , ( input , context ) => {
164+ . array ( { slug : 'items' } , ( flowInput , context ) => {
168165 // All steps get the same context automatically
169- return Array ( input . run . count ) . fill ( 0 ) . map ( ( ) => context . generator ( ) ) ;
166+ return Array ( flowInput . count ) . fill ( 0 ) . map ( ( ) => context . generator ( ) ) ;
170167 } )
171- . step ( { slug : 'process' } , ( input , context ) => {
168+ . step ( { slug : 'process' } , ( flowInput , context ) => {
172169 return context . processor ( [ 1 , 2 , 3 ] ) ;
173170 } ) ;
174171
@@ -187,21 +184,21 @@ describe('.array() method type constraints', () => {
187184 describe ( 'handler signature validation' , ( ) => {
188185 it ( 'should correctly type array step handlers when using getStepDefinition' , ( ) => {
189186 const flow = new Flow < { size : number } > ( { slug : 'test' } )
190- . array ( { slug : 'data' } , ( input , _context ) => Array ( input . run . size ) . fill ( 0 ) . map ( ( _ , i ) => ( { index : i } ) ) )
191- . step ( { slug : 'dependent' , dependsOn : [ 'data' ] } , ( input , _context ) => input . data . length ) ;
187+ . array ( { slug : 'data' } , ( flowInput , _context ) => Array ( flowInput . size ) . fill ( 0 ) . map ( ( _ , i ) => ( { index : i } ) ) )
188+ . step ( { slug : 'dependent' , dependsOn : [ 'data' ] } , ( deps , _context ) => deps . data . length ) ;
192189
193190 const arrayStep = flow . getStepDefinition ( 'data' ) ;
194191
195- // Test array step handler type - handlers have 2 params (input, context )
192+ // Test array step handler type - root steps receive flowInput directly (no run key )
196193 expectTypeOf ( arrayStep . handler ) . toBeFunction ( ) ;
197- expectTypeOf ( arrayStep . handler ) . parameter ( 0 ) . toMatchTypeOf < { run : { size : number } } > ( ) ;
194+ expectTypeOf ( arrayStep . handler ) . parameter ( 0 ) . toMatchTypeOf < { size : number } > ( ) ;
198195 expectTypeOf ( arrayStep . handler ) . returns . toMatchTypeOf <
199196 { index : number } [ ] | Promise < { index : number } [ ] >
200197 > ( ) ;
201198
202199 const dependentStep = flow . getStepDefinition ( 'dependent' ) ;
200+ // Dependent steps receive deps only (no run key)
203201 expectTypeOf ( dependentStep . handler ) . parameter ( 0 ) . toMatchTypeOf < {
204- run : { size : number } ;
205202 data : { index : number } [ ] ;
206203 } > ( ) ;
207204 } ) ;
@@ -213,20 +210,20 @@ describe('.array() method type constraints', () => {
213210 . array ( { slug : 'items' } , ( ) => [ { id : 1 } , { id : 2 } ] )
214211 . array ( { slug : 'processed' , dependsOn : [ 'items' ] } , ( ) => [ 'a' , 'b' ] ) ;
215212
216- // Test StepInput type extraction
213+ // Test StepInput type extraction - root steps get flow input directly
217214 type ItemsInput = StepInput < typeof flow , 'items' > ;
218215 expectTypeOf < ItemsInput > ( ) . toMatchTypeOf < {
219- run : { userId : string } ;
216+ userId : string ;
220217 } > ( ) ;
221218
219+ // Dependent steps get deps only (no run key)
222220 type ProcessedInput = StepInput < typeof flow , 'processed' > ;
223221 expectTypeOf < ProcessedInput > ( ) . toMatchTypeOf < {
224- run : { userId : string } ;
225222 items : { id : number } [ ] ;
226223 } > ( ) ;
227224
228225 // Should not contain non-dependencies
229226 expectTypeOf < ProcessedInput > ( ) . not . toHaveProperty ( 'nonExistent' ) ;
230227 } ) ;
231228 } ) ;
232- } ) ;
229+ } ) ;
0 commit comments