Skip to content
1 change: 1 addition & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
yarnPath: .yarn/releases/yarn-3.5.0.cjs
nodeLinker: node-modules
7 changes: 7 additions & 0 deletions codemod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
schema_version: "1.0.0"
name: react-declassify-workflow
version: 1.0.0
description: "React Class to Hook Codemod with AI review"
author: "istan"
engine: workflow
arguments: []
36 changes: 36 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
default:
just -l

# Build the project
build:
yarn install
yarn build

# Install the packaged tarball globally on your machine
# Example of how to use afterwords:
# yarn dlx @codemod/cli --plugin react-declassify
install-global: pack
npm install -g ./package.tgz

# Run tests
test: build
yarn test

# Create a yarn tarball (equivalent to a Python wheel)
pack: build
yarn pack --filename package.tgz

# Run the codemod locally using the built plugin against a target directory
# Usage: just run-local ../my-project/src
run-local target_dir: build
yarn dlx @codemod/cli --plugin ./dist/index.js '{{ target_dir }}/**/*.tsx' '{{ target_dir }}/**/*.ts' '{{ target_dir }}/**/*.jsx' '{{ target_dir }}/**/*.js'

# Run the Codemod AI Workflow WITHOUT the AI step
# Usage: just run-workflow ../my-project/src
run-workflow target_dir: build
yarn dlx codemod@latest run . --target {{ target_dir }}

# Run the Codemod AI Workflow WITH the AI step turned on
# Usage: just run-workflow-ai ../my-project/src
run-workflow-ai target_dir: build
yarn dlx codemod@latest run . --target {{ target_dir }} --autoAiReview=true
40 changes: 40 additions & 0 deletions workflow.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
version: "1"

params:
autoAiReview:
name: "Auto AI Review"
description: "Whether to use AI to review the transformed React components (requires LLM_API_KEY environment variable)"
type: boolean
default: false

nodes:
- id: apply-transforms
name: Apply AST Transformations
type: automatic
steps:
- name: "Transform React class components to function components"
run: "npx -y @codemod/cli@3.3.0 --plugin ../../../react-declassify/cjs/dist/index.js ${TARGET:-src/} || true"
- id: ai-review
name: "AI Review"
type: automatic
if: "params.autoAiReview == true"
depends_on:
- apply-transforms
steps:
- name: "AI Code Review"
glob: "src/**/*.js"
ai:
max_tokens: 8000
prompt: |
You are an expert React migration codemod agent.
Your job is to fix the remaining issues in the React codebase after an automatic class-to-function component transform.
Please search for all .js files in the src/ directory (especially src/components/ and src/reducers/ and src/control/) that contain the string `TODO_this` or `react-declassify-disable`.
For each file you find, you must edit it to fix the issues:
1. If `TODO_this.shouldComponentUpdate` is used, remove it completely and rewrite the component export to use `React.memo(ComponentName, (prevProps, nextProps) => { ... })`. Make sure to convert any `props` variables and maintain identical behavior. WARNING: `shouldComponentUpdate` returns `true` to update. `React.memo` returns `true` to SKIP update. Invert the boolean logic!
2. For component refs (like dom_rotate, dom_down, etc.), if they are accessed dynamically via `TODO_this[\`dom_${key}\`].dom`, replace that access with `eval(\`dom_${key}\`).current` or create a local object mapping keys to refs and use that. Make sure `TODO_this` is completely removed.
3. Fix any eslint errors you might create:
- Ensure spaces before function parentheses (e.g., `function () {}` not `function(){}`).
- Ensure there are no missing trailing commas.
- If there are camelcase errors for variables like `dom_rotate`, either fix them to `domRotate` (and update all usages including string interpolation like `` \`dom_${key}\` ``) or add `/* eslint-disable camelcase */` at the top of the file to ignore them.

Edit the files directly using your available tools. Do not stop until all instances of `TODO_this` are removed from the src/ directory.