Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add codemod to convert input selectors passed as separate inline arguments to a single array #681

Open
wants to merge 101 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
5d8f60a
Setup initial codemod
aryaemami59 Nov 21, 2023
9e23308
Merge branch 'master' of https://github.com/reduxjs/reselect into cod…
aryaemami59 Nov 26, 2023
7f422c4
Merge branch 'master' of https://github.com/reduxjs/reselect into cod…
aryaemami59 Jan 12, 2024
bbc9e72
Update lockfile
aryaemami59 Jan 12, 2024
bde8530
Move `codemods` folder to top level
aryaemami59 Jan 12, 2024
e0dfdca
Add dependencies
aryaemami59 Jan 12, 2024
971f1ce
Fix eslint configuration
aryaemami59 Jan 12, 2024
9b13857
Add `.gitignore`
aryaemami59 Jan 12, 2024
98d90b4
Add `.prettierrc.json`
aryaemami59 Jan 12, 2024
8414c9d
Add `README.md`
aryaemami59 Jan 12, 2024
13e4844
Add `tsconfig.json`
aryaemami59 Jan 12, 2024
1b2bead
Copy CI from Redux Toolkit
aryaemami59 Jan 12, 2024
2a2102e
Add `vitest.config.ts`
aryaemami59 Jan 12, 2024
7b53ed7
Initial implementation of `convertInputSelectorsToArray` codemod
aryaemami59 Jan 12, 2024
f407d1d
Add vanilla-js test fixtures
aryaemami59 Jan 12, 2024
b558c9c
Fix previous mistake with `.gitignore` files
aryaemami59 Jan 14, 2024
ef20c98
Enable codemod to recognize `.withTypes` calls as selector creators
aryaemami59 Jan 14, 2024
dfb5f2a
Add `withTypes` fixtures
aryaemami59 Jan 14, 2024
6dbe126
Update dependencies
aryaemami59 Jan 14, 2024
df1d5fc
Update dev command
aryaemami59 Jan 16, 2024
8ea8aef
Add `"arrowParens": "avoid"` to `.prettierrc.json`
aryaemami59 Jan 16, 2024
9dace7d
Update dependencies
aryaemami59 Jan 16, 2024
7b0197c
Add `noUncheckedIndexedAccess` to `tsconfig.json`
aryaemami59 Jan 16, 2024
6df66a1
Slightly modify CLI to allow passing multiple glob patterns
aryaemami59 Jan 16, 2024
88eb9fb
Remove leading forward slash from test names
aryaemami59 Jan 16, 2024
90442ab
Remove redundant tests
aryaemami59 Jan 16, 2024
5156c25
Refactor transforms for readability
aryaemami59 Jan 16, 2024
1255378
Remove unnecessary `update-docs` command
aryaemami59 Jan 16, 2024
8ebf7fb
Add `README` files
aryaemami59 Jan 16, 2024
32f8798
Merge branch 'master' of https://github.com/reduxjs/reselect into cod…
aryaemami59 Feb 9, 2024
1cf06a0
Rename `vitest.config.ts` to `vitest.config.mts`
aryaemami59 Feb 9, 2024
69c6c15
Rename `bin\cli.js` to `bin\cli.mjs`
aryaemami59 Feb 9, 2024
6b86668
Remove `"type": "module"` from `package.json`
aryaemami59 Feb 9, 2024
e391a41
Fix `test` command
aryaemami59 Feb 9, 2024
d4adf6a
Add `test:watch` command
aryaemami59 Feb 9, 2024
e0fa7de
Fix `vitest.config.mts`
aryaemami59 Feb 9, 2024
7199e9a
Bump Vitest
aryaemami59 Feb 9, 2024
e1c2d73
Bump Prettier
aryaemami59 Feb 9, 2024
0e57e96
Fix `tsconfig.json`
aryaemami59 Feb 9, 2024
a73f32a
Rename `separate-inline-arguments.input.ts` to `separate-inline-argum…
aryaemami59 Feb 9, 2024
ea8453c
Rename `separate-inline-arguments.output.ts` to `separate-inline-argu…
aryaemami59 Feb 9, 2024
73f09b2
Rename `withTypes.output.ts` to `withTypes-ts.output.ts`
aryaemami59 Feb 9, 2024
2196e96
Rename `withTypes.input.ts` to `withTypes-ts.input.ts`
aryaemami59 Feb 9, 2024
75ddfab
Add global Vitest types
aryaemami59 Feb 9, 2024
6043f06
Fix minor grammar issue in `README.md`
aryaemami59 Feb 9, 2024
e769a6c
Remove `"trailingComma": "none"` from `.prettierrc.json`
aryaemami59 Feb 10, 2024
3355594
Make ESLint extends prettier
aryaemami59 Feb 10, 2024
c5482e9
Format all files
aryaemami59 Feb 10, 2024
4cd75aa
Bump docusaurus
aryaemami59 Feb 10, 2024
5d9dad4
Bump website dependencies
aryaemami59 Feb 10, 2024
50b9f89
Add `convertInputSelectorsToArray` codemod before and after example
aryaemami59 Feb 10, 2024
9bb7c68
Add documentation for codemods
aryaemami59 Feb 10, 2024
55dff9c
Add `convertInputSelectorsToArray` codemod to `.withTypes` section
aryaemami59 Feb 10, 2024
2bb8e84
Bump `@typescript-eslint/parser`
aryaemami59 Feb 10, 2024
6c97007
Simplify `README.md`
aryaemami59 Feb 10, 2024
b0188a3
Remove unnecessary commands
aryaemami59 Feb 10, 2024
2a635ba
Merge branch 'master' of https://github.com/reduxjs/reselect into cod…
aryaemami59 Feb 21, 2024
5c138dd
Remove `baseUrl` from `tsconfig.json`
aryaemami59 Feb 21, 2024
df3eaad
Bump dependencies
aryaemami59 Feb 21, 2024
aa092d0
Add `release-it` config file
aryaemami59 Feb 22, 2024
1b9eed2
Merge branch 'master' of https://github.com/reduxjs/reselect into cod…
aryaemami59 Mar 8, 2024
fc9063e
Bump TypeScript for `reselect-codemods`
aryaemami59 Mar 8, 2024
a7d4dbd
Bump `jscodeshift` version to 0.15.2 for `reselect-codemods`
aryaemami59 Mar 8, 2024
061e189
Bump ESLint version to 8.57.0 for `reselect-codemods`
aryaemami59 Mar 8, 2024
54f8916
Bump `@typescript-eslint/parser` for `reselect-codemods
aryaemami59 Mar 8, 2024
67ee80c
Merge branch 'master' of https://github.com/reduxjs/reselect into cod…
aryaemami59 Mar 11, 2024
7f12b16
Bump TypeScript for `reselect-codemods`
aryaemami59 Mar 26, 2024
00540a1
Bump `@typescript-eslint/parser` for `reselect-codemods`
aryaemami59 Mar 26, 2024
ad71005
Bump `vitest` for `reselect-codemods`
aryaemami59 Mar 26, 2024
cb0bf56
Bump `@typescript-eslint/parser`
aryaemami59 Apr 17, 2024
0886923
Bump `vitest`
aryaemami59 Apr 17, 2024
99752fe
Bump TypeScript
aryaemami59 Apr 17, 2024
5798397
Bump `vitest` version to 1.5.2 for `reselect-codemods`
aryaemami59 Apr 29, 2024
1c1b629
Bump `@typescript-eslint/parser` version to 7.7.1
aryaemami59 Apr 29, 2024
fb7dd0a
Bump `vitest` to version 1.5.3 for `reselect-codemods`
aryaemami59 Apr 30, 2024
849fec7
Bump `@typescript-eslint/parser` to version 7.8.0
aryaemami59 May 1, 2024
a36218b
Merge branch 'master' of https://github.com/reduxjs/reselect into cod…
aryaemami59 May 1, 2024
c4f7898
Bump `vitest` to version 1.6.0 for `reselect-codemods`
aryaemami59 May 6, 2024
732c0c8
Bump `@typescript-eslint/parser` for `reselect-codemods`
aryaemami59 May 14, 2024
935efcb
Bump `execa` to version 9.1.0 for `reselect-codemods`
aryaemami59 May 14, 2024
a339a5d
Fix CI for `reselect-codemods`
aryaemami59 May 14, 2024
cd6f1fc
Rename `ci.yml` to `test-reselect-codemods.yml`
aryaemami59 May 14, 2024
573675d
Move `test-reselect-codemods.yml` to root github actions folder
aryaemami59 May 14, 2024
7fa302c
Fix `reselect-codemods` CI directory
aryaemami59 May 14, 2024
7401021
Remove node 16 from CI
aryaemami59 May 14, 2024
d3e466c
Change CI name
aryaemami59 May 14, 2024
b2b6fce
Add `Check folder contents` CI step
aryaemami59 May 14, 2024
4df84ba
Remove lint step from CI
aryaemami59 May 14, 2024
2ef2392
Fix `cache-dependency-path`
aryaemami59 May 14, 2024
0ca6fe9
Disable `fail-fast`
aryaemami59 May 14, 2024
ae36706
Fix line endings
aryaemami59 May 14, 2024
619f3f8
Remove windows from CI for now
aryaemami59 May 14, 2024
6d4ef17
Merge branch 'master' of https://github.com/reduxjs/reselect into cod…
aryaemami59 Jun 1, 2024
c91f941
Merge branch 'master' of https://github.com/reduxjs/reselect into cod…
aryaemami59 Jun 21, 2024
4d86a01
Bump Prettier to version 3.3.2
aryaemami59 Jun 21, 2024
dc430e5
Bump `@typescript-eslint/parser` to version 7.13.1
aryaemami59 Jun 21, 2024
ed69dfc
Bump `execa` to version 9.2.0
aryaemami59 Jun 21, 2024
e5a6d28
Bump TypeScript to version 5.5.2
aryaemami59 Jun 21, 2024
27f7ed8
Bump `jscodeshift` to version 0.16.0
aryaemami59 Jun 21, 2024
3af9b57
Add `@types/jscodeshift`
aryaemami59 Jun 21, 2024
a87c434
Add `@types/node`
aryaemami59 Jun 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/test-reselect-codemods.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Test Reselect Codemods

on: [push, pull_request, workflow_dispatch]

defaults:
run:
working-directory: codemods

jobs:
test:
name: Run test Suite
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
node: [18, 20, latest]
os: [ubuntu-latest, macos-latest]

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache-dependency-path: ./codemods
cache: 'yarn'

- name: Check folder contents
run: ls -l .

- name: Install dependencies
run: yarn install

- name: Run test suite
run: yarn test
6 changes: 0 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,5 @@ typesversions
.pnp.*
*.tgz

website/translated_docs
website/build/
website/node_modules
website/i18n/*
website/.yarn/

docs/examples/**/*.js
docs/examples/**/*.jsx
11 changes: 11 additions & 0 deletions codemods/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"env": { "node": true },
"extends": ["eslint:recommended", "prettier"],
"ignorePatterns": ["node_modules"],
"parserOptions": { "ecmaVersion": "latest" },
"plugins": ["node"],
"rules": {
"no-unused-vars": [0],
"eol-last": [0]
}
}
30 changes: 30 additions & 0 deletions codemods/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Dependencies
/node_modules

# Production
/build

# Generated files
.docusaurus
.cache-loader

# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
.cache
.yarnrc
.yarn/*
!.yarn/patches
!.yarn/releases
!.yarn/plugins
!.yarn/sdks
!.yarn/versions
.pnp.*
*.tgz
5 changes: 5 additions & 0 deletions codemods/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"singleQuote": true,
"arrowParens": "avoid",
"semi": false
}
9 changes: 9 additions & 0 deletions codemods/.release-it.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"hooks": {
"after:bump": "yarn && git add -u"
},
"git": {
"commitMessage": "Release reselect-codemods ${version}",
"tagName": "reselect-codemods@${version}"
}
}
42 changes: 42 additions & 0 deletions codemods/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Reselect Codemods

A collection of codemods for updating legacy Reselect API usage patterns to modern patterns.

## Usage

To run a specific codemod from this project, you would run the following:

```bash
npx reselect-codemods <TRANSFORM NAME> path/of/files/ or/some**/*glob.js

# or

yarn global add reselect-codemods
reselect-codemods <TRANSFORM NAME> path/of/files/ or/some**/*glob.js
```

## Local Usage

```
node ./bin/cli.mjs <TRANSFORM NAME> path/of/files/ or/some**/*glob.js
```

## Transforms

<!--TRANSFORMS_START-->

- [convertInputSelectorsToArray](transforms/convertInputSelectorsToArray/README.md)

<!--TRANSFORMS_END-->

## Contributing

### Installation

- clone the repo
- change into the repo directory
- `yarn`

### Running tests

- `yarn test`
39 changes: 39 additions & 0 deletions codemods/bin/cli.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env node
import { execaSync } from 'execa'
import { globbySync } from 'globby'
import { createRequire } from 'node:module'
import path from 'node:path'
import { fileURLToPath } from 'node:url'

const require = createRequire(import.meta.url)

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

const transformerDirectory = path.join(
__dirname,
'..',
'transforms',
`${process.argv[2]}/index.ts`,
)

const jscodeshiftExecutable = require.resolve('.bin/jscodeshift')

const extensions = 'ts,js,tsx,jsx'

execaSync(
jscodeshiftExecutable,
[
'-t',
transformerDirectory,
'--extensions',
extensions,
...(process.argv.slice(3).length === 1
? globbySync(process.argv[3])
: globbySync(process.argv.slice(3))),
],
{
stdio: 'inherit',
stripFinalNewline: false,
},
)
52 changes: 52 additions & 0 deletions codemods/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"name": "reselect-codemods",
"version": "0.1.0",
"scripts": {
"lint": "eslint .",
"test": "vitest --run",
"test:watch": "vitest --watch",
"test:coverage": "vitest --coverage"
},
"bin": "./bin/cli.mjs",
"files": [
"bin/*",
"transforms/**/index.ts",
"transforms/**/README.md",
"package.json",
"README.md"
],
"keywords": [
"redux",
"redux-toolkit",
"reselect",
"codemod"
],
"dependencies": {
"execa": "^9.2.0",
"globby": "^14.0.1",
"jscodeshift": "^0.16.0",
"ts-node": "^10.9.2",
"typescript": "^5.5.2"
},
"devDependencies": {
"@types/jscodeshift": "^0.11.11",
"@types/node": "^20.14.7",
"@typescript-eslint/parser": "^7.13.1",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^5.1.3",
"prettier": "^3.3.2",
"vitest": "^1.6.0"
},
"engines": {
"node": ">= 16"
},
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/reduxjs/reselect.git"
}
}
71 changes: 71 additions & 0 deletions codemods/transformTestUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { globbySync } from 'globby'
import type { Transform } from 'jscodeshift'
import type { TestOptions } from 'jscodeshift/src/testUtils'
import { applyTransform } from 'jscodeshift/src/testUtils'
import fs from 'node:fs'
import path from 'node:path'

export const runTransformTest = (
name: string,
transform: Transform,
parser: TestOptions['parser'],
fixturePath: string,
) => {
describe(name, () => {
globbySync('**/*.input.*', {
cwd: fixturePath,
absolute: true,
objectMode: true,
})
.map(entry => entry.name)
.forEach(filename => {
const extension = path.extname(filename)

const testName = filename.replace(`.input${extension}`, '')

const testInputPath = path.join(fixturePath, `${testName}${extension}`)

const inputPath = path.join(
fixturePath,
`${testName}.input${extension}`,
)

const outputPath = path.join(
fixturePath,
`${testName}.output${extension}`,
)

const inputFileContent = fs.readFileSync(inputPath, 'utf8')

const expectedOutput = fs.readFileSync(outputPath, 'utf8')

describe(`${testName}${extension}`, () => {
it('transforms correctly', () => {
const output = applyTransform(
transform,
{},
{
path: testInputPath,
source: inputFileContent,
},
{ parser },
)
expect(output).toBe(expectedOutput.trim().replace('\r\n', '\n'))
})

it('is idempotent', () => {
const output = applyTransform(
transform,
{},
{
path: testInputPath,
source: inputFileContent,
},
{ parser },
)
expect(output).toBe(expectedOutput.trim().replace('\r\n', '\n'))
})
})
})
})
}
69 changes: 69 additions & 0 deletions codemods/transforms/convertInputSelectorsToArray/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# convertInputSelectorsToArray

