angularjs-to-react
Migrate an AngularJS codebase to a React codebase
Example
# Example Output React folder
# react-app/
# ├── public/ # Contains static assets like HTML files, icons, etc.
# │ ├── favicon.ico # App icon
# │ ├── index.html # Main HTML file
# │ └── manifest.json # Manifest file for PWA configuration
# ├── src/
# │ ├── components/ # Contains all React components.
# │ │ ├── Dashboard.tsx # Example component
# │ │ ├── UserProfile.tsx # Example component
# │ │ └── Header.tsx # Example component
# │ ├── services/ # Services for handling API calls and other shared logic.
# │ │ ├── userService.ts # Example service
# │ │ ├── apiService.ts # Handles general API interactions
# │ │ └── authService.ts # Authentication related services
# │ ├── hooks/ # Custom React hooks.
# │ │ ├── useFetch.ts # Hook for API fetching
# │ │ ├── useAuth.ts # Authentication hook
# │ │ └── useResponsive.ts # Responsive design hook
# │ ├── utils/ # Utility functions.
# │ │ ├── format.ts # Formatting utilities
# │ │ ├── validate.ts # Validation utilities
# │ │ └── constants/ # Constants used across the app
# │ │ ├── <constant-name>.ts
# │ │ ├── <constant-name>.ts
# │ │ └── <constant-name>.ts
# │ ├── store/ # Redux store, reducers, and actions if using Redux.
# │ │ ├── index.ts # Combines reducers and configures the store
# │ │ ├── rootReducer.ts # Root reducer combining all feature reducers
# │ │ ├── user/
# │ │ │ ├── userActions.ts # Actions for user-related functionality
# │ │ │ ├── userReducer.ts # Reducer for user-related data
# │ │ │ └── userTypes.ts # TypeScript types and interfaces for user
# │ │ ├── product/
# │ │ │ ├── productActions.ts # Actions for product-related functionality
# │ │ │ ├── productReducer.ts # Reducer for product-related data
# │ │ │ └── productTypes.ts # TypeScript types and interfaces for product
# │ │ └── settings/
# │ │ ├── settingsActions.ts # Actions for settings functionality
# │ │ ├── settingsReducer.ts # Reducer for settings data
# │ │ └── settingsTypes.ts # TypeScript types and interfaces for settings
# │ ├── assets/ # Static assets like images, stylesheets, etc.
# │ │ ├── images/ # Folder for images
# │ │ ├── styles/ # Folder for CSS or SCSS files
# │ │ └── fonts/ # Folder for custom fonts
# │ ├── routes/
# │ │ ├── PrivateRoute.tsx # Component for handling private routes
# │ │ └── Routes.tsx # All route definitions in one place
# │ ├── App.tsx # Root React component
# │ └── index.tsx # Entry point for React application, setup context providers, and Router
# ├── tsconfig.json # TypeScript configuration file
# ├── package.json # Project metadata and dependencies
# ├── .gitignore # Specifies intentionally untracked files to ignore
# └── README.md # Project overview and documentation
constants:
react_directory: 'react'
src_directory: '{{ react_directory }}/src'
assets_directory: '{{ src_directory }}/assets'
entry_file_path: '{{ src_directory }}/App.tsx'
components_directory: '{{ src_directory }}/components'
utils_directory: '{{ src_directory }}/utils'
services_directory: '{{ src_directory }}/services'
controllers_directory: '{{ components_directory }}/controllers'
directives_directory: '{{ components_directory }}/directives'
constants_directory: '{{ utils_directory }}/constants'
config_directory: '{{ utils_directory }}/config'
filters_directory: '{{ utils_directory }}/filters'
context_depth: 3 # The depth of the context to retrieve for each file.
libraries_to_install:
- axios
- react-router-dom
- react-use
library_mappings: |
- All $http and $httpProvider usages should be converted/replaced with the `axios` equivalent.
- All $location usages should be converted/replaced with the `react-router-dom` equivalent, using the `useLocation` hook.
- All $scope usages should be converted/replaced with React's state and props.
- All ng-model usages should be converted/replaced with React's controlled components using the `useState` hook.
- All ng-repeat usages should be converted/replaced with JavaScript's `map` function in JSX.
- All ng-if usages should be converted/replaced with conditional rendering in JSX (`{condition && <Component />}`).
- All ng-show and ng-hide usages should be converted/replaced with conditional rendering in JSX (`{condition ? <Component /> : null}`).
- All ng-class usages should be converted/replaced with dynamic class names using `className` and template literals.
- All angular-aria usages should be converted/replaced with React's built-in accessibility features.
- All angular-loader usages should be converted/replaced with React's built-in lazy loading (`React.lazy` and `Suspense`).
- All angular-messages usages should be converted/replaced with React's built-in state and conditional rendering.
- All angular-resource usages should be converted/replaced with the `axios` equivalent.
- All angular-route usages should be converted/replaced with the `react-router-dom` equivalent.
- All angular-touch usages should be converted/replaced with React's built-in event handling.
transformation_notes: |
## Codebase Transformation Notes
### Generation Preferences
When generating code, follow these guidelines:
- Only include information from the portion you were told to convert.
- Do not create new configs, components, or example usages.
- Remove AngularJS-specific elements that cannot be converted to React.
- Leave empty functions as they are.
- If the current file path was provided above, you should ensure that the import paths are relative to this path.
- At the top of the converted file, you should include a comment with the original file path. Something like `// Converted from <original-file-path>`.
- The resulting code should be DRY and only declare one component per file.
- The resulting code should be written in TypeScript.
- You should always define and export functions. You should never use the class syntax when defining services, hooks, components or otherwise. Always use functional syntax and prefer projection functions where possible.
- Do not hallucinate!
### Angularjs to React Conversion Guidelines
- Angular `ng-` directives should be converted to the react-equivalent logic. Do not leave these in the template.
- Special built-in angularjs services and factories, typically defined as $<service-name>, should be converted to react-equivalent logic.
- AngularJS injectors are no longer needed in React.
### New Files
When defining new files based on unconverted files, assume the following naming strategies (useful for imports):
- AngularJS constants -> TypeScript constants in `{{ constants_directory }}/<constant-name>.ts`. Each file will have a single default export that can be imported and used in other files.
- AngularJS services, factories, and providers -> React services in `{{ services_directory }}/<current-file-name>.tsx`. Each file will have a single default export function that can be imported and used in other files.
- AngularJS directives -> React components in `{{ directives_directory }}/<current-file-name>.tsx`. Each file will have a single default export function that can be imported and used in other files.
- AngularJS filters -> React components in `{{ filters_directory }}/<current-file-name>.tsx`. Each file will have a single default export function that can be imported and used in other files.
- AngularJS controllers and template HTML files -> React components in `{{ controllers_directory }}/<current-file-name>.tsx`. Each file will have a single default export function that can be imported and used in other files.
- AngularJS config and routes -> React components in `{{ config_directory }}/<current-file-name>.tsx`. Each file will have a single default export function that can be imported and used in other files.
### Libraries
The following libraries are already installed in the project and available for you to use (in addition to the default react libraries): {{ libraries_to_install }}
#### Mapping Angularjs libraries to React-compatible libraries:
{{ library_mappings }}
ignore_file_paths:
- 'gulpfile.js'
- 'LICENSE'
- '**/test/**'
- 'test/**'
- 'package.json'
- '.gitignore'
- 'tsconfig.json'
- 'README.md'
- '**/{{ react_directory }}'
- '**/{{ react_directory }}/**'
- '*.config'
# The HRC reference may do more harm now with embedding_graph.
dependency_prompt: |
Acronym Key:
- SDIF: Symbol Defined In File
- SDE: Symbol Defined Externally
- MAP: Mapping
- HRC: HTML Reference Controller
You should find all SDIFs, SDEs, HRCs, and MAPs in the file. Below are some hints to help you determine usage, but also rely on your innate knowledge in case the usage is not explicitly stated below.
You only care about the high level connections between files like definitions for factories, controllers, services, configs, etc. and their dependencies (declared in the brackets after the name of the angular declaration type) as well as mappings of controllers to file paths.
Rules:
- If a AngularJS directive is declared in the template, you care about the value the directive is set to, not the directive itself. For example if you have `ng-controller="ExampleCtrl as example"`, you should only care about `ExampleCtrl` and not `ng-controller`.
- If an Angularjs module is defined in this file, you should return the name of the module as one of the SDIF keys. If it is just used or added to with .controller, .factory, .service, etc, you should include it as a SDE key.
- You should ALWAYS ignore built-in special angularjs functions, variables, and boilerplate like `$http`, `$timeout`, `.module`, `.controller`, etc.
- You should still include $rootScope definitions because it tells us where the global variables are defined.
- NEVER include standard library variables like window.* or document.*, console.*, etc. when looking for SDIFs or SDEs.
- When including nested objects, you should AT MOST include 1 level deep. For example, if you have `PageValue.page.title` and `PageValue.page.content`, you should only include `PageValue.page` once as a SDIF or SDE key, even though more deeply nested sub-fields may be present.
- `directives` defined in js logic should be converted to kebab-case (e.g. `myDirective` -> `my-directive`), then added as a key in either SDIF or SDE.
## MAP Example:
```
var routes = {
"example": {
controller: 'ExampleCtrl',
templateUrl: 'example.html'
}
// ...
<div>
{{ routes }}
</div>
```
- In the above case, in "routes.example" the controller and template are mapped to each other where the template relies on the controller.
- Note that usages of variables, even if defined externally, would not be considered mappings. Mappings should only be used to allow us to map two files together and should NEVER include two symbol types.
- For now, mappings should ONLY be two paths or a symbol and a path. It should never be a symbol and a symbol.
## SDIF Example:
SDIFs are frequently defined in the controller, service, factory, constant, config, etc. Typically it would look something like `angular.module(...).controller(...);` where controller could be any of the valid angularjs types.
```
angular.module('app').controller('ExampleCtrl', ['$scope', '$http', function($scope, $http) {
$scope.example = 'example';
$rootScope.exampleGlobal.example = 'example';
}]);
```
In the above case, the controller is ExampleCtrl and it is a SDIF, likely to be used in other parts of the application. $scope is used to represent local variables in the controller and therefore shouldn't be included. However, `$rootScope.exampleGlobal.example` should be included as an SDE under the key `$rootScope.exampleGlobal`.
## SDE Example:
SDEs are frequently USED in a controller, service, factory, constant, config, etc.
```
angular.module('app').controller('AnotherCtrl', ['$scope', '$http', function($scope, $http) {
if ($scope.example) {
// ...
}
}]);
```
In the above case, $scope.example should not be included in either SDE or SDIF because it is local only to this file and the template. In this case though, AnotherCtrl would be returned as a SDIF, `module("app")` would also be included as an SDE".
## HRC Example:
```
<div ng-controller="someController as vm" ng-init="vm.getCurrentUser()">
....
</div>
```
- In the above case, the referenced controller is someController, and it is needed in the template.
- This controller should be seen before the template in the dependency graph.
Be greedy.
steps:
- name: Create a new React app
tools:
- name: create_react_app
arguments:
path_to_directory: '{{ react_directory }}'
- name: Install target conversion libraries
tools:
- name: for_each
items: '{{ libraries_to_install }}'
each_item:
item_name: library
tools:
- name: run_terminal_command
arguments:
path_to_directory: '{{ react_directory }}'
command: 'npm i {{ library }}'
- name: Update tsconfig to be stricter
tools:
- name: find_files_by_name_with_regex
arguments:
find_file_name_pattern: 'tsconfig\.json'
returns: tsconfig_file_paths
- name: get_first
arguments:
array: '{{ tsconfig_file_paths }}'
returns: tsconfig_file_path
- name: edit_json
arguments:
path_to_file: '{{ tsconfig_file_path }}'
json_path: 'compilerOptions'
action: 'add'
values:
- key: 'noUnusedLocals'
value: true
- key: 'noUnusedParameters'
value: true
- name: Build a dependency graph of the codebase
tools:
- name: build_dependency_graph_with_ai
arguments:
dependency_prompt: '{{ dependency_prompt }}'
exclude_path_patterns: '{{ ignore_file_paths }}'
- name: Convert files in order
tools:
- name: get_files_in_topological_order
arguments:
top_down: true
returns: conversion_order_by_level
- name: for_each
items: '{{ conversion_order_by_level }}'
each_item:
item_name: level
tools:
- name: async_each
items: '{{ level }}'
each_item:
item_name: file_to_convert
tools:
- name: get_content_from_file
arguments:
path_to_file: '{{ file_to_convert }}'
returns: file_contents
- name: get_file_long_context
arguments:
path_to_file: '{{ file_to_convert }}'
depth: '{{ context_depth }}'
graph_type: 'embedding'
returns: file_context
- name: get_file_name
arguments:
path_to_file: '{{ file_to_convert }}'
include_extension: false
returns: file_name
- name: switch
content: |
## {{ file_to_convert }}
```
{{ file_contents }}
```
cases:
# Update App.tsx
- condition_prompt: Is this the root entry point either logic or template for the AngularJS app that should be put into the App.tsx React file?
break: true
tools:
- name: chunk_prompt
arguments:
contents:
- priority: 3
content: '{{ file_context }}'
- priority: 2
content: |
Angularjs Code to convert to React ({{ file_to_convert }}):
```
{{ file_contents }}
```
- priority: 1
content: |
# Instructions
- Extract code from the AngularJS file that should be converted to React.
- Merge that code with the existing content in the file and write out the merged content.
- The only time you can fully replace code is if the code in App.tsx is clearly the dummy text that was generated by create-react-app.
- If the code already looks like it was converted from AngularJS, you should ensure all previous functionality remains along with the new logic that you will implement.
- Do not just concatenate converted parts together, you should rewrite so that the code is DRY without losing functionality.
- If there are no changes to make, return an empty code block (``````).
{{ transformation_notes }}
returns: chunked_prompts
- name: edit_file_long_context
arguments:
path_to_file: '{{ entry_file_path }}'
edit_prompts: '{{ chunked_prompts }}'
- name: mark_files_converted_in_context
arguments:
done_converting: false
old_file_path: '{{ file_to_convert }}'
new_file_paths:
- '{{ entry_file_path }}'
# Constant or value
- condition_prompt: Does this file contain an Angularjs constant or value definition?
tools:
- name: find_content_in_file_with_ai
arguments:
path_to_file: '{{ file_to_convert }}'
find_context_prompt: 'Find and return JUST the name of each constant or value defined in the file. If there are none, return an empty array.'
results_as_array: true
returns: constant_or_value_names
- name: async_each
items: '{{ constant_or_value_names }}'
returns_key: constant_file_path
each_item:
item_name: constant_or_value_name
tools:
- name: make_variable
arguments:
value: '{{ constants_directory }}/{{ constant_or_value_name }}.ts'
returns: constant_file_path
- name: chunk_prompt
arguments:
contents:
- priority: 3
content: '{{ file_context }}'
- priority: 2
content: |
Angularjs Code ({{ file_to_convert }}):
```
{{ file_contents }}
```
- priority: 1
content: |
# Instructions
- Extract `{{ constant_or_value_name }}` from the above AngularJS code and convert it to a TypeScript constant for React components.
- Only extract and convert `{{ constant_or_value_name }}` and it's relevant information to make it work in React on it's own. Ignore anything else.
- The resulting file will be created at {{ constant_file_path }}.
- You should always type the converted angularjs constant or value in TypeScript with the information given. Do not assume new fields, only create a type from the fields you know for certain exist.
- Constants should have a single default export that can be imported and used in other files.
{{ transformation_notes }}
returns: chunked_prompts
- name: edit_file_long_context
arguments:
path_to_file: '{{ constant_file_path }}'
edit_prompts: '{{ chunked_prompts }}'
# Return from for loop
returns: file_paths
- name: mark_files_converted_in_context
arguments:
done_converting: false
old_file_path: '{{ file_to_convert }}'
new_file_paths: '{{ file_paths }}'
# Filters
- condition_prompt: Does this file contain an Angularjs filter definition?
tools:
- name: find_content_in_file_with_ai
arguments:
path_to_file: '{{ file_to_convert }}'
find_context_prompt: 'Find and return JUST the name of each filter defined in the file. If there are none, return an empty array.'
results_as_array: true
returns: filter_names
- name: async_each
items: '{{ filter_names }}'
returns_key: filter_file_path
each_item:
item_name: filter_name
tools:
- name: make_variable
arguments:
value: '{{ filters_directory }}/{{ filter_name }}.tsx' # TODO: This should be .ts ideally - sometimes the model gets confused and will include template code in here so this is a hack until we can figure out why.
returns: filter_file_path
- name: chunk_prompt
arguments:
contents:
- priority: 3
content: '{{ file_context }}'
- priority: 2
content: |
Angularjs Code ({{ file_to_convert }}):
```
{{ file_contents }}
```
- priority: 1
content: |
# Instructions
- Extract `{{ filter_name }}` from the above AngularJS code and convert it to a TypeScript utility function for React components.
- Only extract and convert `{{ filter_name }}` and its relevant information to make it work in React on its own. Ignore anything else.
- The resulting file will be created at {{ filter_file_path }}.
{{ transformation_notes }}
returns: chunked_prompts
- name: edit_file_long_context
arguments:
path_to_file: '{{ filter_file_path }}'
edit_prompts: '{{ chunked_prompts }}'
# Return from for loop
returns: file_paths
- name: mark_files_converted_in_context
arguments:
done_converting: false
old_file_path: '{{ file_to_convert }}'
new_file_paths: '{{ file_paths }}'
# Services
- condition_prompt: Does this file contain an Angularjs service definition?
tools:
- name: find_content_in_file_with_ai
arguments:
path_to_file: '{{ file_to_convert }}'
find_context_prompt: 'Find and return JUST the name of each service defined in the file. If there are none, return an empty array.'
results_as_array: true
returns: service_names
- name: async_each
items: '{{ service_names }}'
returns_key: service_file_path
each_item:
item_name: service_name
tools:
- name: make_variable
arguments:
value: '{{ services_directory }}/{{ service_name }}.tsx'
returns: service_file_path
- name: chunk_prompt
arguments:
contents:
- priority: 3
content: '{{ file_context }}'
- priority: 2
content: |
Angularjs Code ({{ file_to_convert }}):
```
{{ file_contents }}
```
- priority: 1
content: |
# Instructions
- Extract `{{ service_name }}` from the above AngularJS code and convert it to a TypeScript service for React components.
- Only extract and convert `{{ service_name }}` and its relevant information to make it work in React on its own. Ignore anything else.
- The resulting file will be created at {{ service_file_path }}.
- Service files should have a single default export function that can be imported and used in other files.
{{ transformation_notes }}
returns: chunked_prompts
- name: edit_file_long_context
arguments:
path_to_file: '{{ service_file_path }}'
edit_prompts: '{{ chunked_prompts }}'
# Return from for loop
returns: file_paths
- name: mark_files_converted_in_context
arguments:
done_converting: false
old_file_path: '{{ file_to_convert }}'
new_file_paths: '{{ file_paths }}'
# Configs
- condition_prompt: Does this file contain an Angularjs config definition?
tools:
- name: find_content_in_file_with_ai
arguments:
path_to_file: '{{ file_to_convert }}'
find_context_prompt: 'Find and return JUST the name of each config defined in the file. If there is no name defined, create one based on the contents of the config. It is critical that the name could be used as a valid file name. If there are none, return an empty array.'
results_as_array: true
returns: config_names
- name: async_each
items: '{{ config_names }}'
returns_key: config_file_path
each_item:
item_name: config_name
tools:
- name: make_variable
arguments:
value: '{{ config_directory }}/{{ config_name }}.tsx'
returns: config_file_path
- name: chunk_prompt
arguments:
contents:
- priority: 3
content: '{{ file_context }}'
- priority: 2
content: |
Angularjs Code ({{ file_to_convert }}):
```
{{ file_contents }}
```
- priority: 1
content: |
# Instructions
- Extract `{{ config_name }}` from the above AngularJS code and convert it to a TypeScript config for React components.
- Only extract and convert `{{ config_name }}` and its relevant information to make it work in React on its own. Ignore anything else.
- The resulting file will be created at {{ config_file_path }}.
{{ transformation_notes }}
returns: chunked_prompts
- name: edit_file_long_context
arguments:
path_to_file: '{{ config_file_path }}'
edit_prompts: '{{ chunked_prompts }}'
# Return from for loop
returns: file_paths
- name: mark_files_converted_in_context
arguments:
done_converting: false
old_file_path: '{{ file_to_convert }}'
new_file_paths: '{{ file_paths }}'
# Directives
- condition_prompt: Does this file contain an Angularjs directive definition?
tools:
- name: find_content_in_file_with_ai
arguments:
path_to_file: '{{ file_to_convert }}'
find_context_prompt: 'Find and return JUST the name of each directive defined in the file. If there are none, return an empty array.'
results_as_array: true
returns: directive_names
- name: async_each
items: '{{ directive_names }}'
returns_key: directive_file_path
each_item:
item_name: directive_name
tools:
- name: make_variable
arguments:
value: '{{ directives_directory }}/{{ directive_name }}.tsx'
returns: directive_file_path
- name: chunk_prompt
arguments:
contents:
- priority: 3
content: '{{ file_context }}'
- priority: 2
content: |
Angularjs Code ({{ file_to_convert }}):
```
{{ file_contents }}
```
- priority: 1
content: |
# Instructions
- Extract `{{ directive_name }}` from the above AngularJS code and convert it to a TypeScript component for React components.
- Only extract and convert `{{ directive_name }}` and its relevant information to make it work in React on its own. Ignore anything else.
- The resulting file will be created at {{ directive_file_path }}.
{{ transformation_notes }}
returns: chunked_prompts
- name: edit_file_long_context
arguments:
path_to_file: '{{ directive_file_path }}'
edit_prompts: '{{ chunked_prompts }}'
# Return from for loop
returns: file_paths
- name: mark_files_converted_in_context
arguments:
done_converting: false
old_file_path: '{{ file_to_convert }}'
new_file_paths: '{{ file_paths }}'
# Controllers
- condition_prompt: Does this file contain an Angularjs controller definition?
tools:
- name: find_content_in_file_with_ai
arguments:
path_to_file: '{{ file_to_convert }}'
find_context_prompt: 'Find and return JUST the name of each controller defined in the file. If there are none, return an empty array.'
results_as_array: true
returns: controller_names
- name: async_each
items: '{{ controller_names }}'
returns_key: controller_file_path
each_item:
item_name: controller_name
tools:
- name: make_variable
arguments:
value: '{{ controllers_directory }}/{{ controller_name }}.tsx'
returns: controller_file_path
- name: chunk_prompt
arguments:
contents:
- priority: 3
content: '{{ file_context }}'
- priority: 2
content: |
Angularjs Code ({{ file_to_convert }}):
```
{{ file_contents }}
```
- priority: 1
content: |
# Instructions
- Extract `{{ controller_name }}` from the above AngularJS code and convert it to a TypeScript component for React components.
- Only extract and convert `{{ controller_name }}` and its relevant information to make it work in React on its own. Ignore anything else.
- The resulting file will be created at {{ controller_file_path }}.
{{ transformation_notes }}
returns: chunked_prompts
- name: edit_file_long_context
arguments:
path_to_file: '{{ controller_file_path }}'
edit_prompts: '{{ chunked_prompts }}'
# Return from for loop
returns: file_paths
- name: mark_files_converted_in_context
arguments:
done_converting: false
old_file_path: '{{ file_to_convert }}'
new_file_paths: '{{ file_paths }}'
# Routes
- condition_prompt: Does this file contain Angularjs routes definitions that should be included in the React Router?
tools:
- name: truncate_prompt
arguments:
contents:
- priority: 3
content: '{{ file_context }}'
- priority: 2
content: |
Angularjs Code to convert to React ({{ file_to_convert }}):
```
{{ file_contents }}
```
- priority: 1
content: |
# Instructions
- Extract the route definition from the above AngularJS code.
- The only code you care about in this file is the route definition and the variables that define it. Ignore all other code.
- Convert the extracted router-related code to use React Router.
- Ensure all previous functionality remains along with the new logic that you implement.
- Do not just concatenate converted parts together, you should rewrite so that the code is DRY without losing functionality. The result should be a valid React Router configuration file.
- If there isn't any code in the angularjs file that could be converted to valid React Router, you should not make any edits to the file - just return an empty string in that case.
- Do not implement anything other than the router. Other logic will be converted in different steps.
{{ transformation_notes }}
returns: truncated_prompt
- name: edit_file
arguments:
path_to_file: '{{ config_directory }}/{{ file_name }}.tsx'
edit_prompt: '{{ truncated_prompt }}'
- name: mark_files_converted_in_context
arguments:
done_converting: false
old_file_path: '{{ file_to_convert }}'
new_file_paths:
- '{{ config_directory }}/{{ file_name }}.tsx'
# Add case for html?
default:
tools:
# TODO: Implement this case
- name: echo_one
arguments:
echo_arg: 'Doing nothing with {{ file_to_convert }}'
# This file is done being converted since it has been fully processed by the switch statement (or skipped)
- name: mark_files_converted_in_context
arguments:
done_converting: true
old_file_path: '{{ file_to_convert }}'
- name: Combine Routes into a single file and add to App.tsx
tools:
- name: find_files_by_name_with_regex
arguments:
path_to_directory: '{{ config_directory }}'
find_file_name_pattern: '.*'
returns: config_file_paths
- name: get_content_from_files
arguments:
paths_to_files: '{{ config_file_paths }}'
returns: config_file_contents
- name: edit_file
arguments:
path_to_file: '{{ entry_file_path }}'
edit_prompt: |
Remove all of the boilerplate added by create-react-app from this file. By the end, this should be as bare bones as possible.
# Update App.tsx with any routes from the config files
- name: edit_file
arguments:
path_to_file: '{{ entry_file_path }}'
edit_prompt: |
The below code could contain React Router configuration. You should extract and add any routes directly into the App.tsx file in addition to adding any comments that start with `// Converted from` that are present at the top of the file we are extracting from. Be meticulous and precise. Do not hallucinate.
## Example route
If a config file contains a route like this:
```
// Converted from example/file/path1.js
// ...
<Route path="/" element={<Home />} />
// ...
```
It should be added to the App.tsx file like this:
```
// Converted from example/file/path1.js
// Converted from example/file/path2.js
// ... more imports and logic ...
function App() {
// ... maybe some more business logic ...
return (
<Routes>
<Route path="/" element={<Home />} />
// ... other routes ...
</Routes>
);
}
```
## Config Files
```
{{ config_file_contents }}
```
# Delete routes now that they have been extracted into App.tsx
- name: for_each
items: '{{ config_file_paths }}'
each_item:
item_name: config_file_path
tools:
- name: get_content_from_file
arguments:
path_to_file: '{{ config_file_path }}'
returns: content_for_this_config_file
- name: ask_question
arguments:
question_prompt: |
Does the following file contain React Router routes in the form `<Route ... />`? Axios requests should be left alone. This should JUST be routes that are rendered in the browser.
```
{{ content_for_this_config_file }}
```
returns: contains_react_routes
- name: if_else
condition: '{{ contains_react_routes }}'
if:
tools:
- name: delete_file_or_folder
arguments:
path_to_target: '{{ config_file_path }}'
- name: Copy static assets
tools:
- name: find_files_by_name_with_regex
arguments:
path_to_directory: 'src'
find_file_name_pattern: .*\.(css|svg|png|jpg|jpeg|eot|ttf|otf|woff|woff2|gif|bmp|webp|webm|mp3)$
returns: static_asset_files
- name: for_each
items: '{{ static_asset_files }}'
each_item:
item_name: static_file
tools:
- name: copy_file
arguments:
source_path: '{{ static_file }}'
destination_path: '{{ assets_directory }}/{{ static_file }}'
returns: copied_file_path
- name: Add CSS imports to App.tsx
tools:
- name: find_files_by_name_with_regex
arguments:
path_to_directory: '{{ assets_directory }}'
find_file_name_pattern: '.*\.css$'
returns: css_files
- name: edit_file
arguments:
path_to_file: '{{ entry_file_path }}'
edit_prompt: |
We are currently looking at this file: `{{ entry_file_path }}`
Add CSS imports at the top of the file for the following css files:
```
{{ css_files }}
```
- name: Resolve import paths
tools:
- name: resolve_import_paths
arguments:
path_to_directory: '{{ react_directory }}'
- name: Validate TypeScript Project
tools:
- name: validate_typescript_project
arguments:
max_context_depth: 3
directory: '{{ react_directory }}'
Last updated