Skip to content

Commit

Permalink
Add duck battlecry generator (erikras#74)
Browse files Browse the repository at this point in the history
  • Loading branch information
pedsmoreira authored and erikras committed Jun 6, 2018
1 parent 713fceb commit de966e1
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 0 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,18 @@ bindActionCreators({loadWidgets, createWidget, updateWidget, removeWidget}, disp

[Todomvc using ducks.](https://github.com/goopscoop/ga-react-tutorial/tree/6-reduxActionsAndReducers)

### BattleCry generators

There are configurable [BattleCry](https://github.com/pedsmoreira/battlecry) generators ready to be downloaded and help scaffolding ducks:

```sh
npm install -g battlecry
cry download erikras/ducks-modular-redux
cry init duck
```

Run `cry --help` to check more info about the generators available;

### Implementation

The migration to this code structure was [painless](https://github.com/erikras/react-redux-universal-hot-example/commit/3fdf194683abb7c40f3cb7969fd1f8aa6a4f9c57), and I foresee it reducing much future development misery.
Expand Down
77 changes: 77 additions & 0 deletions battlecry/generators/duck/duck.generator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Generator, File, namedCasex, casex, log } from 'battlecry';

const CONFIG_FILE = 'configureStore.js';
const REDUX_PATH = 'src/redux';

export default class DuckGenerator extends Generator {
config = {
init: {
description: 'Create configStore.js file 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 actions() {
return (this.args.actions || ['set']).reverse();
}

init() {
const configFile = this.configFile;
if(configFile.exists) return log.warn(`Modular ducks have already been initiated. Please check the ${configFile.path} file`);

this.template(CONFIG_FILE).saveAs(configFile.path);
this.generator('duck').setArgs({name: 'todo'}).play('generate');
}

generate() {
this.addActionsToDuck();
this.addDuckToConfig();
}

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('// Actions', `const __NA_ME__ = '${casex(this.args.name, 'na-me')}/__NA-ME__';`, action);

file.after('switch (action.type) {', [
' case __NA_ME__:',
' // Perform action',
' return state;'
], action);

file.after('// Action Creators', [
namedCasex('export function __naMe__() {', + `${action}_${this.args.name}`),
' return { type: __NA_ME__ };',
'}',
''
], action);
});

file.saveAs(path, this.args.name);
}

addDuckToConfig() {
const file = this.configFile;
if(!file.exists) return null;

file
.afterLast('import ', "import __naMe__ from './modules/__naMe__'", this.args.name)
.after('combineReducers({', ' __naMe__,', this.args.name)
.save();
}
}
10 changes: 10 additions & 0 deletions battlecry/generators/duck/templates/__naMe__.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Actions

// Reducer
export default function reducer(state = {}, action = {}) {
switch (action.type) {
default: return state;
}
}

// Action Creators
12 changes: 12 additions & 0 deletions battlecry/generators/duck/templates/configureStore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { createStore, applyMiddleware, combineReducers } from 'redux';
import createLogger from 'redux-logger';

const loggerMiddleware = createLogger(); // initialize logger

const createStoreWithMiddleware = applyMiddleware(loggerMiddleware)(createStore); // apply logger to redux

const reducer = combineReducers({
});

const configureStore = (initialState) => createStoreWithMiddleware(reducer, initialState);
export default configureStore;

0 comments on commit de966e1

Please sign in to comment.