1+ import type { SgRoot } from "@codemod.com/jssg-types/src/main" ;
2+ import type Js from '@codemod.com/jssg-types/src/langs/javascript' ;
3+
4+ async function transform ( root : SgRoot < Js > ) : Promise < string > {
5+ const rootNode = root . root ( ) ;
6+
7+ // Helper function to find the request parameter name
8+ function findRequestParamName ( node : any ) : string {
9+ // Start from the call expression and traverse up to find function parameters
10+ let current = node ;
11+ while ( current ) {
12+ const parent = current . parent ( ) ;
13+ if ( ! parent ) break ;
14+ // Check if we're in a function declaration or arrow function
15+ if ( parent . kind ( ) === 'function_declaration' || parent . kind ( ) === 'arrow_function' ) {
16+ const params = parent . field ( 'parameters' ) ;
17+
18+ if ( params && params . children ( ) . length > 0 ) {
19+ const firstParam = params . children ( ) [ 1 ] ;
20+ if ( firstParam . kind ( ) === 'required_parameter' ) {
21+ const pattern = firstParam . field ( 'pattern' ) ;
22+ if ( pattern && pattern . kind ( ) === 'identifier' ) {
23+ return pattern . text ( ) ;
24+ }
25+ }
26+ }
27+ }
28+
29+ current = parent ;
30+ }
31+ return 'req' ; // default fallback
32+ }
33+
34+ // Find all redirect and location
35+ const nodes = rootNode . findAll ( {
36+ rule : {
37+ any : [
38+ {
39+ pattern : "$OBJ.redirect($ARG)" ,
40+ } ,
41+ {
42+ pattern : "$OBJ.location($ARG)" ,
43+ } ]
44+ }
45+ } ) ;
46+
47+ const edits = nodes . reduce ( ( acc : any [ ] , node : any ) => {
48+ const requestParamName = findRequestParamName ( node ) ;
49+ const obj = node . getMatch ( "OBJ" ) ;
50+ const arg = node . getMatch ( "ARG" ) ;
51+
52+ // Only transform when the argument is the literal 'back' (single or double quotes)
53+ const argText = arg && typeof arg . text === 'function' ? arg . text ( ) : null ;
54+ if ( argText !== "'back'" && argText !== '"back"' && argText !== "‘back’" && argText !== "“back”" ) {
55+ return acc ; // skip this node, no edit
56+ }
57+
58+ // Case: obj.redirect('back') or obj.location('back')
59+ const objText = obj ?. text ( ) ;
60+ const methodName = node . text ( ) . includes ( '.redirect(' ) ? 'redirect' : 'location' ;
61+ acc . push ( node . replace ( `${ objText } .${ methodName } (${ requestParamName } .get("Referrer") || "/")` ) ) ;
62+ return acc ;
63+ } , [ ] as any [ ] ) ;
64+
65+ const newSource = rootNode . commitEdits ( edits ) ;
66+ return newSource ;
67+ }
68+
69+ export default transform ;
0 commit comments