ts-morph-react 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import { FormatCodeSettings, SourceFile, VariableDeclaration, FunctionDeclaration, Node, ts } from 'ts-morph';
2
+ import { RulesConfig } from '@eslint/core';
3
+ import { Options } from 'prettier';
2
4
  import { PartialDeep } from 'type-fest';
3
5
 
4
6
  interface TransformerConfig {
@@ -6,9 +8,13 @@ interface TransformerConfig {
6
8
  enforceFunctionComponent: boolean;
7
9
  enforceNamedImports: boolean;
8
10
  enforceFormat: boolean;
11
+ enforceEslint: boolean;
12
+ enforcePrettier: boolean;
9
13
  format: FormatCodeSettings;
14
+ prettier: Options;
15
+ eslint: Partial<RulesConfig>;
10
16
  }
11
- declare function mergeConfig({ format, ...config }?: PartialDeep<TransformerConfig>): TransformerConfig;
17
+ declare function mergeConfig({ eslint, format, prettier, ...config }?: PartialDeep<TransformerConfig>): TransformerConfig;
12
18
 
13
19
  interface TransformerParams {
14
20
  sourceFile: SourceFile;
@@ -23,11 +29,15 @@ interface Transformer {
23
29
 
24
30
  declare const enforceDirectExports: Transformer;
25
31
 
32
+ declare const enforceEslint: Transformer;
33
+
34
+ declare const enforceFormat: Transformer;
35
+
26
36
  declare const enforceFunctionComponent: Transformer;
27
37
 
28
38
  declare const enforceNamedImports: Transformer;
29
39
 
30
- declare function createTempSourceFile(filename: string): Promise<string>;
40
+ declare const enforcePrettier: Transformer;
31
41
 
32
42
  declare const REACT_TYPES: string[];
33
43
  declare const REACT_HOOKS: string[];
@@ -50,4 +60,4 @@ interface SeparationEntry {
50
60
  }
51
61
  declare function enforeLineSeparation(sourceFile: SourceFile, predicate: (cur: Node<ts.Node>, prev: Node<ts.Node>, triviaWidth: number) => SeparationIntent): void;
52
62
 
53
- export { type MatchFn, REACT_APIS, REACT_HOOKS, REACT_TYPES, type SeparationEntry, SeparationIntent, type TransformFn, type Transformer, type TransformerConfig, type TransformerParams, createTempSourceFile, enforceDirectExports, enforceFunctionComponent, enforceNamedImports, enforeLineSeparation, isForwardRefComponent, isFunctionComponent, isReactComponent, mergeConfig, transform, transformers };
63
+ export { type MatchFn, REACT_APIS, REACT_HOOKS, REACT_TYPES, type SeparationEntry, SeparationIntent, type TransformFn, type Transformer, type TransformerConfig, type TransformerParams, enforceDirectExports, enforceEslint, enforceFormat, enforceFunctionComponent, enforceNamedImports, enforcePrettier, enforeLineSeparation, isForwardRefComponent, isFunctionComponent, isReactComponent, mergeConfig, transform, transformers };
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
- import {SyntaxKind,Node,StructureKind,VariableDeclarationKind,ts,ImportDeclaration}from'ts-morph';import {mkdtemp}from'fs/promises';import {tmpdir}from'os';import {join}from'path';var y=["ComponentProps","ComponentPropsWithRef","ComponentPropsWithoutRef","FC","FunctionComponent","ReactNode","ReactElement","JSX","RefObject","MutableRefObject","CSSProperties","HTMLAttributes","SVGAttributes","DOMAttributes","PropsWithChildren","PropsWithRef"],N=["useState","useEffect","useCallback","useMemo","useRef","useContext","useReducer","useImperativeHandle","useLayoutEffect","useDebugValue","useTransition","useDeferredValue","useId","useSyncExternalStore"],R=["forwardRef","memo","lazy","createContext","createElement","cloneElement","isValidElement","Children","Fragment","StrictMode","Suspense"];function b(e){try{let t=e.getInitializer?.();if(!t)return !1;let r=t.getDescendantsOfKind?.(SyntaxKind.JsxElement)||[],o=t.getDescendantsOfKind?.(SyntaxKind.JsxSelfClosingElement)||[];if(r.length>0||o.length>0)return !0;if(Node.isArrowFunction(t)){let n=t.getBody?.();if(n){let i=n.getDescendantsOfKind?.(SyntaxKind.JsxElement)||[],a=n.getDescendantsOfKind?.(SyntaxKind.JsxSelfClosingElement)||[];return i.length>0||a.length>0}}return !1}catch{return false}}function I(e){try{let t=e.getInitializer?.();if(!t)return !1;let r=t.getText?.();return !!(r?.includes("forwardRef(")||r?.includes("React.forwardRef("))}catch{return false}}function T(e){try{let t=e.getDescendantsOfKind?.(SyntaxKind.JsxElement)||[],r=e.getDescendantsOfKind?.(SyntaxKind.JsxSelfClosingElement)||[];return t.length>0||r.length>0}catch{return false}}var A={match:({config:e})=>e.enforceDirectExports,transform:async({sourceFile:e})=>{e.getFunctions().forEach(t=>{if(!T(t)||t.isExported()&&t.hasExportKeyword())return;let r=t.getName(),o=false;e.getExportDeclarations().forEach(n=>{n.getNamedExports().some(a=>a.getName()===r)&&(o=true);}),o&&(t.setIsExported(true),e.getExportDeclarations().forEach(n=>{let a=n.getNamedExports().filter(s=>s.getName()===r);a.length>0&&(a.forEach(s=>{s.remove();}),n.getNamedExports().length===0&&n.remove());}));}),e.getVariableDeclarations().forEach(t=>{if(!b(t)||I(t))return;let r=t.getInitializer();if(!r||!Node.isArrowFunction(r))return;let o=t.getName(),n=t.getVariableStatement();if(!n)return;let i=n.hasExportKeyword(),a=false;e.getExportDeclarations().forEach(f=>{f.getNamedExports().some(E=>E.getName()===o)&&(a=true);});let s=i||a,p=r.getParameters().map(f=>f.getText()).join(", "),g=r.getBody();if(!g)return;let x=g.getText(),d,c=x.trim();c.startsWith("(")&&c.endsWith(")")?d=`{
1
+ import {SyntaxKind,Node,ImportDeclaration,StructureKind,VariableDeclarationKind,ts}from'ts-morph';import j from'@stylistic/eslint-plugin';import {ESLint}from'eslint';import {dirname}from'path';import J from'typescript-eslint';import {format}from'prettier';var y=["ComponentProps","ComponentPropsWithRef","ComponentPropsWithoutRef","FC","FunctionComponent","ReactNode","ReactElement","JSX","RefObject","MutableRefObject","CSSProperties","HTMLAttributes","SVGAttributes","DOMAttributes","PropsWithChildren","PropsWithRef"],N=["useState","useEffect","useCallback","useMemo","useRef","useContext","useReducer","useImperativeHandle","useLayoutEffect","useDebugValue","useTransition","useDeferredValue","useId","useSyncExternalStore"],b=["forwardRef","memo","lazy","createContext","createElement","cloneElement","isValidElement","Children","Fragment","StrictMode","Suspense"];function R(e){try{let t=e.getInitializer?.();if(!t)return !1;let r=t.getDescendantsOfKind?.(SyntaxKind.JsxElement)||[],o=t.getDescendantsOfKind?.(SyntaxKind.JsxSelfClosingElement)||[];if(r.length>0||o.length>0)return !0;if(Node.isArrowFunction(t)){let n=t.getBody?.();if(n){let i=n.getDescendantsOfKind?.(SyntaxKind.JsxElement)||[],s=n.getDescendantsOfKind?.(SyntaxKind.JsxSelfClosingElement)||[];return i.length>0||s.length>0}}return !1}catch{return false}}function P(e){try{let t=e.getInitializer?.();if(!t)return !1;let r=t.getText?.();return !!(r?.includes("forwardRef(")||r?.includes("React.forwardRef("))}catch{return false}}function T(e){try{let t=e.getDescendantsOfKind?.(SyntaxKind.JsxElement)||[],r=e.getDescendantsOfKind?.(SyntaxKind.JsxSelfClosingElement)||[];return t.length>0||r.length>0}catch{return false}}var I={match:({config:e})=>e.enforceDirectExports,transform:async({sourceFile:e})=>{e.getFunctions().forEach(t=>{if(!T(t)||t.isExported()&&t.hasExportKeyword())return;let r=t.getName(),o=false;e.getExportDeclarations().forEach(n=>{n.getNamedExports().some(s=>s.getName()===r)&&(o=true);}),o&&(t.setIsExported(true),e.getExportDeclarations().forEach(n=>{let s=n.getNamedExports().filter(a=>a.getName()===r);s.length>0&&(s.forEach(a=>{a.remove();}),n.getNamedExports().length===0&&n.remove());}));}),e.getVariableDeclarations().forEach(t=>{if(!R(t)||P(t))return;let r=t.getInitializer();if(!r||!Node.isArrowFunction(r))return;let o=t.getName(),n=t.getVariableStatement();if(!n)return;let i=n.hasExportKeyword(),s=false;e.getExportDeclarations().forEach(f=>{f.getNamedExports().some(E=>E.getName()===o)&&(s=true);});let a=i||s,p=r.getParameters().map(f=>f.getText()).join(", "),g=r.getBody();if(!g)return;let x=g.getText(),l,c=x.trim();c.startsWith("(")&&c.endsWith(")")?l=`{
2
2
  return ${c.slice(1,-1).trim()}
3
- }`:c.startsWith("{")?d=x:d=`{
3
+ }`:c.startsWith("{")?l=x:l=`{
4
4
  return ${x}
5
- }`;let u=`${s?"export ":""}function ${o}(${p}) ${d}`;n.replaceWithText(u),a&&e.getExportDeclarations().forEach(f=>{let E=f.getNamedExports().filter(S=>S.getName()===o);E.length>0&&(E.forEach(S=>{S.remove();}),f.getNamedExports().length===0&&f.remove());});});}};var D={match:({config:e})=>e.enforceFunctionComponent,transform:async({sourceFile:e,config:{enforceDirectExports:t}})=>{e.getFunctions().forEach(r=>{if(!T(r))return;let o=r.getName();if(!o)return;let n=r.isExported(),i=false;e.getExportDeclarations().forEach(c=>{c.getNamedExports().some(f=>f.getName()===o)&&(i=true);});let a=t&&(n||i),m=r.getParameters()[0],g=(m.getTypeNode()??m.getType()).getText();m.removeType();let x=g==="any"?"React.FunctionComponent":`React.FunctionComponent<${g}>`,d=r.getChildIndex();e.insertVariableStatement(d,{declarations:[{name:o,type:x,initializer:c=>{c.write("(").write(r.getParameters().map(C=>C.getText()).join(", ")).write(")");let u=r.getReturnTypeNode()?.getText();u&&c.write(`: ${u}`),c.write(" => ");let f=r.getBody()?.getText()??"{}";c.block(()=>{c.write(f.replace(/^{|}$/g,"").trim());});}}],declarationKind:VariableDeclarationKind.Const,kind:StructureKind.VariableStatement,isExported:a}),r.remove();});}};var P={match:({config:e})=>e.enforceNamedImports,transform:async({sourceFile:e})=>{let t=e.getImportDeclarations().find(i=>i.getModuleSpecifier().getLiteralValue()==="react");if(!t||!t.getNamespaceImport())return;let o=new Set,n=new Set;if(e.forEachDescendant(i=>{if(i.getKind()===SyntaxKind.TypeReference){let a=i.asKind(SyntaxKind.TypeReference);if(!a)return;let s=a.getTypeName();if(Node.isQualifiedName(s)){let m=s.getLeft().getText(),p=s.getRight().getText();m==="React"&&y.includes(p)&&(s.replaceWithText(p),o.add(p));}}if(i.getKind()===SyntaxKind.PropertyAccessExpression){let a=i.asKind(SyntaxKind.PropertyAccessExpression);if(!a)return;let s=a.getExpression(),m=a.getName();s.getText()==="React"&&(N.includes(m)||R.includes(m)||y.includes(m))&&(a.replaceWithText(m),y.includes(m)?o.add(m):(N.includes(m)||R.includes(m))&&n.add(m));}}),o.size>0||n.size>0){t.removeNamespaceImport();let i=Array.from(o).sort();for(let s of i)t.addNamedImport({name:s,isTypeOnly:true});let a=Array.from(n).sort();for(let s of a)t.addNamedImport(s);}}};function O({format:e,...t}={}){return {enforceDirectExports:false,enforceFunctionComponent:false,enforceNamedImports:false,enforceFormat:false,format:{indentSize:2,convertTabsToSpaces:true,indentStyle:ts.IndentStyle.Smart,indentMultiLineObjectLiteralBeginningOnBlankLine:true,ensureNewLineAtEndOfFile:true,semicolons:ts.SemicolonPreference.Remove,trimTrailingWhitespace:true,...e},...t}}async function fe(e){let t=await mkdtemp(join(tmpdir(),"ts-morph-react-"));return join(t,e)}var w=(o=>(o[o.IGNORE=0]="IGNORE",o[o.COMBINE=1]="COMBINE",o[o.SEPARATE=2]="SEPARATE",o))(w||{});function V(e,t){let r=[],o=e.getChildSyntaxListOrThrow();for(let n=o.getChildCount()-1;n>0;n-=1){let i=o.getChildAtIndex(n-1),a=o.getChildAtIndex(n),s=t(a,i,a.getLeadingTriviaWidth());r.push({range:[i.getEnd(),a.getStart()],intent:s});}r.forEach(({range:n,intent:i})=>{i===1?e.replaceText(n,`
5
+ }`;let u=`${a?"export ":""}function ${o}(${p}) ${l}`;n.replaceWithText(u),s&&e.getExportDeclarations().forEach(f=>{let E=f.getNamedExports().filter(S=>S.getName()===o);E.length>0&&(E.forEach(S=>{S.remove();}),f.getNamedExports().length===0&&f.remove());});});}};var A={match:({config:e})=>e.enforceEslint,transform:async({sourceFile:e,config:t})=>{let r=e.getFilePath(),o=dirname(r),n=new ESLint({fix:true,cwd:o,overrideConfigFile:true,overrideConfig:[{basePath:".",languageOptions:{parser:J.parser,ecmaVersion:2020,sourceType:"module",parserOptions:{ecmaFeatures:{jsx:true}}},files:["**/*.{ts,tsx,js,jsx}"],plugins:{"@stylistic":j},rules:t.eslint}]}),[i]=await n.lintText(e.getFullText(),{filePath:r});i?.output&&e.replaceWithText(i.output);}};var O=(o=>(o[o.IGNORE=0]="IGNORE",o[o.COMBINE=1]="COMBINE",o[o.SEPARATE=2]="SEPARATE",o))(O||{});function w(e,t){let r=[],o=e.getChildSyntaxListOrThrow();for(let n=o.getChildCount()-1;n>0;n-=1){let i=o.getChildAtIndex(n-1),s=o.getChildAtIndex(n),a=t(s,i,s.getLeadingTriviaWidth());r.push({range:[i.getEnd(),s.getStart()],intent:a});}r.forEach(({range:n,intent:i})=>{i===1?e.replaceText(n,`
6
6
  `):i===2&&e.replaceText(n,`
7
7
 
8
- `);});}var L={match:({config:e})=>e.enforceFormat,transform:async({sourceFile:e,config:{format:t}})=>{e.formatText(t),V(e,(r,o)=>o instanceof ImportDeclaration&&r instanceof ImportDeclaration?1:2),e.organizeImports(t);}};var _=[A,D,P,L];async function Se(e,t={}){let r={config:O(t),sourceFile:e};for(let o of _)o.match(r)&&await o.transform(r);}export{R as REACT_APIS,N as REACT_HOOKS,y as REACT_TYPES,w as SeparationIntent,fe as createTempSourceFile,A as enforceDirectExports,D as enforceFunctionComponent,P as enforceNamedImports,V as enforeLineSeparation,I as isForwardRefComponent,T as isFunctionComponent,b as isReactComponent,O as mergeConfig,Se as transform,_ as transformers};//# sourceMappingURL=index.js.map
8
+ `);});}var F={match:({config:e})=>e.enforceFormat,transform:async({sourceFile:e,config:t})=>{w(e,(r,o)=>o instanceof ImportDeclaration&&r instanceof ImportDeclaration?1:2),e.organizeImports(),e.formatText(t.format);}};var v={match:({config:e})=>e.enforceFunctionComponent,transform:async({sourceFile:e,config:{enforceDirectExports:t}})=>{e.getFunctions().forEach(r=>{if(!T(r))return;let o=r.getName();if(!o)return;let n=r.isExported(),i=false;e.getExportDeclarations().forEach(c=>{c.getNamedExports().some(f=>f.getName()===o)&&(i=true);});let s=t&&(n||i),m=r.getParameters()[0],g=(m.getTypeNode()??m.getType()).getText();m.removeType();let x=g==="any"?"React.FunctionComponent":`React.FunctionComponent<${g}>`,l=r.getChildIndex();e.insertVariableStatement(l,{declarations:[{name:o,type:x,initializer:c=>{c.write("(").write(r.getParameters().map(C=>C.getText()).join(", ")).write(")");let u=r.getReturnTypeNode()?.getText();u&&c.write(`: ${u}`),c.write(" => ");let f=r.getBody()?.getText()??"{}";c.block(()=>{c.write(f.replace(/^{|}$/g,"").trim());});}}],declarationKind:VariableDeclarationKind.Const,kind:StructureKind.VariableStatement,isExported:s}),r.remove();});}};var K={match:({config:e})=>e.enforceNamedImports,transform:async({sourceFile:e})=>{let t=e.getImportDeclarations().find(i=>i.getModuleSpecifier().getLiteralValue()==="react");if(!t||!t.getNamespaceImport())return;let o=new Set,n=new Set;if(e.forEachDescendant(i=>{if(i.getKind()===SyntaxKind.TypeReference){let s=i.asKind(SyntaxKind.TypeReference);if(!s)return;let a=s.getTypeName();if(Node.isQualifiedName(a)){let m=a.getLeft().getText(),p=a.getRight().getText();m==="React"&&y.includes(p)&&(a.replaceWithText(p),o.add(p));}}if(i.getKind()===SyntaxKind.PropertyAccessExpression){let s=i.asKind(SyntaxKind.PropertyAccessExpression);if(!s)return;let a=s.getExpression(),m=s.getName();a.getText()==="React"&&(N.includes(m)||b.includes(m)||y.includes(m))&&(s.replaceWithText(m),y.includes(m)?o.add(m):(N.includes(m)||b.includes(m))&&n.add(m));}}),o.size>0||n.size>0){t.removeNamespaceImport();let i=Array.from(o).sort();for(let a of i)t.addNamedImport({name:a,isTypeOnly:true});let s=Array.from(n).sort();for(let a of s)t.addNamedImport(a);}}};var V={match:({config:e})=>e.enforcePrettier,transform:async({sourceFile:e,config:t})=>{let r=await format(e.getText(),{parser:"typescript",...t.prettier});e.replaceWithText(r);}};function z({eslint:e,format:t,prettier:r,...o}={}){return {enforceDirectExports:false,enforceFunctionComponent:false,enforceNamedImports:false,enforceFormat:false,enforceEslint:false,enforcePrettier:false,eslint:{"@stylistic/indent":["error",2],"@stylistic/quotes":["error","single"],"@stylistic/semi":["error","never"],"@stylistic/no-trailing-spaces":"error","@stylistic/no-multiple-empty-lines":["error",{max:1,maxEOF:0,maxBOF:0}],"@stylistic/function-paren-newline":["error","never"],"@stylistic/object-curly-newline":["error","never"],...e},format:{indentSize:2,convertTabsToSpaces:true,ensureNewLineAtEndOfFile:true,indentStyle:ts.IndentStyle.Block,semicolons:ts.SemicolonPreference.Remove,trimTrailingWhitespace:true,...t},prettier:{semi:false,singleQuote:true,jsxSingleQuote:true,arrowParens:"always",bracketSameLine:true,objectWrap:"collapse",printWidth:120,...r},...o}}var G=[I,v,K,F,A,V];async function we(e,t={}){let r={config:z(t),sourceFile:e};for(let o of G)o.match(r)&&await o.transform(r);}export{b as REACT_APIS,N as REACT_HOOKS,y as REACT_TYPES,O as SeparationIntent,I as enforceDirectExports,A as enforceEslint,F as enforceFormat,v as enforceFunctionComponent,K as enforceNamedImports,V as enforcePrettier,w as enforeLineSeparation,P as isForwardRefComponent,T as isFunctionComponent,R as isReactComponent,z as mergeConfig,we as transform,G as transformers};//# sourceMappingURL=index.js.map
9
9
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/react.ts","../src/transformers/enforceDirectExports.ts","../src/transformers/enforceFunctionComponent.ts","../src/transformers/enforceNamedImports.ts","../src/utils/config.ts","../src/utils/file.ts","../src/utils/trivia.ts","../src/transformers/enforceFormat.ts","../src/utils/transform.ts"],"names":["REACT_TYPES","REACT_HOOKS","REACT_APIS","isReactComponent","varDecl","initializer","descendants","SyntaxKind","selfClosing","Node","body","bodyDescendants","bodySelfClosing","isForwardRefComponent","text","isFunctionComponent","func","enforceDirectExports","config","sourceFile","funcName","isExportedViaSeparateStatement","exportDecl","exp","matchingExports","namedExport","varName","varStatement","isExportedViaKeyword","isExported","paramsText","p","bodyText","functionBody","trimmedBody","funcText","enforceFunctionComponent","param","typeText","typeAnnotation","index","writer","returnType","VariableDeclarationKind","StructureKind","enforceNamedImports","reactImport","importDeclaration","typeImportsNeeded","valueImportsNeeded","node","typeRef","typeName","left","right","propAccess","expr","name","typeImportsArray","valueImportsArray","valueName","mergeConfig","format","ts","createTempSourceFile","filename","dir","mkdtemp","join","tmpdir","SeparationIntent","enforeLineSeparation","predicate","instructions","syntaxList","prev","cur","intent","range","enforceFormat","ImportDeclaration","transformers","transform","params","transformer"],"mappings":"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","file":"index.js","sourcesContent":["import { FunctionDeclaration, Node, SyntaxKind, VariableDeclaration } from 'ts-morph'\n\n// React types that should be imported as named imports\nexport const REACT_TYPES = [\n 'ComponentProps',\n 'ComponentPropsWithRef',\n 'ComponentPropsWithoutRef',\n 'FC',\n 'FunctionComponent',\n 'ReactNode',\n 'ReactElement',\n 'JSX',\n 'RefObject',\n 'MutableRefObject',\n 'CSSProperties',\n 'HTMLAttributes',\n 'SVGAttributes',\n 'DOMAttributes',\n 'PropsWithChildren',\n 'PropsWithRef'\n]\n\n// React hooks that should be imported as named imports\nexport const REACT_HOOKS = [\n 'useState',\n 'useEffect',\n 'useCallback',\n 'useMemo',\n 'useRef',\n 'useContext',\n 'useReducer',\n 'useImperativeHandle',\n 'useLayoutEffect',\n 'useDebugValue',\n 'useTransition',\n 'useDeferredValue',\n 'useId',\n 'useSyncExternalStore'\n]\n\n// React APIs that should be imported as named imports\nexport const REACT_APIS = [\n 'forwardRef',\n 'memo',\n 'lazy',\n 'createContext',\n 'createElement',\n 'cloneElement',\n 'isValidElement',\n 'Children',\n 'Fragment',\n 'StrictMode',\n 'Suspense'\n]\n\n// Helper to detect if a variable declaration is a React component\nexport function isReactComponent(varDecl: VariableDeclaration): boolean {\n try {\n const initializer = varDecl.getInitializer?.()\n if (!initializer) return false\n\n // Check if the initializer contains JSX\n const descendants = initializer.getDescendantsOfKind?.(SyntaxKind.JsxElement) || []\n const selfClosing = initializer.getDescendantsOfKind?.(SyntaxKind.JsxSelfClosingElement) || []\n\n if (descendants.length > 0 || selfClosing.length > 0) { return true }\n\n // Check if it's assigned to an arrow function that returns JSX\n if (Node.isArrowFunction(initializer)) {\n const body = initializer.getBody?.()\n if (body) {\n const bodyDescendants = body.getDescendantsOfKind?.(SyntaxKind.JsxElement) || []\n const bodySelfClosing = body.getDescendantsOfKind?.(SyntaxKind.JsxSelfClosingElement) || []\n return bodyDescendants.length > 0 || bodySelfClosing.length > 0\n }\n }\n\n return false\n } catch {\n return false\n }\n}\n\n// Helper to check if a variable is a forwardRef component\nexport function isForwardRefComponent(varDecl: VariableDeclaration): boolean {\n try {\n const initializer = varDecl.getInitializer?.()\n if (!initializer) return false\n\n const text = initializer.getText?.()\n return text?.includes('forwardRef(') || text?.includes('React.forwardRef(') ? true : false\n } catch {\n return false\n }\n}\n\n// Helper to check if a function is a React component (returns JSX)\nexport function isFunctionComponent(func: FunctionDeclaration): boolean {\n try {\n const descendants = func.getDescendantsOfKind?.(SyntaxKind.JsxElement) || []\n const selfClosing = func.getDescendantsOfKind?.(SyntaxKind.JsxSelfClosingElement) || []\n if (descendants.length > 0 || selfClosing.length > 0) { return true }\n return false\n } catch {\n return false\n }\n}\n","import { Node } from 'ts-morph'\nimport { isForwardRefComponent, isFunctionComponent, isReactComponent } from '../utils/react'\nimport { Transformer } from '../utils/transformer'\n\nexport const enforceDirectExports: Transformer = {\n match: ({ config }) => config.enforceDirectExports,\n transform: async ({ sourceFile }) => {\n // Transform function declarations: add direct export if it's a component\n sourceFile.getFunctions().forEach((func) => {\n // Skip if not a component\n if (!isFunctionComponent(func)) { return }\n\n // Skip if already exported directly\n if (func.isExported() && func.hasExportKeyword()) { return }\n\n const funcName = func.getName()\n\n // Check if it's exported via separate export statement\n let isExportedViaSeparateStatement = false\n sourceFile.getExportDeclarations().forEach((exportDecl) => {\n const namedExports = exportDecl.getNamedExports()\n if (namedExports.some((exp) => exp.getName() === funcName)) {\n isExportedViaSeparateStatement = true\n }\n })\n\n // Only convert if it's a component that should be exported\n if (isExportedViaSeparateStatement) {\n // Add direct export modifier\n func.setIsExported(true)\n\n // Remove from separate export statements\n sourceFile.getExportDeclarations().forEach((exportDecl) => {\n const namedExports = exportDecl.getNamedExports()\n const matchingExports = namedExports.filter((namedExport) => namedExport.getName() === funcName)\n if (matchingExports.length > 0) {\n matchingExports.forEach((namedExport) => { namedExport.remove() })\n if (exportDecl.getNamedExports().length === 0) { exportDecl.remove() }\n }\n })\n }\n })\n\n // Transform const arrow functions to function declarations (if they're components and not forwardRef)\n sourceFile.getVariableDeclarations().forEach((varDecl) => {\n // Skip if not a component\n if (!isReactComponent(varDecl)) return\n\n // Skip forwardRef and memo patterns\n if (isForwardRefComponent(varDecl)) return\n\n const initializer = varDecl.getInitializer()\n if (!initializer || !Node.isArrowFunction(initializer)) return\n\n const varName = varDecl.getName()\n const varStatement = varDecl.getVariableStatement()\n if (!varStatement) return\n\n const isExportedViaKeyword = varStatement.hasExportKeyword()\n\n // Check if it's exported via separate export statement\n let isExportedViaSeparateStatement = false\n sourceFile.getExportDeclarations().forEach((exportDecl) => {\n const namedExports = exportDecl.getNamedExports()\n if (namedExports.some((exp) => exp.getName() === varName)) {\n isExportedViaSeparateStatement = true\n }\n })\n\n const isExported = isExportedViaKeyword || isExportedViaSeparateStatement\n\n // Get the parameters\n const params = initializer.getParameters()\n const paramsText = params.map((p) => p.getText()).join(', ')\n\n // Get the body\n const body = initializer.getBody()\n if (!body) return\n\n const bodyText = body.getText()\n\n // Build the function body\n let functionBody: string\n const trimmedBody = bodyText.trim()\n\n if (trimmedBody.startsWith('(') && trimmedBody.endsWith(')')) {\n // Parenthesized expression like: (\n // <button />\n // )\n const innerBody = trimmedBody.slice(1, -1).trim()\n functionBody = `{\\n return ${innerBody}\\n }`\n } else if (trimmedBody.startsWith('{')) {\n // Already a block statement\n functionBody = bodyText\n } else {\n // Simple JSX expression like: <button />\n functionBody = `{\\n return ${bodyText}\\n }`\n }\n\n const funcText = `${isExported ? 'export ' : ''}function ${varName}(${paramsText}) ${functionBody}`\n\n // Replace the variable statement with function declaration\n varStatement.replaceWithText(funcText)\n\n // Remove from separate export statements if it was exported that way\n if (isExportedViaSeparateStatement) {\n sourceFile.getExportDeclarations().forEach((exportDecl) => {\n const namedExports = exportDecl.getNamedExports()\n const matchingExports = namedExports.filter((namedExport) => namedExport.getName() === varName)\n\n if (matchingExports.length > 0) {\n matchingExports.forEach((namedExport) => {\n namedExport.remove()\n })\n\n // Remove the entire export declaration if no exports remain\n if (exportDecl.getNamedExports().length === 0) {\n exportDecl.remove()\n }\n }\n })\n }\n })\n }\n}\n","import { StructureKind, VariableDeclarationKind } from 'ts-morph'\nimport { isFunctionComponent } from '../utils/react'\nimport { Transformer } from '../utils/transformer'\n\nexport const enforceFunctionComponent: Transformer = {\n match: ({ config }) => config.enforceFunctionComponent,\n transform: async ({ sourceFile, config: { enforceDirectExports } }) => {\n sourceFile.getFunctions().forEach((func) => {\n if (!isFunctionComponent(func)) { return }\n\n const funcName = func.getName()\n if (!funcName) { return }\n\n const isExportedViaKeyword = func.isExported()\n let isExportedViaSeparateStatement = false\n\n sourceFile.getExportDeclarations().forEach((exportDecl) => {\n const namedExports = exportDecl.getNamedExports()\n if (namedExports.some((exp) => exp.getName() === funcName)) {\n isExportedViaSeparateStatement = true\n }\n })\n\n const isExported = enforceDirectExports && (isExportedViaKeyword || isExportedViaSeparateStatement)\n\n // Get the parameters with their type annotations\n const params = func.getParameters()\n const param = params[0]\n const type = param.getTypeNode() ?? param.getType()\n const typeText = type.getText()\n param.removeType()\n const typeAnnotation = typeText === 'any' ? 'React.FunctionComponent' : `React.FunctionComponent<${typeText}>`\n\n const index = func.getChildIndex()\n sourceFile.insertVariableStatement(index, {\n declarations: [{\n name: funcName,\n type: typeAnnotation,\n initializer: (writer) => {\n writer.write('(').write(func.getParameters().map((p) => p.getText()).join(', ')).write(')')\n const returnType = func.getReturnTypeNode()?.getText()\n if (returnType) { writer.write(`: ${returnType}`) }\n writer.write(' => ')\n const bodyText = func.getBody()?.getText() ?? '{}'\n writer.block(() => { writer.write(bodyText.replace(/^{|}$/g, '').trim()) })\n }\n }],\n declarationKind: VariableDeclarationKind.Const,\n kind: StructureKind.VariableStatement,\n isExported\n })\n func.remove()\n })\n }\n}\n","import { Node, SyntaxKind } from 'ts-morph'\nimport { REACT_APIS, REACT_HOOKS, REACT_TYPES } from '../utils/react'\nimport { Transformer } from '../utils/transformer'\n\nexport const enforceNamedImports: Transformer = {\n match: ({ config }) => config.enforceNamedImports,\n transform: async ({ sourceFile }) => {\n // Find React import declaration\n const reactImport = sourceFile.getImportDeclarations().find((importDeclaration) => {\n return importDeclaration.getModuleSpecifier().getLiteralValue() === 'react'\n })\n\n // If no React import exists, no transformation needed\n if (!reactImport) { return }\n\n // Check if it's already using named imports only (early exit if enforceNamedImports is disabled)\n const namespaceImport = reactImport.getNamespaceImport()\n if (!namespaceImport) { return }\n\n // Initialize tracking sets\n const typeImportsNeeded = new Set<string>()\n const valueImportsNeeded = new Set<string>()\n\n // ============================================================\n // Phase 2 & 3: Transform Type References and Hook Calls\n // (Single-pass traversal for efficiency)\n // ============================================================\n\n sourceFile.forEachDescendant((node) => {\n // Handle TypeReference nodes (Phase 2)\n if (node.getKind() === SyntaxKind.TypeReference) {\n const typeRef = node.asKind(SyntaxKind.TypeReference)\n if (!typeRef) return\n\n const typeName = typeRef.getTypeName()\n\n // Check if it's a qualified name like React.ComponentProps or React.HTMLAttributes\n if (Node.isQualifiedName(typeName)) {\n const left = typeName.getLeft().getText()\n const right = typeName.getRight().getText()\n\n if (left === 'React') {\n // Check if it's a known React type\n if (REACT_TYPES.includes(right)) {\n typeName.replaceWithText(right)\n typeImportsNeeded.add(right)\n }\n }\n }\n }\n\n // Handle PropertyAccessExpression nodes (Phase 3)\n // This handles both React.Component and React.SomethingRef patterns\n if (node.getKind() === SyntaxKind.PropertyAccessExpression) {\n const propAccess = node.asKind(SyntaxKind.PropertyAccessExpression)\n if (!propAccess) return\n\n const expr = propAccess.getExpression()\n const name = propAccess.getName()\n\n if (expr.getText() === 'React') {\n // Check if it's a known hook or API\n if (REACT_HOOKS.includes(name) || REACT_APIS.includes(name) || REACT_TYPES.includes(name)) {\n propAccess.replaceWithText(name)\n\n // Determine if it's a type or value import\n if (REACT_TYPES.includes(name)) {\n typeImportsNeeded.add(name)\n } else if (REACT_HOOKS.includes(name) || REACT_APIS.includes(name)) {\n valueImportsNeeded.add(name)\n }\n }\n }\n }\n })\n\n // ============================================================\n // Phase 4: Import Management\n // ============================================================\n\n // Only add named imports and remove namespace if we have imports to add\n if (typeImportsNeeded.size > 0 || valueImportsNeeded.size > 0) {\n // Remove namespace import FIRST (before adding named imports)\n reactImport.removeNamespaceImport()\n\n // Add type imports (with 'type' keyword for type-only imports)\n const typeImportsArray = Array.from(typeImportsNeeded).sort()\n for (const typeName of typeImportsArray) {\n reactImport.addNamedImport({\n name: typeName,\n isTypeOnly: true\n })\n }\n\n // Add value imports\n const valueImportsArray = Array.from(valueImportsNeeded).sort()\n for (const valueName of valueImportsArray) {\n reactImport.addNamedImport(valueName)\n }\n }\n }\n}\n","import { FormatCodeSettings, ts } from 'ts-morph'\nimport { PartialDeep } from 'type-fest'\n\nexport interface TransformerConfig {\n enforceDirectExports: boolean\n enforceFunctionComponent: boolean\n enforceNamedImports: boolean\n enforceFormat: boolean\n format: FormatCodeSettings\n}\n\nexport function mergeConfig({ format, ...config }: PartialDeep<TransformerConfig> = {}): TransformerConfig {\n return {\n enforceDirectExports: false,\n enforceFunctionComponent: false,\n enforceNamedImports: false,\n enforceFormat: false,\n format: {\n indentSize: 2,\n convertTabsToSpaces: true,\n indentStyle: ts.IndentStyle.Smart,\n indentMultiLineObjectLiteralBeginningOnBlankLine: true,\n ensureNewLineAtEndOfFile: true,\n semicolons: ts.SemicolonPreference.Remove,\n trimTrailingWhitespace: true,\n ...format\n },\n ...config\n }\n}\n","import { mkdtemp } from 'fs/promises'\nimport { tmpdir } from 'os'\nimport { join } from 'path'\n\nexport async function createTempSourceFile(filename: string) {\n const dir = await mkdtemp(join(tmpdir(), 'ts-morph-react-'))\n return join(dir, filename)\n}\n","import { Node, SourceFile, ts } from 'ts-morph'\n\nexport enum SeparationIntent { IGNORE, COMBINE, SEPARATE }\n\nexport interface SeparationEntry {\n range: [number, number]\n intent: SeparationIntent\n}\n\nexport function enforeLineSeparation(sourceFile: SourceFile, predicate: (cur: Node<ts.Node>, prev: Node<ts.Node>, triviaWidth: number) => SeparationIntent) {\n const instructions: SeparationEntry[] = []\n const syntaxList = sourceFile.getChildSyntaxListOrThrow()\n for (let index = syntaxList.getChildCount() - 1; index > 0; index -= 1) {\n const prev = syntaxList.getChildAtIndex(index - 1)\n const cur = syntaxList.getChildAtIndex(index)\n const intent = predicate(cur, prev, cur.getLeadingTriviaWidth())\n instructions.push({ range: [prev.getEnd(), cur.getStart()], intent })\n }\n instructions.forEach(({ range, intent }) => {\n if (intent === SeparationIntent.COMBINE) {\n sourceFile.replaceText(range, '\\n')\n } else if (intent === SeparationIntent.SEPARATE) {\n sourceFile.replaceText(range, '\\n\\n')\n }\n })\n}\n","import { ImportDeclaration } from 'ts-morph'\nimport { Transformer } from '../utils/transformer'\nimport { enforeLineSeparation, SeparationIntent } from '../utils/trivia'\n\nexport const enforceFormat: Transformer = {\n match: ({ config }) => config.enforceFormat,\n transform: async ({ sourceFile, config: { format } }) => {\n sourceFile.formatText(format)\n enforeLineSeparation(sourceFile, (cur, prev) => (prev instanceof ImportDeclaration && cur instanceof ImportDeclaration)\n ? SeparationIntent.COMBINE\n : SeparationIntent.SEPARATE\n )\n sourceFile.organizeImports(format)\n }\n}\n","import { SourceFile } from 'ts-morph'\nimport { PartialDeep } from 'type-fest'\nimport { enforceDirectExports } from '../transformers/enforceDirectExports'\nimport { enforceFormat } from '../transformers/enforceFormat'\nimport { enforceFunctionComponent } from '../transformers/enforceFunctionComponent'\nimport { enforceNamedImports } from '../transformers/enforceNamedImports'\nimport { mergeConfig, TransformerConfig } from './config'\nimport { TransformerParams } from './transformer'\n\nexport const transformers = [enforceDirectExports, enforceFunctionComponent, enforceNamedImports, enforceFormat]\n\nexport async function transform(\n sourceFile: SourceFile,\n config: PartialDeep<TransformerConfig> = {}\n): Promise<void> {\n const params: TransformerParams = { config: mergeConfig(config), sourceFile }\n for (const transformer of transformers) {\n if (transformer.match(params)) {\n await transformer.transform(params)\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/react.ts","../src/transformers/enforceDirectExports.ts","../src/transformers/enforceEslint.ts","../src/utils/trivia.ts","../src/transformers/enforceFormat.ts","../src/transformers/enforceFunctionComponent.ts","../src/transformers/enforceNamedImports.ts","../src/transformers/enforcePrettier.ts","../src/utils/config.ts","../src/utils/transform.ts"],"names":["REACT_TYPES","REACT_HOOKS","REACT_APIS","isReactComponent","varDecl","initializer","descendants","SyntaxKind","selfClosing","Node","body","bodyDescendants","bodySelfClosing","isForwardRefComponent","text","isFunctionComponent","func","enforceDirectExports","config","sourceFile","funcName","isExportedViaSeparateStatement","exportDecl","exp","matchingExports","namedExport","varName","varStatement","isExportedViaKeyword","isExported","paramsText","p","bodyText","functionBody","trimmedBody","funcText","enforceEslint","filePath","cwd","dirname","eslint","ESLint","tseslint","stylistic","result","SeparationIntent","enforeLineSeparation","predicate","instructions","syntaxList","index","prev","cur","intent","range","enforceFormat","ImportDeclaration","enforceFunctionComponent","param","typeText","typeAnnotation","writer","returnType","VariableDeclarationKind","StructureKind","enforceNamedImports","reactImport","importDeclaration","typeImportsNeeded","valueImportsNeeded","node","typeRef","typeName","left","right","propAccess","expr","name","typeImportsArray","valueImportsArray","valueName","enforcePrettier","formattedText","format","mergeConfig","prettier","ts","transformers","transform","params","transformer"],"mappings":"gQAEO,IAAMA,CAAAA,CAAc,CACzB,iBACA,uBAAA,CACA,0BAAA,CACA,IAAA,CACA,mBAAA,CACA,WAAA,CACA,cAAA,CACA,MACA,WAAA,CACA,kBAAA,CACA,eAAA,CACA,gBAAA,CACA,eAAA,CACA,eAAA,CACA,oBACA,cACF,CAAA,CAEaC,CAAAA,CAAc,CACzB,UAAA,CACA,WAAA,CACA,cACA,SAAA,CACA,QAAA,CACA,YAAA,CACA,YAAA,CACA,qBAAA,CACA,iBAAA,CACA,gBACA,eAAA,CACA,kBAAA,CACA,OAAA,CACA,sBACF,CAAA,CAEaC,CAAAA,CAAa,CACxB,YAAA,CACA,MAAA,CACA,MAAA,CACA,eAAA,CACA,eAAA,CACA,cAAA,CACA,iBACA,UAAA,CACA,UAAA,CACA,YAAA,CACA,UACF,EAEO,SAASC,EAAiBC,CAAAA,CAAuC,CACtE,GAAI,CACF,IAAMC,CAAAA,CAAcD,EAAQ,cAAA,IAAiB,CAC7C,GAAI,CAACC,CAAAA,CAAa,OAAO,GAGzB,IAAMC,CAAAA,CAAcD,CAAAA,CAAY,oBAAA,GAAuBE,UAAAA,CAAW,UAAU,GAAK,EAAC,CAC5EC,CAAAA,CAAcH,CAAAA,CAAY,oBAAA,GAAuBE,UAAAA,CAAW,qBAAqB,CAAA,EAAK,EAAC,CAE7F,GAAID,CAAAA,CAAY,MAAA,CAAS,GAAKE,CAAAA,CAAY,MAAA,CAAS,CAAA,CAAK,OAAO,CAAA,CAAA,CAG/D,GAAIC,KAAK,eAAA,CAAgBJ,CAAW,CAAA,CAAG,CACrC,IAAMK,CAAAA,CAAOL,EAAY,OAAA,IAAU,CACnC,GAAIK,CAAAA,CAAM,CACR,IAAMC,EAAkBD,CAAAA,CAAK,oBAAA,GAAuBH,UAAAA,CAAW,UAAU,CAAA,EAAK,GACxEK,CAAAA,CAAkBF,CAAAA,CAAK,oBAAA,GAAuBH,UAAAA,CAAW,qBAAqB,CAAA,EAAK,EAAC,CAC1F,OAAOI,CAAAA,CAAgB,MAAA,CAAS,CAAA,EAAKC,CAAAA,CAAgB,OAAS,CAChE,CACF,CAEA,OAAO,CAAA,CACT,CAAA,KAAQ,CACN,OAAO,MACT,CACF,CAEO,SAASC,CAAAA,CAAsBT,EAAuC,CAC3E,GAAI,CACF,IAAMC,CAAAA,CAAcD,CAAAA,CAAQ,kBAAiB,CAC7C,GAAI,CAACC,CAAAA,CAAa,OAAO,CAAA,CAAA,CAEzB,IAAMS,CAAAA,CAAOT,CAAAA,CAAY,OAAA,IAAU,CACnC,OAAO,CAAA,EAAAS,GAAM,QAAA,CAAS,aAAa,CAAA,EAAKA,CAAAA,EAAM,QAAA,CAAS,mBAAmB,EAC5E,CAAA,KAAQ,CACN,OAAO,MACT,CACF,CAEO,SAASC,CAAAA,CAAoBC,CAAAA,CAAoC,CACtE,GAAI,CACF,IAAMV,EAAcU,CAAAA,CAAK,oBAAA,GAAuBT,UAAAA,CAAW,UAAU,CAAA,EAAK,GACpEC,CAAAA,CAAcQ,CAAAA,CAAK,oBAAA,GAAuBT,UAAAA,CAAW,qBAAqB,CAAA,EAAK,EAAC,CACtF,OAAID,CAAAA,CAAY,MAAA,CAAS,CAAA,EAAKE,CAAAA,CAAY,OAAS,CAErD,CAAA,KAAQ,CACN,OAAO,MACT,CACF,CChGO,IAAMS,CAAAA,CAAoC,CAC/C,KAAA,CAAO,CAAC,CAAE,OAAAC,CAAO,CAAA,GAAMA,CAAAA,CAAO,oBAAA,CAC9B,SAAA,CAAW,MAAO,CAAE,UAAA,CAAAC,CAAW,CAAA,GAAM,CAEnCA,CAAAA,CAAW,YAAA,GAAe,OAAA,CAASH,CAAAA,EAAS,CAK1C,GAHI,CAACD,CAAAA,CAAoBC,CAAI,CAAA,EAGzBA,CAAAA,CAAK,UAAA,EAAW,EAAKA,CAAAA,CAAK,gBAAA,GAAsB,OAEpD,IAAMI,CAAAA,CAAWJ,CAAAA,CAAK,OAAA,EAAQ,CAG1BK,EAAiC,KAAA,CACrCF,CAAAA,CAAW,qBAAA,EAAsB,CAAE,OAAA,CAASG,CAAAA,EAAe,CACpCA,CAAAA,CAAW,eAAA,EAAgB,CAC/B,IAAA,CAAMC,CAAAA,EAAQA,CAAAA,CAAI,SAAQ,GAAMH,CAAQ,CAAA,GACvDC,CAAAA,CAAiC,IAAA,EAErC,CAAC,EAGGA,CAAAA,GAEFL,CAAAA,CAAK,aAAA,CAAc,IAAI,CAAA,CAGvBG,CAAAA,CAAW,uBAAsB,CAAE,OAAA,CAASG,CAAAA,EAAe,CAEzD,IAAME,CAAAA,CADeF,EAAW,eAAA,EAAgB,CACX,MAAA,CAAQG,CAAAA,EAAgBA,CAAAA,CAAY,OAAA,KAAcL,CAAQ,CAAA,CAC3FI,CAAAA,CAAgB,MAAA,CAAS,CAAA,GAC3BA,CAAAA,CAAgB,QAASC,CAAAA,EAAgB,CAAEA,CAAAA,CAAY,MAAA,GAAS,CAAC,EAC7DH,CAAAA,CAAW,eAAA,EAAgB,CAAE,MAAA,GAAW,CAAA,EAAKA,CAAAA,CAAW,QAAO,EAEvE,CAAC,CAAA,EAEL,CAAC,CAAA,CAGDH,CAAAA,CAAW,yBAAwB,CAAE,OAAA,CAASf,CAAAA,EAAY,CAKxD,GAHI,CAACD,EAAiBC,CAAO,CAAA,EAGzBS,CAAAA,CAAsBT,CAAO,CAAA,CAAG,OAEpC,IAAMC,CAAAA,CAAcD,CAAAA,CAAQ,cAAA,EAAe,CAC3C,GAAI,CAACC,GAAe,CAACI,IAAAA,CAAK,eAAA,CAAgBJ,CAAW,CAAA,CAAG,OAExD,IAAMqB,CAAAA,CAAUtB,CAAAA,CAAQ,OAAA,EAAQ,CAC1BuB,CAAAA,CAAevB,CAAAA,CAAQ,sBAAqB,CAClD,GAAI,CAACuB,CAAAA,CAAc,OAEnB,IAAMC,EAAuBD,CAAAA,CAAa,gBAAA,EAAiB,CAGvDN,CAAAA,CAAiC,KAAA,CACrCF,CAAAA,CAAW,uBAAsB,CAAE,OAAA,CAASG,CAAAA,EAAe,CACpCA,CAAAA,CAAW,eAAA,GACf,IAAA,CAAMC,CAAAA,EAAQA,CAAAA,CAAI,OAAA,EAAQ,GAAMG,CAAO,IACtDL,CAAAA,CAAiC,IAAA,EAErC,CAAC,CAAA,CAED,IAAMQ,CAAAA,CAAaD,GAAwBP,CAAAA,CAIrCS,CAAAA,CADSzB,CAAAA,CAAY,aAAA,EAAc,CACf,GAAA,CAAK0B,GAAMA,CAAAA,CAAE,OAAA,EAAS,CAAA,CAAE,IAAA,CAAK,IAAI,EAGrDrB,CAAAA,CAAOL,CAAAA,CAAY,OAAA,EAAQ,CACjC,GAAI,CAACK,EAAM,OAEX,IAAMsB,CAAAA,CAAWtB,CAAAA,CAAK,OAAA,EAAQ,CAG1BuB,EACEC,CAAAA,CAAcF,CAAAA,CAAS,IAAA,EAAK,CAE9BE,CAAAA,CAAY,UAAA,CAAW,GAAG,CAAA,EAAKA,CAAAA,CAAY,QAAA,CAAS,GAAG,CAAA,CAKzDD,CAAAA,CAAe,CAAA;AAAA,WAAA,EADGC,EAAY,KAAA,CAAM,CAAA,CAAG,EAAE,CAAA,CAAE,MACF;AAAA,GAAA,CAAA,CAChCA,EAAY,UAAA,CAAW,GAAG,CAAA,CAEnCD,CAAAA,CAAeD,EAGfC,CAAAA,CAAe,CAAA;AAAA,WAAA,EAAiBD,CAAQ;AAAA,GAAA,CAAA,CAG1C,IAAMG,CAAAA,CAAW,CAAA,EAAGN,CAAAA,CAAa,SAAA,CAAY,EAAE,CAAA,SAAA,EAAYH,CAAO,CAAA,CAAA,EAAII,CAAU,CAAA,EAAA,EAAKG,CAAY,CAAA,CAAA,CAGjGN,CAAAA,CAAa,eAAA,CAAgBQ,CAAQ,CAAA,CAGjCd,CAAAA,EACFF,CAAAA,CAAW,qBAAA,EAAsB,CAAE,OAAA,CAASG,CAAAA,EAAe,CAEzD,IAAME,CAAAA,CADeF,CAAAA,CAAW,eAAA,GACK,MAAA,CAAQG,CAAAA,EAAgBA,CAAAA,CAAY,OAAA,EAAQ,GAAMC,CAAO,CAAA,CAE1FF,CAAAA,CAAgB,MAAA,CAAS,CAAA,GAC3BA,CAAAA,CAAgB,OAAA,CAASC,CAAAA,EAAgB,CACvCA,CAAAA,CAAY,MAAA,GACd,CAAC,CAAA,CAGGH,CAAAA,CAAW,eAAA,EAAgB,CAAE,MAAA,GAAW,CAAA,EAC1CA,CAAAA,CAAW,MAAA,EAAO,EAGxB,CAAC,EAEL,CAAC,EACH,CACF,ECtHO,IAAMc,CAAAA,CAA6B,CACxC,MAAO,CAAC,CAAE,MAAA,CAAAlB,CAAO,CAAA,GAAMA,CAAAA,CAAO,aAAA,CAC9B,SAAA,CAAW,MAAO,CAAE,UAAA,CAAAC,CAAAA,CAAY,MAAA,CAAAD,CAAO,CAAA,GAAM,CAC3C,IAAMmB,CAAAA,CAAWlB,CAAAA,CAAW,WAAA,EAAY,CAClCmB,CAAAA,CAAMC,OAAAA,CAAQF,CAAQ,CAAA,CACtBG,CAAAA,CAAS,IAAIC,MAAAA,CAAO,CACxB,GAAA,CAAK,IAAA,CACL,GAAA,CAAAH,CAAAA,CACA,mBAAoB,IAAA,CACpB,cAAA,CAAgB,CAAC,CACf,QAAA,CAAU,GAAA,CACV,eAAA,CAAiB,CACf,MAAA,CAAQI,CAAAA,CAAS,MAAA,CACjB,WAAA,CAAa,IAAA,CACb,UAAA,CAAY,QAAA,CACZ,aAAA,CAAe,CAAE,YAAA,CAAc,CAAE,GAAA,CAAK,IAAK,CAAE,CAC/C,CAAA,CACA,KAAA,CAAO,CAAC,sBAAsB,CAAA,CAC9B,OAAA,CAAS,CAAE,YAAA,CAAcC,CAAU,CAAA,CACnC,KAAA,CAAOzB,CAAAA,CAAO,MAChB,CAAC,CACH,CAAC,CAAA,CAEK,CAAC0B,CAAM,CAAA,CAAI,MAAMJ,CAAAA,CAAO,QAAA,CAASrB,CAAAA,CAAW,WAAA,EAAY,CAAG,CAAE,QAAA,CAAAkB,CAAS,CAAC,CAAA,CACzEO,CAAAA,EAAQ,MAAA,EAAUzB,CAAAA,CAAW,eAAA,CAAgByB,CAAAA,CAAO,MAAM,EAChE,CACF,EC9BO,IAAKC,CAAAA,CAAAA,CAAAA,CAAAA,GAAmBA,CAAAA,CAAAA,CAAAA,CAAA,MAAA,CAAA,CAAA,CAAA,CAAA,QAAA,CAAQA,CAAAA,CAAAA,CAAAA,CAAA,OAAA,CAAA,CAAA,CAAA,CAAA,SAAA,CAASA,CAAAA,CAAAA,CAAAA,CAAA,QAAA,CAAA,CAAA,CAAA,CAAA,UAAA,CAApCA,CAAAA,CAAAA,EAAAA,CAAAA,EAAA,EAAA,EAOL,SAASC,CAAAA,CAAqB3B,CAAAA,CAAwB4B,CAAAA,CAA+F,CAC1J,IAAMC,EAAkC,EAAC,CACnCC,CAAAA,CAAa9B,CAAAA,CAAW,yBAAA,EAA0B,CACxD,IAAA,IAAS+B,CAAAA,CAAQD,CAAAA,CAAW,aAAA,EAAc,CAAI,CAAA,CAAGC,CAAAA,CAAQ,CAAA,CAAGA,CAAAA,EAAS,CAAA,CAAG,CACtE,IAAMC,CAAAA,CAAOF,CAAAA,CAAW,eAAA,CAAgBC,CAAAA,CAAQ,CAAC,CAAA,CAC3CE,CAAAA,CAAMH,CAAAA,CAAW,eAAA,CAAgBC,CAAK,CAAA,CACtCG,CAAAA,CAASN,CAAAA,CAAUK,CAAAA,CAAKD,CAAAA,CAAMC,EAAI,qBAAA,EAAuB,CAAA,CAC/DJ,CAAAA,CAAa,IAAA,CAAK,CAAE,KAAA,CAAO,CAACG,CAAAA,CAAK,MAAA,EAAO,CAAGC,CAAAA,CAAI,QAAA,EAAU,CAAA,CAAG,MAAA,CAAAC,CAAO,CAAC,EACtE,CACAL,CAAAA,CAAa,OAAA,CAAQ,CAAC,CAAE,KAAA,CAAAM,CAAAA,CAAO,MAAA,CAAAD,CAAO,CAAA,GAAM,CACtCA,CAAAA,GAAW,CAAA,CACblC,CAAAA,CAAW,YAAYmC,CAAAA,CAAO;AAAA,CAAI,CAAA,CACzBD,CAAAA,GAAW,CAAA,EACpBlC,CAAAA,CAAW,YAAYmC,CAAAA,CAAO;;AAAA,CAAM,EAExC,CAAC,EACH,CCrBO,IAAMC,EAA6B,CACxC,KAAA,CAAO,CAAC,CAAE,OAAArC,CAAO,CAAA,GAAMA,EAAO,aAAA,CAC9B,SAAA,CAAW,MAAO,CAAE,UAAA,CAAAC,CAAAA,CAAY,MAAA,CAAAD,CAAO,CAAA,GAAM,CAC3C4B,EAAqB3B,CAAAA,CAAY,CAACiC,EAAKD,CAAAA,GAAUA,CAAAA,YAAgBK,iBAAAA,EAAqBJ,CAAAA,YAAeI,qBAGrG,CAAA,CACArC,CAAAA,CAAW,iBAAgB,CAC3BA,CAAAA,CAAW,WAAWD,CAAAA,CAAO,MAAM,EACrC,CACF,ECVO,IAAMuC,CAAAA,CAAwC,CACnD,MAAO,CAAC,CAAE,OAAAvC,CAAO,CAAA,GAAMA,EAAO,wBAAA,CAC9B,SAAA,CAAW,MAAO,CAAE,WAAAC,CAAAA,CAAY,MAAA,CAAQ,CAAE,oBAAA,CAAAF,CAAqB,CAAE,CAAA,GAAM,CACrEE,CAAAA,CAAW,YAAA,GAAe,OAAA,CAASH,CAAAA,EAAS,CAC1C,GAAI,CAACD,EAAoBC,CAAI,CAAA,CAAK,OAElC,IAAMI,EAAWJ,CAAAA,CAAK,OAAA,EAAQ,CAC9B,GAAI,CAACI,CAAAA,CAAY,OAEjB,IAAMQ,CAAAA,CAAuBZ,EAAK,UAAA,EAAW,CACzCK,EAAiC,KAAA,CAErCF,CAAAA,CAAW,uBAAsB,CAAE,OAAA,CAASG,CAAAA,EAAe,CACpCA,EAAW,eAAA,EAAgB,CAC/B,KAAMC,CAAAA,EAAQA,CAAAA,CAAI,SAAQ,GAAMH,CAAQ,CAAA,GACvDC,CAAAA,CAAiC,MAErC,CAAC,CAAA,CAED,IAAMQ,CAAAA,CAAaZ,CAAAA,GAAyBW,GAAwBP,CAAAA,CAAAA,CAI9DqC,CAAAA,CADS1C,CAAAA,CAAK,aAAA,GACC,CAAC,CAAA,CAEhB2C,GADOD,CAAAA,CAAM,WAAA,IAAiBA,CAAAA,CAAM,OAAA,EAAQ,EAC5B,OAAA,GACtBA,CAAAA,CAAM,UAAA,GACN,IAAME,CAAAA,CAAiBD,IAAa,KAAA,CAAQ,yBAAA,CAA4B,CAAA,wBAAA,EAA2BA,CAAQ,IAErGT,CAAAA,CAAQlC,CAAAA,CAAK,eAAc,CACjCG,CAAAA,CAAW,wBAAwB+B,CAAAA,CAAO,CACxC,YAAA,CAAc,CAAC,CACb,IAAA,CAAM9B,CAAAA,CACN,KAAMwC,CAAAA,CACN,WAAA,CAAcC,GAAW,CACvBA,CAAAA,CAAO,KAAA,CAAM,GAAG,EAAE,KAAA,CAAM7C,CAAAA,CAAK,aAAA,EAAc,CAAE,IAAKe,CAAAA,EAAMA,CAAAA,CAAE,OAAA,EAAS,EAAE,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAC1F,IAAM+B,CAAAA,CAAa9C,CAAAA,CAAK,mBAAkB,EAAG,OAAA,GACzC8C,CAAAA,EAAcD,CAAAA,CAAO,MAAM,CAAA,EAAA,EAAKC,CAAU,CAAA,CAAE,CAAA,CAChDD,EAAO,KAAA,CAAM,MAAM,EACnB,IAAM7B,CAAAA,CAAWhB,EAAK,OAAA,EAAQ,EAAG,OAAA,EAAQ,EAAK,KAC9C6C,CAAAA,CAAO,KAAA,CAAM,IAAM,CAAEA,CAAAA,CAAO,MAAM7B,CAAAA,CAAS,OAAA,CAAQ,QAAA,CAAU,EAAE,EAAE,IAAA,EAAM,EAAE,CAAC,EAC5E,CACF,CAAC,CAAA,CACD,eAAA,CAAiB+B,uBAAAA,CAAwB,MACzC,IAAA,CAAMC,aAAAA,CAAc,kBACpB,UAAA,CAAAnC,CACF,CAAC,CAAA,CACDb,CAAAA,CAAK,MAAA,GACP,CAAC,EACH,CACF,EClDO,IAAMiD,EAAmC,CAC9C,KAAA,CAAO,CAAC,CAAE,OAAA/C,CAAO,CAAA,GAAMA,CAAAA,CAAO,mBAAA,CAC9B,UAAW,MAAO,CAAE,WAAAC,CAAW,CAAA,GAAM,CAEnC,IAAM+C,CAAAA,CAAc/C,CAAAA,CAAW,qBAAA,GAAwB,IAAA,CAAMgD,CAAAA,EACpDA,EAAkB,kBAAA,EAAmB,CAAE,iBAAgB,GAAM,OACrE,CAAA,CAOD,GAJI,CAACD,CAAAA,EAID,CADoBA,EAAY,kBAAA,EAAmB,CAC/B,OAGxB,IAAME,CAAAA,CAAoB,IAAI,GAAA,CACxBC,EAAqB,IAAI,GAAA,CA4D/B,GArDAlD,CAAAA,CAAW,iBAAA,CAAmBmD,GAAS,CAErC,GAAIA,CAAAA,CAAK,OAAA,KAAc/D,UAAAA,CAAW,aAAA,CAAe,CAC/C,IAAMgE,CAAAA,CAAUD,EAAK,MAAA,CAAO/D,UAAAA,CAAW,aAAa,CAAA,CACpD,GAAI,CAACgE,CAAAA,CAAS,OAEd,IAAMC,CAAAA,CAAWD,EAAQ,WAAA,EAAY,CAGrC,GAAI9D,IAAAA,CAAK,gBAAgB+D,CAAQ,CAAA,CAAG,CAClC,IAAMC,CAAAA,CAAOD,EAAS,OAAA,EAAQ,CAAE,OAAA,EAAQ,CAClCE,EAAQF,CAAAA,CAAS,QAAA,EAAS,CAAE,OAAA,GAE9BC,CAAAA,GAAS,OAAA,EAEPzE,CAAAA,CAAY,QAAA,CAAS0E,CAAK,CAAA,GAC5BF,CAAAA,CAAS,gBAAgBE,CAAK,CAAA,CAC9BN,EAAkB,GAAA,CAAIM,CAAK,CAAA,EAGjC,CACF,CAIA,GAAIJ,CAAAA,CAAK,SAAQ,GAAM/D,UAAAA,CAAW,yBAA0B,CAC1D,IAAMoE,CAAAA,CAAaL,CAAAA,CAAK,OAAO/D,UAAAA,CAAW,wBAAwB,EAClE,GAAI,CAACoE,EAAY,OAEjB,IAAMC,CAAAA,CAAOD,CAAAA,CAAW,eAAc,CAChCE,CAAAA,CAAOF,EAAW,OAAA,EAAQ,CAE5BC,EAAK,OAAA,EAAQ,GAAM,OAAA,GAEjB3E,CAAAA,CAAY,SAAS4E,CAAI,CAAA,EAAK3E,EAAW,QAAA,CAAS2E,CAAI,GAAK7E,CAAAA,CAAY,QAAA,CAAS6E,CAAI,CAAA,CAAA,GACtFF,EAAW,eAAA,CAAgBE,CAAI,EAG3B7E,CAAAA,CAAY,QAAA,CAAS6E,CAAI,CAAA,CAC3BT,CAAAA,CAAkB,GAAA,CAAIS,CAAI,GACjB5E,CAAAA,CAAY,QAAA,CAAS4E,CAAI,CAAA,EAAK3E,CAAAA,CAAW,SAAS2E,CAAI,CAAA,GAC/DR,CAAAA,CAAmB,GAAA,CAAIQ,CAAI,CAAA,EAInC,CACF,CAAC,CAAA,CAOGT,EAAkB,IAAA,CAAO,CAAA,EAAKC,CAAAA,CAAmB,IAAA,CAAO,EAAG,CAE7DH,CAAAA,CAAY,uBAAsB,CAGlC,IAAMY,EAAmB,KAAA,CAAM,IAAA,CAAKV,CAAiB,CAAA,CAAE,MAAK,CAC5D,IAAA,IAAWI,KAAYM,CAAAA,CACrBZ,CAAAA,CAAY,eAAe,CACzB,IAAA,CAAMM,CAAAA,CACN,UAAA,CAAY,IACd,CAAC,CAAA,CAIH,IAAMO,CAAAA,CAAoB,KAAA,CAAM,KAAKV,CAAkB,CAAA,CAAE,IAAA,EAAK,CAC9D,QAAWW,CAAAA,IAAaD,CAAAA,CACtBb,EAAY,cAAA,CAAec,CAAS,EAExC,CACF,CACF,MClGaC,CAAAA,CAA+B,CAC1C,MAAO,CAAC,CAAE,MAAA,CAAA/D,CAAO,IAAMA,CAAAA,CAAO,eAAA,CAC9B,UAAW,MAAO,CAAE,WAAAC,CAAAA,CAAY,MAAA,CAAAD,CAAO,CAAA,GAAM,CAC3C,IAAMgE,CAAAA,CAAgB,MAAMC,MAAAA,CAAOhE,CAAAA,CAAW,SAAQ,CAAG,CAAE,MAAA,CAAQ,YAAA,CAAc,GAAGD,CAAAA,CAAO,QAAS,CAAC,CAAA,CACrGC,EAAW,eAAA,CAAgB+D,CAAa,EAE1C,CACF,ECOO,SAASE,EAAY,CAAE,MAAA,CAAA5C,CAAAA,CAAQ,MAAA,CAAA2C,EAAQ,QAAA,CAAAE,CAAAA,CAAU,GAAGnE,CAAO,CAAA,CAAoC,EAAC,CAAsB,CAC3H,OAAO,CACL,qBAAsB,KAAA,CACtB,wBAAA,CAA0B,MAC1B,mBAAA,CAAqB,KAAA,CACrB,cAAe,KAAA,CACf,aAAA,CAAe,KAAA,CACf,eAAA,CAAiB,MACjB,MAAA,CAAQ,CACN,oBAAqB,CAAC,OAAA,CAAS,CAAC,CAAA,CAChC,mBAAA,CAAqB,CAAC,OAAA,CAAS,QAAQ,CAAA,CACvC,iBAAA,CAAmB,CAAC,OAAA,CAAS,OAAO,EACpC,+BAAA,CAAiC,OAAA,CACjC,oCAAA,CAAsC,CAAC,QAAS,CAAE,GAAA,CAAO,EAAG,MAAA,CAAU,CAAA,CAAG,OAAU,CAAE,CAAC,CAAA,CACtF,mCAAA,CAAqC,CAAC,OAAA,CAAS,OAAO,EACtD,iCAAA,CAAmC,CAAC,QAAS,OAAO,CAAA,CACpD,GAAGsB,CACL,EACA,MAAA,CAAQ,CACN,UAAA,CAAY,CAAA,CACZ,oBAAqB,IAAA,CACrB,wBAAA,CAA0B,IAAA,CAC1B,WAAA,CAAa8C,GAAG,WAAA,CAAY,KAAA,CAC5B,WAAYA,EAAAA,CAAG,mBAAA,CAAoB,OACnC,sBAAA,CAAwB,IAAA,CACxB,GAAGH,CACL,EACA,QAAA,CAAU,CACR,KAAM,KAAA,CACN,WAAA,CAAa,KACb,cAAA,CAAgB,IAAA,CAChB,WAAA,CAAa,QAAA,CACb,gBAAiB,IAAA,CACjB,UAAA,CAAY,WACZ,UAAA,CAAY,GAAA,CACZ,GAAGE,CACL,CAAA,CACA,GAAGnE,CACL,CACF,CC7CO,IAAMqE,EAAe,CAC1BtE,CAAAA,CACAwC,EACAQ,CAAAA,CACAV,CAAAA,CACAnB,CAAAA,CACA6C,CACF,EAEA,eAAsBO,EAAAA,CACpBrE,EACAD,CAAAA,CAAyC,GAC1B,CACf,IAAMuE,CAAAA,CAA4B,CAAE,OAAQL,CAAAA,CAAYlE,CAAM,EAAG,UAAA,CAAAC,CAAW,EAC5E,IAAA,IAAWuE,CAAAA,IAAeH,CAAAA,CACpBG,CAAAA,CAAY,MAAMD,CAAM,CAAA,EAC1B,MAAMC,CAAAA,CAAY,SAAA,CAAUD,CAAM,EAGxC","file":"index.js","sourcesContent":["import { FunctionDeclaration, Node, SyntaxKind, VariableDeclaration } from 'ts-morph'\n\nexport const REACT_TYPES = [\n 'ComponentProps',\n 'ComponentPropsWithRef',\n 'ComponentPropsWithoutRef',\n 'FC',\n 'FunctionComponent',\n 'ReactNode',\n 'ReactElement',\n 'JSX',\n 'RefObject',\n 'MutableRefObject',\n 'CSSProperties',\n 'HTMLAttributes',\n 'SVGAttributes',\n 'DOMAttributes',\n 'PropsWithChildren',\n 'PropsWithRef'\n]\n\nexport const REACT_HOOKS = [\n 'useState',\n 'useEffect',\n 'useCallback',\n 'useMemo',\n 'useRef',\n 'useContext',\n 'useReducer',\n 'useImperativeHandle',\n 'useLayoutEffect',\n 'useDebugValue',\n 'useTransition',\n 'useDeferredValue',\n 'useId',\n 'useSyncExternalStore'\n]\n\nexport const REACT_APIS = [\n 'forwardRef',\n 'memo',\n 'lazy',\n 'createContext',\n 'createElement',\n 'cloneElement',\n 'isValidElement',\n 'Children',\n 'Fragment',\n 'StrictMode',\n 'Suspense'\n]\n\nexport function isReactComponent(varDecl: VariableDeclaration): boolean {\n try {\n const initializer = varDecl.getInitializer?.()\n if (!initializer) return false\n\n // Check if the initializer contains JSX\n const descendants = initializer.getDescendantsOfKind?.(SyntaxKind.JsxElement) || []\n const selfClosing = initializer.getDescendantsOfKind?.(SyntaxKind.JsxSelfClosingElement) || []\n\n if (descendants.length > 0 || selfClosing.length > 0) { return true }\n\n // Check if it's assigned to an arrow function that returns JSX\n if (Node.isArrowFunction(initializer)) {\n const body = initializer.getBody?.()\n if (body) {\n const bodyDescendants = body.getDescendantsOfKind?.(SyntaxKind.JsxElement) || []\n const bodySelfClosing = body.getDescendantsOfKind?.(SyntaxKind.JsxSelfClosingElement) || []\n return bodyDescendants.length > 0 || bodySelfClosing.length > 0\n }\n }\n\n return false\n } catch {\n return false\n }\n}\n\nexport function isForwardRefComponent(varDecl: VariableDeclaration): boolean {\n try {\n const initializer = varDecl.getInitializer?.()\n if (!initializer) return false\n\n const text = initializer.getText?.()\n return text?.includes('forwardRef(') || text?.includes('React.forwardRef(') ? true : false\n } catch {\n return false\n }\n}\n\nexport function isFunctionComponent(func: FunctionDeclaration): boolean {\n try {\n const descendants = func.getDescendantsOfKind?.(SyntaxKind.JsxElement) || []\n const selfClosing = func.getDescendantsOfKind?.(SyntaxKind.JsxSelfClosingElement) || []\n if (descendants.length > 0 || selfClosing.length > 0) { return true }\n return false\n } catch {\n return false\n }\n}\n","import { Node } from 'ts-morph'\nimport { isForwardRefComponent, isFunctionComponent, isReactComponent } from '../utils/react'\nimport { Transformer } from '../utils/transformer'\n\nexport const enforceDirectExports: Transformer = {\n match: ({ config }) => config.enforceDirectExports,\n transform: async ({ sourceFile }) => {\n // Transform function declarations: add direct export if it's a component\n sourceFile.getFunctions().forEach((func) => {\n // Skip if not a component\n if (!isFunctionComponent(func)) { return }\n\n // Skip if already exported directly\n if (func.isExported() && func.hasExportKeyword()) { return }\n\n const funcName = func.getName()\n\n // Check if it's exported via separate export statement\n let isExportedViaSeparateStatement = false\n sourceFile.getExportDeclarations().forEach((exportDecl) => {\n const namedExports = exportDecl.getNamedExports()\n if (namedExports.some((exp) => exp.getName() === funcName)) {\n isExportedViaSeparateStatement = true\n }\n })\n\n // Only convert if it's a component that should be exported\n if (isExportedViaSeparateStatement) {\n // Add direct export modifier\n func.setIsExported(true)\n\n // Remove from separate export statements\n sourceFile.getExportDeclarations().forEach((exportDecl) => {\n const namedExports = exportDecl.getNamedExports()\n const matchingExports = namedExports.filter((namedExport) => namedExport.getName() === funcName)\n if (matchingExports.length > 0) {\n matchingExports.forEach((namedExport) => { namedExport.remove() })\n if (exportDecl.getNamedExports().length === 0) { exportDecl.remove() }\n }\n })\n }\n })\n\n // Transform const arrow functions to function declarations (if they're components and not forwardRef)\n sourceFile.getVariableDeclarations().forEach((varDecl) => {\n // Skip if not a component\n if (!isReactComponent(varDecl)) return\n\n // Skip forwardRef and memo patterns\n if (isForwardRefComponent(varDecl)) return\n\n const initializer = varDecl.getInitializer()\n if (!initializer || !Node.isArrowFunction(initializer)) return\n\n const varName = varDecl.getName()\n const varStatement = varDecl.getVariableStatement()\n if (!varStatement) return\n\n const isExportedViaKeyword = varStatement.hasExportKeyword()\n\n // Check if it's exported via separate export statement\n let isExportedViaSeparateStatement = false\n sourceFile.getExportDeclarations().forEach((exportDecl) => {\n const namedExports = exportDecl.getNamedExports()\n if (namedExports.some((exp) => exp.getName() === varName)) {\n isExportedViaSeparateStatement = true\n }\n })\n\n const isExported = isExportedViaKeyword || isExportedViaSeparateStatement\n\n // Get the parameters\n const params = initializer.getParameters()\n const paramsText = params.map((p) => p.getText()).join(', ')\n\n // Get the body\n const body = initializer.getBody()\n if (!body) return\n\n const bodyText = body.getText()\n\n // Build the function body\n let functionBody: string\n const trimmedBody = bodyText.trim()\n\n if (trimmedBody.startsWith('(') && trimmedBody.endsWith(')')) {\n // Parenthesized expression like: (\n // <button />\n // )\n const innerBody = trimmedBody.slice(1, -1).trim()\n functionBody = `{\\n return ${innerBody}\\n }`\n } else if (trimmedBody.startsWith('{')) {\n // Already a block statement\n functionBody = bodyText\n } else {\n // Simple JSX expression like: <button />\n functionBody = `{\\n return ${bodyText}\\n }`\n }\n\n const funcText = `${isExported ? 'export ' : ''}function ${varName}(${paramsText}) ${functionBody}`\n\n // Replace the variable statement with function declaration\n varStatement.replaceWithText(funcText)\n\n // Remove from separate export statements if it was exported that way\n if (isExportedViaSeparateStatement) {\n sourceFile.getExportDeclarations().forEach((exportDecl) => {\n const namedExports = exportDecl.getNamedExports()\n const matchingExports = namedExports.filter((namedExport) => namedExport.getName() === varName)\n\n if (matchingExports.length > 0) {\n matchingExports.forEach((namedExport) => {\n namedExport.remove()\n })\n\n // Remove the entire export declaration if no exports remain\n if (exportDecl.getNamedExports().length === 0) {\n exportDecl.remove()\n }\n }\n })\n }\n })\n }\n}\n","import stylistic from '@stylistic/eslint-plugin'\nimport { ESLint } from 'eslint'\nimport { dirname } from 'path'\nimport tseslint from 'typescript-eslint'\nimport { Transformer } from '../utils/transformer'\n\nexport const enforceEslint: Transformer = {\n match: ({ config }) => config.enforceEslint,\n transform: async ({ sourceFile, config }) => {\n const filePath = sourceFile.getFilePath()\n const cwd = dirname(filePath)\n const eslint = new ESLint({\n fix: true,\n cwd,\n overrideConfigFile: true,\n overrideConfig: [{\n basePath: '.',\n languageOptions: {\n parser: tseslint.parser,\n ecmaVersion: 2020,\n sourceType: 'module',\n parserOptions: { ecmaFeatures: { jsx: true } }\n },\n files: ['**/*.{ts,tsx,js,jsx}'],\n plugins: { '@stylistic': stylistic },\n rules: config.eslint\n }]\n })\n\n const [result] = await eslint.lintText(sourceFile.getFullText(), { filePath })\n if (result?.output) { sourceFile.replaceWithText(result.output) }\n }\n}\n","import { Node, SourceFile, ts } from 'ts-morph'\n\nexport enum SeparationIntent { IGNORE, COMBINE, SEPARATE }\n\nexport interface SeparationEntry {\n range: [number, number]\n intent: SeparationIntent\n}\n\nexport function enforeLineSeparation(sourceFile: SourceFile, predicate: (cur: Node<ts.Node>, prev: Node<ts.Node>, triviaWidth: number) => SeparationIntent) {\n const instructions: SeparationEntry[] = []\n const syntaxList = sourceFile.getChildSyntaxListOrThrow()\n for (let index = syntaxList.getChildCount() - 1; index > 0; index -= 1) {\n const prev = syntaxList.getChildAtIndex(index - 1)\n const cur = syntaxList.getChildAtIndex(index)\n const intent = predicate(cur, prev, cur.getLeadingTriviaWidth())\n instructions.push({ range: [prev.getEnd(), cur.getStart()], intent })\n }\n instructions.forEach(({ range, intent }) => {\n if (intent === SeparationIntent.COMBINE) {\n sourceFile.replaceText(range, '\\n')\n } else if (intent === SeparationIntent.SEPARATE) {\n sourceFile.replaceText(range, '\\n\\n')\n }\n })\n}\n","import { ImportDeclaration } from 'ts-morph'\nimport { Transformer } from '../utils/transformer'\nimport { enforeLineSeparation, SeparationIntent } from '../utils/trivia'\n\nexport const enforceFormat: Transformer = {\n match: ({ config }) => config.enforceFormat,\n transform: async ({ sourceFile, config }) => {\n enforeLineSeparation(sourceFile, (cur, prev) => (prev instanceof ImportDeclaration && cur instanceof ImportDeclaration)\n ? SeparationIntent.COMBINE\n : SeparationIntent.SEPARATE\n )\n sourceFile.organizeImports()\n sourceFile.formatText(config.format)\n }\n}\n","import { StructureKind, VariableDeclarationKind } from 'ts-morph'\nimport { isFunctionComponent } from '../utils/react'\nimport { Transformer } from '../utils/transformer'\n\nexport const enforceFunctionComponent: Transformer = {\n match: ({ config }) => config.enforceFunctionComponent,\n transform: async ({ sourceFile, config: { enforceDirectExports } }) => {\n sourceFile.getFunctions().forEach((func) => {\n if (!isFunctionComponent(func)) { return }\n\n const funcName = func.getName()\n if (!funcName) { return }\n\n const isExportedViaKeyword = func.isExported()\n let isExportedViaSeparateStatement = false\n\n sourceFile.getExportDeclarations().forEach((exportDecl) => {\n const namedExports = exportDecl.getNamedExports()\n if (namedExports.some((exp) => exp.getName() === funcName)) {\n isExportedViaSeparateStatement = true\n }\n })\n\n const isExported = enforceDirectExports && (isExportedViaKeyword || isExportedViaSeparateStatement)\n\n // Get the parameters with their type annotations\n const params = func.getParameters()\n const param = params[0]\n const type = param.getTypeNode() ?? param.getType()\n const typeText = type.getText()\n param.removeType()\n const typeAnnotation = typeText === 'any' ? 'React.FunctionComponent' : `React.FunctionComponent<${typeText}>`\n\n const index = func.getChildIndex()\n sourceFile.insertVariableStatement(index, {\n declarations: [{\n name: funcName,\n type: typeAnnotation,\n initializer: (writer) => {\n writer.write('(').write(func.getParameters().map((p) => p.getText()).join(', ')).write(')')\n const returnType = func.getReturnTypeNode()?.getText()\n if (returnType) { writer.write(`: ${returnType}`) }\n writer.write(' => ')\n const bodyText = func.getBody()?.getText() ?? '{}'\n writer.block(() => { writer.write(bodyText.replace(/^{|}$/g, '').trim()) })\n }\n }],\n declarationKind: VariableDeclarationKind.Const,\n kind: StructureKind.VariableStatement,\n isExported\n })\n func.remove()\n })\n }\n}\n","import { Node, SyntaxKind } from 'ts-morph'\nimport { REACT_APIS, REACT_HOOKS, REACT_TYPES } from '../utils/react'\nimport { Transformer } from '../utils/transformer'\n\nexport const enforceNamedImports: Transformer = {\n match: ({ config }) => config.enforceNamedImports,\n transform: async ({ sourceFile }) => {\n // Find React import declaration\n const reactImport = sourceFile.getImportDeclarations().find((importDeclaration) => {\n return importDeclaration.getModuleSpecifier().getLiteralValue() === 'react'\n })\n\n // If no React import exists, no transformation needed\n if (!reactImport) { return }\n\n // Check if it's already using named imports only (early exit if enforceNamedImports is disabled)\n const namespaceImport = reactImport.getNamespaceImport()\n if (!namespaceImport) { return }\n\n // Initialize tracking sets\n const typeImportsNeeded = new Set<string>()\n const valueImportsNeeded = new Set<string>()\n\n // ============================================================\n // Phase 2 & 3: Transform Type References and Hook Calls\n // (Single-pass traversal for efficiency)\n // ============================================================\n\n sourceFile.forEachDescendant((node) => {\n // Handle TypeReference nodes (Phase 2)\n if (node.getKind() === SyntaxKind.TypeReference) {\n const typeRef = node.asKind(SyntaxKind.TypeReference)\n if (!typeRef) return\n\n const typeName = typeRef.getTypeName()\n\n // Check if it's a qualified name like React.ComponentProps or React.HTMLAttributes\n if (Node.isQualifiedName(typeName)) {\n const left = typeName.getLeft().getText()\n const right = typeName.getRight().getText()\n\n if (left === 'React') {\n // Check if it's a known React type\n if (REACT_TYPES.includes(right)) {\n typeName.replaceWithText(right)\n typeImportsNeeded.add(right)\n }\n }\n }\n }\n\n // Handle PropertyAccessExpression nodes (Phase 3)\n // This handles both React.Component and React.SomethingRef patterns\n if (node.getKind() === SyntaxKind.PropertyAccessExpression) {\n const propAccess = node.asKind(SyntaxKind.PropertyAccessExpression)\n if (!propAccess) return\n\n const expr = propAccess.getExpression()\n const name = propAccess.getName()\n\n if (expr.getText() === 'React') {\n // Check if it's a known hook or API\n if (REACT_HOOKS.includes(name) || REACT_APIS.includes(name) || REACT_TYPES.includes(name)) {\n propAccess.replaceWithText(name)\n\n // Determine if it's a type or value import\n if (REACT_TYPES.includes(name)) {\n typeImportsNeeded.add(name)\n } else if (REACT_HOOKS.includes(name) || REACT_APIS.includes(name)) {\n valueImportsNeeded.add(name)\n }\n }\n }\n }\n })\n\n // ============================================================\n // Phase 4: Import Management\n // ============================================================\n\n // Only add named imports and remove namespace if we have imports to add\n if (typeImportsNeeded.size > 0 || valueImportsNeeded.size > 0) {\n // Remove namespace import FIRST (before adding named imports)\n reactImport.removeNamespaceImport()\n\n // Add type imports (with 'type' keyword for type-only imports)\n const typeImportsArray = Array.from(typeImportsNeeded).sort()\n for (const typeName of typeImportsArray) {\n reactImport.addNamedImport({\n name: typeName,\n isTypeOnly: true\n })\n }\n\n // Add value imports\n const valueImportsArray = Array.from(valueImportsNeeded).sort()\n for (const valueName of valueImportsArray) {\n reactImport.addNamedImport(valueName)\n }\n }\n }\n}\n","import { format } from 'prettier'\nimport { Transformer } from '../utils/transformer'\n\nexport const enforcePrettier: Transformer = {\n match: ({ config }) => config.enforcePrettier,\n transform: async ({ sourceFile, config }) => {\n const formattedText = await format(sourceFile.getText(), { parser: 'typescript', ...config.prettier })\n sourceFile.replaceWithText(formattedText)\n\n }\n}\n","import { RulesConfig } from '@eslint/core'\nimport { Options as PrettierOptions } from 'prettier'\nimport { FormatCodeSettings, ts } from 'ts-morph'\nimport { PartialDeep } from 'type-fest'\n\nexport interface TransformerConfig {\n enforceDirectExports: boolean\n enforceFunctionComponent: boolean\n enforceNamedImports: boolean\n enforceFormat: boolean\n enforceEslint: boolean\n enforcePrettier: boolean\n format: FormatCodeSettings\n prettier: PrettierOptions\n eslint: Partial<RulesConfig>\n}\n\nexport function mergeConfig({ eslint, format, prettier, ...config }: PartialDeep<TransformerConfig> = {}): TransformerConfig {\n return {\n enforceDirectExports: false,\n enforceFunctionComponent: false,\n enforceNamedImports: false,\n enforceFormat: false,\n enforceEslint: false,\n enforcePrettier: false,\n eslint: {\n '@stylistic/indent': ['error', 2],\n '@stylistic/quotes': ['error', 'single'],\n '@stylistic/semi': ['error', 'never'],\n '@stylistic/no-trailing-spaces': 'error',\n '@stylistic/no-multiple-empty-lines': ['error', { 'max': 1, 'maxEOF': 0, 'maxBOF': 0 }],\n '@stylistic/function-paren-newline': ['error', 'never'],\n '@stylistic/object-curly-newline': ['error', 'never'],\n ...eslint\n },\n format: {\n indentSize: 2,\n convertTabsToSpaces: true,\n ensureNewLineAtEndOfFile: true,\n indentStyle: ts.IndentStyle.Block,\n semicolons: ts.SemicolonPreference.Remove,\n trimTrailingWhitespace: true,\n ...format\n },\n prettier: {\n semi: false,\n singleQuote: true,\n jsxSingleQuote: true,\n arrowParens: 'always',\n bracketSameLine: true,\n objectWrap: 'collapse',\n printWidth: 120,\n ...prettier\n },\n ...config\n }\n}\n","import { SourceFile } from 'ts-morph'\nimport { PartialDeep } from 'type-fest'\nimport { enforceDirectExports } from '../transformers/enforceDirectExports'\nimport { enforceEslint } from '../transformers/enforceEslint'\nimport { enforceFormat } from '../transformers/enforceFormat'\nimport { enforceFunctionComponent } from '../transformers/enforceFunctionComponent'\nimport { enforceNamedImports } from '../transformers/enforceNamedImports'\nimport { enforcePrettier } from '../transformers/enforcePrettier'\nimport { mergeConfig, TransformerConfig } from './config'\nimport { TransformerParams } from './transformer'\n\nexport const transformers = [\n enforceDirectExports,\n enforceFunctionComponent,\n enforceNamedImports,\n enforceFormat,\n enforceEslint,\n enforcePrettier\n]\n\nexport async function transform(\n sourceFile: SourceFile,\n config: PartialDeep<TransformerConfig> = {}\n): Promise<void> {\n const params: TransformerParams = { config: mergeConfig(config), sourceFile }\n for (const transformer of transformers) {\n if (transformer.match(params)) {\n await transformer.transform(params)\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-morph-react",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "A collection of transformers for ts-morph to refactor react code",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -24,25 +24,30 @@
24
24
  }
25
25
  },
