Last active
May 2, 2019 10:51
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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