# Guidelines
Any setup needed or usage specification will be here.

# Project setup
## [New project `cactus --project ...` command](#Comandos_(--help))
## Existing project
## Without redux
Create the following structure in your project:
```
public/
src/
    assets/
    common/
        components/
    i18n/
    style/
    index.js
    App.js
setting.js
settings-dev.json
settings-prod.json
```
What cactus will look:
- common folder existing, for when module name in component generation is empty.

### Files that need `// cactus` lines
```
// Nothing
```

## With Redux
Create the following structure in your project:
```
public/
src/
    assets/
    common/
        components/
        common.actions.js
        common.middleware.js
        common.reducer.js
        common.services.js
    i18n/
    redux/
        actions.js
        configureStore.js
        rootReducer.js
    style/
    index.js
    App.js
setting.js
settings-dev.json
settings-prod.json
```
What cactus will look:
- common folder existing, for when module name in component generation is empty.
- every module needs to have actions, middleware, reducer and services files (see common example above). If not, `cactus --request ...` will fail.

### Files that need `// cactus` lines
`any module (like common/)`

`theModule.actions.js`
```javascript
//... -> every previous action constant
export const AN_ACTION = 'AN_ACTION';
// cactus


const commonActions = {
    //... -> every previous action definition
    anAction: () => ({type: AN_ACTION}),
    // cactus
};
...
```

`theModule.middleware.js`
```javascript
import {
    //... -> every previous action constant import
    AN_ACTION,
    // cactus
} from './common.actions';
import actions from '../redux/actions';

const commonMiddleware = ({dispatch, getState}) => next => action => {
    next(action);
    switch (action.type) {
        //... -> every previous action case
        case AN_ACTION: break;
        // cactus

        default: break;
    }
};

export default commonMiddleware;
```

`theModule.reducer.js`
```javascript
import {
    //... -> every previous action constant import
    AN_ACTION
    // cactus
} from './common.actions';

const initialState = {
    //... -> every previous initialState variable
    anActionVariable: null,
    // cactus
};

const commonReducer = (state = initialState, action) => {
    switch (action.type) {
        //... -> every previous action case
        case AN_ACTION: return { ...state };
        //cactus

        default: return state;
    };
}
...
```

`theModule.services.js`
```javascript
export const services = {
    //... -> every other request
    aRequest: () => get(webApi + '/a-request'),
    // cactus
};
```

`src/redux/actions.js`
```javascript
//... -> every other module actions import
import aModuleActions from '../a-module/aModule.actions';
// cactus

export default {
    //... -> every other module definition
    aModule: aModuleActions,
    // cactus
};
```

`src/redux/configureStore.js`
```javascript
import { createBrowserHistory } from 'history'
import {applyMiddleware, compose, createStore} from 'redux'
import { connectRouter, routerMiddleware } from 'connected-react-router'
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import thunk from 'redux-thunk'
import logger from 'redux-logger';
import rootReducer from "./rootReducer";
//... -> every other middleware import
import aModuleMiddleware from './common/common.middleware';
// cactus

const persistConfig = {
    key: 'root',
    storage,
};

const persistedReducer = persistReducer(persistConfig, rootReducer);

const history = createBrowserHistory();

const middleware = routerMiddleware(history);

const store = process.env.NODE_ENV === 'production' ? createStore(
    connectRouter(history)(persistedReducer),
    undefined,
    compose(applyMiddleware(
        thunk, 
        middleware,
        //... -> every other middleware
        commonMiddleware,
        // cactus
    ))
) : createStore(
    connectRouter(history)(persistedReducer),
    undefined,
    compose(applyMiddleware(
        thunk, 
        logger, 
        middleware,
        //... -> every other middleware
        commonMiddleware,
        // cactus
    ))
);

const persistor = persistStore(store);

export default { store, persistor, history };
```

`src/redux/rootReducer.js`
```javascript
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router';
import { i18nReducer } from "react-redux-i18n";
//... -> every other reducer import
import aModuleReducer from '../a-module/aModule.reducer';
// cactus


export default createRootReducer = (history) => combineReducers({
    i18n: i18nReducer,
    router: connectRouter(history),
    //... -> every other reducer 
    common: aModuleReducer,
    // cactus
});
```

# CLI Commands Guideline

## Sin argumentos
```
C:\Users\Me\projects> cactus
```

Abre el menu de seleccion.
```
C:\Users\Me\projects> cactus
? Generate: (Use arrow keys)
> Component
  Module
  Project
  Request
```

### Componente submenu
```
? Generate: (Use arrow keys): Component
? Module: 
No module given, will be created in common/ module.
? Name: Aasdsdf
? Type:
> Functional
  Class
  Dumb class
? With redux: Yes/No
Component generated in common/components/Aasdsdf/
```

### Module submenu
```
? Generate: (Use arrow keys): Module
? Name: dsffa
? With redux: Yes/No
Module generated in src/dsffa
```

### Project submenu
```
? Generate: (Use arrow keys): Project
? Name: Jqweh
? With redux: Yes/No
```

### Request submenu
```
? Generate: (Use arrow keys): Request
? Module: dsffa
? Name: get-person
? Type: post
? Path: api/get-persons/all
```

## Comandos (--help)
```
Usage:
    cactus                                  Start generator menu prompts
    cactus --help                           Show this
    cactus --project                        Generate project
        -n <project-name>                   Must be in kebab-case 
        -r                                  With redux
    cactus --module                         Generate module
        -n <module-name>                    Must be in kebab-case 
        -r                                  With redux
    cactus --component                      Generate component
        -m <module-name>                    Module where component will be generated, must be in kebab-case
        -n <name>                           Must be in kebab-case
        -t <class|class dumb|functional>   Request type
        -r                                  With redux
    cactus --request                        Generate redux request
        -m <module-name>                    Module where component will be generated, must be in kebab-case
        -n <name>                           Must be in kebab-case
        -t <get|post|put|delete>            Request type
        -p <path>                           Path of the request, can be empty
```

### Examples
`cactus` 
[Menu](Sin-argumentos).

`cactus --help --asd --project asdasd` Ignores everything but "--help", shows the help text.

`cactus --project -n new-project -r` Creates a project with foldername "new-project" and redux integrated.
> redux integrated folder

Redux will be inside one folder
```
redux/
    actions.js
    configureStore.js
    rootReducer.js
```
`actions.js` All actions from every module.

`configureStore.js` Integrates middleware and returns the store used in index.ts.

`rootReducer.js` Integrates all reducers.

---
`cactus --module -n asd -r` Creates a module in the current project with the name "asd" if available (if not will be "asd-1", if not will be "asd-2", and so forth) with redux integrated.

`cactus --component -m users -n user-list -r` Creates a component in the module "users" with the name "UserList" in the current project and with redux integrated. Note that argument value should be in kebab-case, as cactus translates it to the needed type when generating (request variable name in users/components/UserList/ will be `getUserData: () => ...`)

`cactus --request -m users -n get-user-data -t get` Creates a request in redux services in the module "users" with the name "getUserData". Note that argument value should be in kebab-case, as cactus translates it to the needed type when generating (request variable name in users.services.js will be `getUserData: () => ...`)
