Skip to content

Instantly share code, notes, and snippets.

@Tymek
Last active May 2, 2019 10:51
Show Gist options
  • Save Tymek/9906a914c5e675f5d8bb7ccabc853b33 to your computer and use it in GitHub Desktop.
Save Tymek/9906a914c5e675f5d8bb7ccabc853b33 to your computer and use it in GitHub Desktop.
Find unused action types in Redux stores. no eslint rule for that :| easy to miss during actionTypes refactoring
#!/usr/bin/env node
const fs = require('fs')
const isWin = process.platform === "win32";
const findCmd = isWin ? 'dir /s *store.js' : 'find src -name "*store.js"'
const exec = require('child_process').exec
const findStores = () => new Promise((resolve, reject) => {
exec(
findCmd,
function (error, stdout, stderr) {
resolve(stdout)
if (error !== null) {
console.log('exec error: ' + error)
console.log('stderr: ' + stderr)
reject(error)
}
}
)}
)
const cleanLineFromActionType = line => {
const pattern = /^\s*([\w_]+):\s/
const match = line.match(pattern)
return match ? match[1] : ''
}
const getActionTypes = store => {
const pattern = /const actionTypes = {((?:\n|\s.*)*)/mg
const match = store.match(pattern)
if(!match) {
return []
}
const lines = match[0].split('\n')
const types = lines.map(cleanLineFromActionType).filter(x => !!x)
return types
}
const getReducer = store => {
const pattern = /export const reducer = \(.+\n((?:\n|\s.*)*)/mg
const match = store.match(pattern)
if(!match) {
return ''
}
return match[0]
}
const finder = (action, reducer) => {
const pattern = new RegExp(`case actionTypes.${action}`, "gm")
const match = reducer.match(pattern)
return !!match
}
const parseStore = async file => {
const content = await new Promise((resolve, reject) => {
fs.readFile(file, 'utf8', function(err, contents) {
if (err) {
console.error(err)
resolve(null)
}
resolve(contents)
})
})
if (!content) {
return null
}
const actionTypes = getActionTypes(content)
const reducer = getReducer(content)
const unusedActions = actionTypes.filter(action => !finder(action, reducer)).join(', ')
return [file, unusedActions]
}
const main = async () => {
const stores = await findStores()
const storesList = stores.split('\n')
const fileUnusedActions = await Promise.all(storesList.map(parseStore))
const filteredFilesWithUnusedActions = fileUnusedActions.filter(store => store && store[1])
return filteredFilesWithUnusedActions.map(f => f.join('\n\t')).join('\n\n')
}
main().then(console.log)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment