Skip to content

Commit cb7f61e

Browse files
authored
Implement legacy Postman global API transformations (#5403)
1 parent 6bcb850 commit cb7f61e

File tree

2 files changed

+399
-0
lines changed

2 files changed

+399
-0
lines changed

packages/bruno-converters/src/utils/jscode-shift-translator.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ function translateCode(code) {
350350
// Process all transformations in a single pass
351351
processTransformations(ast, transformedNodes);
352352

353+
// Handle legacy Postman global APIs
354+
handleLegacyGlobalAPIs(ast, transformedNodes, code);
355+
353356
// Handle special Postman syntax patterns
354357
handleTestsBracketNotation(ast);
355358

@@ -787,5 +790,102 @@ function handleTestsBracketNotation(ast) {
787790
});
788791
}
789792

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 = /responseBody|responseHeaders|responseTime/;
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+
790890
export { getMemberExpressionString };
791891
export default translateCode;

0 commit comments

Comments
 (0)