@@ -350,6 +350,9 @@ function translateCode(code) {
350
350
// Process all transformations in a single pass
351
351
processTransformations ( ast , transformedNodes ) ;
352
352
353
+ // Handle legacy Postman global APIs
354
+ handleLegacyGlobalAPIs ( ast , transformedNodes , code ) ;
355
+
353
356
// Handle special Postman syntax patterns
354
357
handleTestsBracketNotation ( ast ) ;
355
358
@@ -787,5 +790,102 @@ function handleTestsBracketNotation(ast) {
787
790
} ) ;
788
791
}
789
792
793
+ /**
794
+ * Handle legacy Postman global API transformations
795
+ * This function processes legacy Postman globals like responseBody, responseHeaders, responseTime
796
+ * while preserving user-defined variables with the same names
797
+ *
798
+ * @param {Object } ast - jscodeshift AST
799
+ * @param {Set } transformedNodes - Set of already transformed nodes
800
+ * @param {string } code - The original Postman script code
801
+ */
802
+ function handleLegacyGlobalAPIs ( ast , transformedNodes , code ) {
803
+ // regex check before the ast traversal
804
+ const legacyGlobalRegex = / r e s p o n s e B o d y | r e s p o n s e H e a d e r s | r e s p o n s e T i m e / ;
805
+
806
+ if ( ! legacyGlobalRegex . test ( code ) ) {
807
+ return ;
808
+ }
809
+
810
+ // Check for variable declarations with legacy global names - track which ones have conflicts
811
+ const conflictingNames = new Set ( ) ;
812
+
813
+ // Check variable declarations
814
+ ast . find ( j . VariableDeclarator ) . forEach ( path => {
815
+ if ( path . value . id . type === 'Identifier' ) {
816
+ const varName = path . value . id . name ;
817
+ if ( legacyGlobalRegex . test ( varName ) ) {
818
+ conflictingNames . add ( varName ) ;
819
+ }
820
+ }
821
+ } ) ;
822
+
823
+ // Handle JSON.parse(responseBody) → res.getBody()
824
+ // Only transform if responseBody doesn't have a user variable conflict
825
+ if ( ! conflictingNames . has ( 'responseBody' ) ) {
826
+ ast . find ( j . CallExpression ) . forEach ( path => {
827
+ if ( transformedNodes . has ( path . node ) ) return ;
828
+
829
+ const callExpr = path . value ;
830
+ if ( callExpr . callee . type === 'MemberExpression' && callExpr . callee . object . name === 'JSON' && callExpr . callee . property . name === 'parse' ) {
831
+ const args = callExpr . arguments ;
832
+
833
+ // Check if the argument is 'responseBody'
834
+ if ( args . length > 0 && args [ 0 ] . type === 'Identifier' && args [ 0 ] . name === 'responseBody' ) {
835
+ // Replace JSON.parse(responseBody) with res.getBody()
836
+ j ( path ) . replaceWith ( j . identifier ( 'res.getBody()' ) ) ;
837
+ transformedNodes . add ( path . node ) ;
838
+ }
839
+ }
840
+ } ) ;
841
+ }
842
+
843
+ // Handle standalone legacy Postman global variables
844
+ const legacyGlobals = [
845
+ { name : 'responseBody' , replacement : 'res.getBody()' } ,
846
+ { name : 'responseHeaders' , replacement : 'res.getHeaders()' } ,
847
+ { name : 'responseTime' , replacement : 'res.getResponseTime()' }
848
+ ] ;
849
+
850
+ legacyGlobals . forEach ( ( { name, replacement } ) => {
851
+ // Skip transformation if this name has a user variable conflict
852
+ if ( conflictingNames . has ( name ) ) {
853
+ return ;
854
+ }
855
+
856
+ ast . find ( j . Identifier , { name } ) . forEach ( path => {
857
+ if ( transformedNodes . has ( path . node ) ) return ;
858
+
859
+ // Only transform identifiers that are being used as values, not as variable names
860
+ const parent = path . parent . value ;
861
+
862
+ // Skip if this is part of a variable declaration (const responseBody = ...)
863
+ if ( parent . type === 'VariableDeclarator' && parent . id === path . node ) {
864
+ return ; // Keep unchanged
865
+ }
866
+
867
+ // Skip if this is part of an assignment (responseBody = ...)
868
+ if ( parent . type === 'AssignmentExpression' && parent . left === path . node ) {
869
+ return ; // Keep unchanged
870
+ }
871
+
872
+ // Skip if this is part of a function parameter
873
+ if ( parent . type === 'FunctionDeclaration' || parent . type === 'FunctionExpression' ) {
874
+ return ; // Keep unchanged
875
+ }
876
+
877
+ // Skip if this is part of an object property
878
+ if ( parent . type === 'Property' && ( parent . key === path . node || parent . value === path . node ) ) {
879
+ return ; // Keep unchanged
880
+ }
881
+
882
+ // Transform all other references (including function call arguments)
883
+ // This will transform console.log(responseBody) → console.log(res.getBody())
884
+ j ( path ) . replaceWith ( j . identifier ( replacement ) ) ;
885
+ transformedNodes . add ( path . node ) ;
886
+ } ) ;
887
+ } ) ;
888
+ }
889
+
790
890
export { getMemberExpressionString } ;
791
891
export default translateCode ;
0 commit comments