26
26
  "dependencies": {
27
- "ts-morph": "^27.0.2"
28
- },
29
- "devDependencies": {
30
- "@base-ui/react": "^1.0.0",
27
+ "@eslint/core": "^1.0.0",
31
28
  "@eslint/js": "^9.39.2",
32
29
  "@stylistic/eslint-plugin": "^5.6.1",
33
- "@types/node": "^25.0.3",
34
- "cli-highlight": "^2.1.11",
30
+ "@types/eslint-plugin-jsx-a11y": "^6.10.1",
31
+ "@typescript-eslint/typescript-estree": "^8.50.1",
35
32
  "eslint": "^9.39.2",
36
33
  "eslint-plugin-jsx-a11y": "^6.10.2",
37
34
  "eslint-plugin-react": "^7.37.5",
38
35
  "eslint-plugin-react-hooks": "^7.0.1",
36
+ "node-estree": "^4.0.0",
37
+ "prettier": "^3.7.4",
38
+ "ts-morph": "^26.0.0",
39
+ "typescript-eslint": "^8.50.1"
40
+ },
41
+ "devDependencies": {
42
+ "@base-ui/react": "^1.0.0",
43
+ "@types/node": "^25.0.3",
44
+ "cli-highlight": "^2.1.11",
39
45
  "react": "^19.2.3",
40
46
  "rimraf": "^6.0.1",
41
47
  "tsup": "^8.5.0",
42
48
  "tsx": "^4.21.0",
43
49
  "type-fest": "^4.41.0",
44
50
  "typescript": "^5.9.2",
45
- "typescript-eslint": "^8.50.1",
46
51
  "vite-tsconfig-paths": "^6.0.3",
47
52
  "vitest": "^4.0.16"
48
53
  },