Last active
August 28, 2017 14:25
-
-
Save martin056/ecbde18139bbc46a15c89f6a6115e5a4 to your computer and use it in GitHub Desktop.
Bash script that generates containers for Redux apps. The directories it uses are not configurable at the moment - if you have user `create-react-app` it will work for you.
This file contains hidden or 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
#!/bin/bash | |
# USAGE (cd utility/ first!): ./create_container.sh -n <CONTAINER_NAME> -a <ACTION_1> (-a <ACTION_2>...) | |
RED='\033[0;31m' | |
GREEN='\033[0;32m' | |
NC='\033[0m' | |
SRC_PATH=../src | |
CONTAINERS_PATH=${SRC_PATH}/containers | |
GLOBAL_REDUCER_FILE=${SRC_PATH}/global-reducer.jsx | |
function join_by { | |
# function that joins the given array by the splitter given. | |
local IFS="$1"; shift; echo "$*"; | |
} | |
# Get the arguments | |
while getopts ":n:a:" opt; do | |
case $opt in | |
n) CONTAINER_NAME="$OPTARG";; | |
a) ACTIONS+=($OPTARG);; | |
\?) echo "${RED}Invalid option -$OPTARG ${NC}" >&2;; | |
esac | |
done | |
shift $((OPTIND -1)) | |
# Uppercase all actions | |
ACTIONS_UPPERCASED=() | |
if [[ ${#ACTIONS[@]} = 0 ]]; then | |
echo "No actions provided..." | |
else | |
for ACTION in "${ACTIONS[@]}"; do | |
ACTION_NAME=$(echo "${ACTION}" | tr '[:lower:]' '[:upper:]') | |
ACTIONS_UPPERCASED=("${ACTIONS_UPPERCASED[@]}" "${ACTION_NAME}") | |
done | |
fi | |
# Check if the container starts with Uppercase | |
re='[A-Z]' | |
if [[ ${CONTAINER_NAME::1} =~ $re ]]; then | |
echo -e "${GREEN}Container ${CONTAINER_NAME} will be generated...${NC}" | |
else | |
echo -e "${RED}Containers must start with Uppercase!${NC}" | |
exit 99 | |
fi | |
# Generate files | |
CONTAINER_DIR_PATH=${CONTAINERS_PATH}/${CONTAINER_NAME} | |
mkdir ${CONTAINER_DIR_PATH} | |
touch ${CONTAINER_DIR_PATH}/component.jsx \ | |
${CONTAINER_DIR_PATH}/reducer.jsx \ | |
${CONTAINER_DIR_PATH}/actions.jsx \ | |
${CONTAINER_DIR_PATH}/constants.js \ | |
${CONTAINER_DIR_PATH}/sagas.jsx \ | |
${CONTAINER_DIR_PATH}/services.jsx | |
# Generate initial code for component | |
COMPONENT=${CONTAINER_DIR_PATH}/component.jsx | |
COMPONENT_CONFIG=$( cat <<SETVAR | |
import React from 'react'; | |
import { connect } from 'react-redux'; | |
export class ${CONTAINER_NAME} extends React.Component { | |
constructor(props) { | |
super(props); | |
} | |
render() { | |
return () | |
} | |
}; | |
export default connect()(${CONTAINER_NAME}); | |
SETVAR | |
) | |
echo -e "${COMPONENT_CONFIG}" > ${COMPONENT} | |
# Generate initial code for reducer | |
REDUCER=${CONTAINER_DIR_PATH}/reducer.jsx | |
# Lower the first letter of the component | |
CONTAINER_LOWER_FIRST_LETTER="$(echo ${CONTAINER_NAME::1} | tr [:upper:] [:lower:])"${CONTAINER_NAME:1} | |
REDUCER_NAME=${CONTAINER_LOWER_FIRST_LETTER}"Reducer" # <GivenName> -> <givenName>Reducer | |
ACTIONS_STRING=$(join_by , "${ACTIONS_UPPERCASED[@]}") # ACTION_1,ACTION_2,ACTION_3... | |
ACTION_CASES=() | |
for ACTION in "${ACTIONS_UPPERCASED[@]}"; do | |
ACTION_CASE=$( cat <<SETVAR | |
case ${ACTION}: | |
return { | |
// Object.assign({}, state, ...) | |
};\n | |
SETVAR | |
) | |
ACTION_CASES=("${ACTION_CASES[@]}""${ACTION_CASE}") | |
done | |
REDUCER_CONFIG=$( cat <<SETVAR | |
import { ${ACTIONS_STRING} } from './constants'; | |
const ${REDUCER_NAME} = (state = {}, action) => { | |
switch(action.type) { | |
${ACTION_CASES[@]} | |
default: | |
return state; | |
} | |
}; | |
export default ${REDUCER_NAME}; | |
SETVAR | |
) | |
echo -e "${REDUCER_CONFIG}" > ${REDUCER} | |
REDUCER_PATH="'"./containers/${CONTAINER_NAME}/reducer"'" # think of better way to do this! | |
# Import the new reducer in the global reducer | |
echo -e "$(awk -v reducer="${REDUCER_NAME}" \ | |
-v reducer_path="${REDUCER_PATH}" \ | |
'/import '"{"' combineReducers '"}"' from/ { print; print "import "'"reducer"'" from "'"reducer_path"'";"; next }1' \ | |
${GLOBAL_REDUCER_FILE})" > ${GLOBAL_REDUCER_FILE} | |
# Add the new reducer to the global reducer | |
echo -e "$(awk -v container="${CONTAINER_LOWER_FIRST_LETTER}" \ | |
-v reducer="${REDUCER_NAME}" \ | |
'/const appReducer = combineReducers/ { print; print " "'"container"'": "'"reducer"'","; next }1' \ | |
${GLOBAL_REDUCER_FILE})" > ${GLOBAL_REDUCER_FILE} | |
# Add the actions to the constants file | |
CONSTANTS_FILE=${CONTAINER_DIR_PATH}/constants.js | |
for ACTION in "${ACTIONS_UPPERCASED[@]}"; do | |
echo -e "export const ${ACTION} = '${ACTION}';" >> ${CONSTANTS_FILE} | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment