From aae6fe9256df2f148d68f24e5a902d3edbbf65f5 Mon Sep 17 00:00:00 2001 From: Erick Peniche Date: Wed, 1 Apr 2020 17:22:36 -0500 Subject: [PATCH] Add generator files for duck pattern using redux starter kit --- .../duck-starter-kit.generator.js | 98 +++++++++++++++++++ .../duck-starter-kit/templates/__naMe__.js | 12 +++ .../templates/configureStore.js | 19 ++++ .../duck-starter-kit/templates/reducers.js | 6 ++ 4 files changed, 135 insertions(+) create mode 100644 battlecry/generators/duck-starter-kit/duck-starter-kit.generator.js create mode 100644 battlecry/generators/duck-starter-kit/templates/__naMe__.js create mode 100644 battlecry/generators/duck-starter-kit/templates/configureStore.js create mode 100644 battlecry/generators/duck-starter-kit/templates/reducers.js diff --git a/battlecry/generators/duck-starter-kit/duck-starter-kit.generator.js b/battlecry/generators/duck-starter-kit/duck-starter-kit.generator.js new file mode 100644 index 0000000..f4392e3 --- /dev/null +++ b/battlecry/generators/duck-starter-kit/duck-starter-kit.generator.js @@ -0,0 +1,98 @@ +import { Generator, File, casex, log } from 'battlecry'; + +const CONFIG_FILE = 'configureStore.js'; +const REDUCERS_FILE = 'reducers.js'; +const REDUX_PATH = 'src/redux'; + +export default class DuckStarterKitGenerator extends Generator { + config = { + init: { + description: 'Create configStore.js and reducers.js files using redux-starter-kit and an example duck' + }, + generate: { + args: 'name ...actions?', + description: 'Create or modify duck to add actions' + } + }; + + get configFile() { + const template = this.template(CONFIG_FILE); + const path = `${REDUX_PATH}/${template.filename}`; + + return new File(path); + } + + get reducersFile() { + const template = this.template(REDUCERS_FILE); + const path = `${REDUX_PATH}/${template.filename}`; + + return new File(path); + } + + get actions() { + return (this.args.actions || ['set']).reverse(); + } + + init() { + const configFile = this.configFile; + + if(configFile.exists) { + log.warn(`${CONFIG_FILE} has already been initiated. Please check the ${configFile.path} file`); + } else { + this.template(CONFIG_FILE).saveAs(configFile.path); + } + + const reducersFile = this.reducersFile; + + if(reducersFile.exists) { + log.warn(`${REDUCERS_FILE} has already been initiated. Please check the ${reducersFile.path} file`); + } else { + this.template(REDUCERS_FILE).saveAs(reducersFile.path); + } + + if (!configFile.exists && !reducersFile.exists) { + this.generator('duck-starter-kit').setArgs({name: 'todo'}).play('generate'); + } + } + + generate() { + this.addActionsToDuck(); + this.addDuckToReducers(); + } + + addActionsToDuck() { + const template = this.template('_*'); + const path = `${REDUX_PATH}/modules/${template.filename}`; + + let file = new File(path, this.args.name); + if(!file.exists) file = template; + + this.actions.forEach(action => { + file.after('// Action Creators', `export const __naMe__ = createAction('${casex(this.args.name, 'na-me')}/__NA-ME__');`, action); + + file.after('createReducer(initialState, {', [ + ' [__naMe__]: (state, action) => {', + ' // Perform action', + ' },' + ], action); + }); + + file.saveAs(path, this.args.name); + } + + addDuckToReducers() { + const file = this.reducersFile; + + if(!file.exists) return null; + + try { + const reducerExistsLine = file.search(' __naMe__,', this.args.name); + log.warn(`Found existing reducer "${casex(this.args.name, 'naMe')}" in line ${reducerExistsLine} of ${file.dirname}/${file.filename}`); + } catch (e) { + file + .after('// Reducers', "import __naMe__ from './modules/__naMe__'", this.args.name) + .after('const reducers = {', ' __naMe__,', this.args.name) + .save(); + } + } +} diff --git a/battlecry/generators/duck-starter-kit/templates/__naMe__.js b/battlecry/generators/duck-starter-kit/templates/__naMe__.js new file mode 100644 index 0000000..e991239 --- /dev/null +++ b/battlecry/generators/duck-starter-kit/templates/__naMe__.js @@ -0,0 +1,12 @@ +import { createReducer, createAction } from 'redux-starter-kit'; + +// Action Creators + +// Reducer +const initialState = { +}; + +const reducer = createReducer(initialState, { +}); + +export default reducer; diff --git a/battlecry/generators/duck-starter-kit/templates/configureStore.js b/battlecry/generators/duck-starter-kit/templates/configureStore.js new file mode 100644 index 0000000..c17706d --- /dev/null +++ b/battlecry/generators/duck-starter-kit/templates/configureStore.js @@ -0,0 +1,19 @@ +import { configureStore, getDefaultMiddleware } from 'redux-starter-kit'; +import { combineReducers } from 'redux'; +import reducers from './reducers'; + +const rootReducer = combineReducers(reducers); + +export default function configureAppStore(preloadedState) { + const store = configureStore({ + reducer: rootReducer, + middleware: [...getDefaultMiddleware()], + preloadedState, + }); + + if (process.env.NODE_ENV !== 'production' && module.hot) { + module.hot.accept('./reducers', () => store.replaceReducer(rootReducer)); + } + + return store; +} diff --git a/battlecry/generators/duck-starter-kit/templates/reducers.js b/battlecry/generators/duck-starter-kit/templates/reducers.js new file mode 100644 index 0000000..6a17a91 --- /dev/null +++ b/battlecry/generators/duck-starter-kit/templates/reducers.js @@ -0,0 +1,6 @@ +// Reducers + +const reducers = { +}; + +export default reducers;