Transforms the usage of Reselect's `createSelector` API by consolidating multiple inline input selector arguments into a single array.

It should work with both JavaScript and TypeScript files.

## Usage

```
npx reselect-codemods convertInputSelectorsToArray path/of/files/ or/some**/*glob.js

# or

yarn global add reselect-codemods
reselect-codemods convertInputSelectorsToArray path/of/files/ or/some**/*glob.js
```

## Local Usage

```
node ./bin/cli.mjs convertInputSelectorsToArray path/of/files/ or/some**/*glob.js
```

## Input / Output

<!--FIXTURES_TOC_START-->

- [separate-inline-arguments.input.ts](#separate-inline-arguments.ts)
- [withTypes.input.ts](#withTypes.ts)

<!--FIXTURES_TOC_END-->

## <!--FIXTURES_CONTENT_START-->

<a id="separate-inline-arguments.ts">**separate-inline-arguments.ts**</a>

**Input** (<small>[separate-inline-arguments.input.ts](transforms\convertInputSelectorsToArray\__testfixtures__\separate-inline-arguments.input.ts)</small>):

```ts
import { createSelector } from 'reselect'

export interface RootState {
todos: { id: number; completed: boolean }[]
alerts: { id: number; read: boolean }[]
}

const selectTodoById = createSelector(
(state: RootState) => state.todos,
(state: RootState, id: number) => id,
(todos, id) => todos.find(todo => todo.id === id)
)
```

**Output** (<small>[separate-inline-arguments.output.ts](transforms\convertInputSelectorsToArray\__testfixtures__\separate-inline-arguments.output.ts)</small>):

```ts
import { createSelector } from 'reselect'

export interface RootState {
todos: { id: number; completed: boolean }[]
alerts: { id: number; read: boolean }[]
}

const selectTodoById = createSelector(
[(state: RootState) => state.todos, (state: RootState, id: number) => id],
(todos, id) => todos.find(todo => todo.id === id)
)
```
<!--FIXTURES_CONTENT_END-->