musare.sh 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. #!/bin/bash
  2. set -e
  3. export PATH=/usr/local/bin:/usr/bin:/bin
  4. # Color variables
  5. CYAN='\033[33;36m';
  6. RED='\033[0;31m'
  7. YELLOW='\033[0;93m'
  8. GREEN='\033[0;32m'
  9. NC='\033[0m'
  10. # Print provided formatted error and exit with code (default 1)
  11. throw()
  12. {
  13. echo -e "${RED}${1}${NC}"
  14. exit "${2:-1}"
  15. }
  16. # Navigate to repository
  17. scriptLocation=$(dirname -- "$(readlink -fn -- "$0"; echo x)")
  18. cd "${scriptLocation%x}"
  19. # Import environment variables
  20. if [[ ! -f .env ]]; then
  21. throw "Error: .env does not exist" 2
  22. fi
  23. # shellcheck disable=SC1091
  24. source .env
  25. # Define docker command
  26. docker="${DOCKER_COMMAND:-docker}"
  27. if [[ ${docker} != "docker" && ${docker} != "podman" ]]; then
  28. throw "Error: Invalid DOCKER_COMMAND"
  29. fi
  30. set +e
  31. # Check if docker is installed
  32. ${docker} --version > /dev/null 2>&1
  33. dockerInstalled=$?
  34. # Define docker compose command
  35. dockerCompose="${docker} compose"
  36. # Check if docker compose is installed
  37. ${dockerCompose} version > /dev/null 2>&1
  38. composeInstalled=$?
  39. if [[ ${composeInstalled} -gt 0 ]]; then
  40. dockerCompose="${docker}-compose"
  41. ${dockerCompose} --version > /dev/null 2>&1
  42. composeInstalled=$?
  43. fi
  44. set -e
  45. # Exit if docker and/or docker compose is not installed
  46. if [[ ${dockerInstalled} -gt 0 || ${composeInstalled} -gt 0 ]]; then
  47. if [[ ${dockerInstalled} -eq 0 && ${composeInstalled} -gt 0 ]]; then
  48. throw "Error: ${dockerCompose} not installed."
  49. fi
  50. if [[ ${dockerInstalled} -gt 0 && ${composeInstalled} -eq 0 ]]; then
  51. throw "Error: ${docker} not installed."
  52. fi
  53. throw "Error: ${docker} and ${dockerCompose} not installed."
  54. fi
  55. # Add docker compose file arguments to command
  56. composeFiles="-f compose.yml"
  57. if [[ ${APP_ENV} == "development" ]]; then
  58. composeFiles="${composeFiles} -f compose.dev.yml"
  59. fi
  60. if [[ ${CONTAINER_MODE} == "local" ]]; then
  61. composeFiles="${composeFiles} -f compose.local.yml"
  62. fi
  63. if [[ -f compose.override.yml ]]; then
  64. composeFiles="${composeFiles} -f compose.override.yml"
  65. elif [[ -f docker-compose.override.yml ]]; then
  66. composeFiles="${composeFiles} -f docker-compose.override.yml"
  67. fi
  68. dockerCompose="${dockerCompose} ${composeFiles}"
  69. # Parse services from arguments string
  70. handleServices()
  71. {
  72. # shellcheck disable=SC2206
  73. validServices=($1)
  74. servicesArray=()
  75. invalidServices=false
  76. for x in "${@:2}"; do
  77. if [[ ${validServices[*]} =~ (^|[[:space:]])"$x"($|[[:space:]]) ]]; then
  78. if ! [[ ${servicesArray[*]} =~ (^|[[:space:]])"$x"($|[[:space:]]) ]]; then
  79. servicesArray+=("${x}")
  80. fi
  81. else
  82. if [[ $invalidServices == false ]]; then
  83. invalidServices="${x}"
  84. else
  85. invalidServices="${invalidServices} ${x}"
  86. fi
  87. fi
  88. done
  89. if [[ $invalidServices == false && ${#servicesArray[@]} -gt 0 ]]; then
  90. echo "1|${servicesArray[*]}"
  91. elif [[ $invalidServices == false ]]; then
  92. echo "1|all"
  93. else
  94. echo "0|Invalid Service(s): ${invalidServices}"
  95. fi
  96. }
  97. # Execute a docker command
  98. runDockerCommand()
  99. {
  100. validCommands=(start stop restart pull build ps logs)
  101. if ! [[ ${validCommands[*]} =~ (^|[[:space:]])"$2"($|[[:space:]]) ]]; then
  102. throw "Error: Invalid runDockerCommand input"
  103. fi
  104. servicesString=$(handleServices "backend frontend mongo redis" "${@:3}")
  105. if [[ ${servicesString:0:1} != 1 ]]; then
  106. throw "${servicesString:2}\n${YELLOW}Usage: ${1} [backend, frontend, mongo, redis]"
  107. fi
  108. if [[ ${servicesString:2:4} == "all" ]]; then
  109. servicesString=""
  110. pullServices="mongo redis"
  111. buildServices="backend frontend"
  112. else
  113. servicesString=${servicesString:2}
  114. pullArray=()
  115. buildArray=()
  116. if [[ "${servicesString}" == *mongo* ]]; then
  117. pullArray+=("mongo")
  118. fi
  119. if [[ "${servicesString}" == *redis* ]]; then
  120. pullArray+=("redis")
  121. fi
  122. if [[ "${servicesString}" == *backend* ]]; then
  123. buildArray+=("backend")
  124. fi
  125. if [[ "${servicesString}" == *frontend* ]]; then
  126. buildArray+=("frontend")
  127. fi
  128. pullServices="${pullArray[*]}"
  129. buildServices="${buildArray[*]}"
  130. fi
  131. if [[ ${2} == "stop" || ${2} == "restart" ]]; then
  132. # shellcheck disable=SC2086
  133. ${dockerCompose} stop ${servicesString}
  134. fi
  135. if [[ ${2} == "start" || ${2} == "restart" ]]; then
  136. # shellcheck disable=SC2086
  137. ${dockerCompose} up -d ${servicesString}
  138. fi
  139. if [[ ${2} == "pull" && ${pullServices} != "" ]]; then
  140. # shellcheck disable=SC2086
  141. ${dockerCompose} pull ${pullServices}
  142. fi
  143. if [[ ${2} == "build" && ${buildServices} != "" ]]; then
  144. # shellcheck disable=SC2086
  145. ${dockerCompose} build ${buildServices}
  146. fi
  147. if [[ ${2} == "ps" || ${2} == "logs" ]]; then
  148. # shellcheck disable=SC2086
  149. ${dockerCompose} "${2}" ${servicesString}
  150. fi
  151. }
  152. # Get docker container id
  153. getContainerId()
  154. {
  155. if [[ $docker == "docker" ]]; then
  156. containerId=$(${dockerCompose} ps -q "${1}")
  157. else
  158. containerId=$(${dockerCompose} ps \
  159. | sed '0,/CONTAINER/d' \
  160. | awk "/${1}/ {print \$1;exit}")
  161. fi
  162. echo "${containerId}"
  163. }
  164. # Reset services
  165. handleReset()
  166. {
  167. servicesString=$(handleServices "backend frontend mongo redis" "${@:2}")
  168. if [[ ${servicesString:0:1} != 1 ]]; then
  169. throw "${servicesString:2}\n${YELLOW}Usage: ${1} [backend, frontend, mongo, redis]"
  170. fi
  171. confirmMessage="${GREEN}Are you sure you want to reset all data"
  172. if [[ ${servicesString:2:4} != "all" ]]; then
  173. confirmMessage="${confirmMessage} for $(echo "${servicesString:2}" | tr ' ' ',')"
  174. fi
  175. echo -e "${confirmMessage}? ${YELLOW}[y,n]: ${NC}"
  176. read -r confirm
  177. if [[ "${confirm}" != y* ]]; then
  178. throw "Cancelled reset"
  179. fi
  180. if [[ ${servicesString:2:4} == "all" ]]; then
  181. runDockerCommand "$(basename "$0") $1" stop
  182. ${dockerCompose} rm -v --force
  183. else
  184. # shellcheck disable=SC2086
  185. runDockerCommand "$(basename "$0") $1" stop ${servicesString:2}
  186. # shellcheck disable=SC2086
  187. ${dockerCompose} rm -v --force ${servicesString:2}
  188. fi
  189. }
  190. # Attach to service in docker container
  191. attachContainer()
  192. {
  193. containerId=$(getContainerId "${2}")
  194. if [[ -z $containerId ]]; then
  195. throw "Error: ${2} offline, please start to attach."
  196. fi
  197. case $2 in
  198. backend)
  199. echo -e "${YELLOW}Detach with CTRL+P+Q${NC}"
  200. ${docker} attach "$containerId"
  201. ;;
  202. mongo)
  203. MONGO_VERSION_INT=${MONGO_VERSION:0:1}
  204. echo -e "${YELLOW}Detach with CTRL+D${NC}"
  205. if [[ $MONGO_VERSION_INT -ge 5 ]]; then
  206. ${dockerCompose} exec mongo mongosh musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "disableTelemetry()" --shell
  207. else
  208. ${dockerCompose} exec mongo mongo musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}"
  209. fi
  210. ;;
  211. redis)
  212. echo -e "${YELLOW}Detach with CTRL+C${NC}"
  213. ${dockerCompose} exec redis redis-cli -a "${REDIS_PASSWORD}"
  214. ;;
  215. *)
  216. throw "Invalid service ${2}\n${YELLOW}Usage: ${1} [backend, mongo, redis]"
  217. ;;
  218. esac
  219. }
  220. # Lint codebase, docs, scripts, etc
  221. handleLinting()
  222. {
  223. set +e
  224. # shellcheck disable=SC2001
  225. services=$(sed "s/\(\ \)\{0,1\}\(-\)\{0,2\}fix//g;t;q1" <<< "${@:2}")
  226. fixFound=$?
  227. if [[ $fixFound -eq 0 ]]; then
  228. fix="--fix"
  229. echo -e "${GREEN}Auto-fix enabled${NC}"
  230. fi
  231. # shellcheck disable=SC2001
  232. services=$(sed "s/\(\ \)\{0,1\}\(-\)\{0,2\}no-cache//g;t;q1" <<< "${services}")
  233. noCacheFound=$?
  234. cache="--cache"
  235. if [[ $noCacheFound -eq 0 ]]; then
  236. cache=""
  237. echo -e "${YELLOW}ESlint cache disabled${NC}"
  238. fi
  239. set -e
  240. # shellcheck disable=SC2068
  241. servicesString=$(handleServices "backend frontend docs shell" ${services[@]})
  242. if [[ ${servicesString:0:1} != 1 ]]; then
  243. throw "${servicesString:2}\n${YELLOW}Usage: ${1} [backend, frontend, docs, shell] [fix]"
  244. fi
  245. set +e
  246. if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *frontend* ]]; then
  247. echo -e "${CYAN}Running frontend lint...${NC}"
  248. # shellcheck disable=SC2086
  249. ${dockerCompose} exec -T frontend npm run lint -- ${cache} ${fix}
  250. frontendExitValue=$?
  251. fi
  252. if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *backend* ]]; then
  253. echo -e "${CYAN}Running backend lint...${NC}"
  254. # shellcheck disable=SC2086
  255. ${dockerCompose} exec -T backend npm run lint -- ${cache} ${fix}
  256. backendExitValue=$?
  257. fi
  258. if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *docs* ]]; then
  259. echo -e "${CYAN}Running docs lint...${NC}"
  260. # shellcheck disable=SC2086
  261. ${docker} run --rm -v "${scriptLocation}":/workdir ghcr.io/igorshubovych/markdownlint-cli:latest ".wiki" "*.md" ${fix}
  262. docsExitValue=$?
  263. fi
  264. if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *shell* ]]; then
  265. echo -e "${CYAN}Running shell lint...${NC}"
  266. ${docker} run --rm -v "${scriptLocation}":/mnt koalaman/shellcheck:stable ./*.sh ./**/*.sh
  267. shellExitValue=$?
  268. fi
  269. set -e
  270. if [[ ${frontendExitValue} -gt 0 || ${backendExitValue} -gt 0 || ${docsExitValue} -gt 0 || ${shellExitValue} -gt 0 ]]; then
  271. exit 1
  272. fi
  273. }
  274. # Validate typescript in services
  275. handleTypescript()
  276. {
  277. set +e
  278. # shellcheck disable=SC2001
  279. services=$(sed "s/\(\ \)\{0,1\}\(-\)\{0,2\}strict//g;t;q1" <<< "${@:2}")
  280. strictFound=$?
  281. if [[ $strictFound -eq 0 ]]; then
  282. strict="--strict"
  283. echo -e "${GREEN}Strict mode enabled${NC}"
  284. fi
  285. set -e
  286. # shellcheck disable=SC2068
  287. servicesString=$(handleServices "backend frontend" ${services[@]})
  288. if [[ ${servicesString:0:1} != 1 ]]; then
  289. throw "${servicesString:2}\n${YELLOW}Usage: ${1} [backend, frontend] [strict]"
  290. fi
  291. set +e
  292. if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *frontend* ]]; then
  293. echo -e "${CYAN}Running frontend typescript check...${NC}"
  294. # shellcheck disable=SC2086
  295. ${dockerCompose} exec -T frontend npm run typescript -- ${strict}
  296. frontendExitValue=$?
  297. fi
  298. if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *backend* ]]; then
  299. echo -e "${CYAN}Running backend typescript check...${NC}"
  300. # shellcheck disable=SC2086
  301. ${dockerCompose} exec -T backend npm run typescript -- ${strict}
  302. backendExitValue=$?
  303. fi
  304. set -e
  305. if [[ ${frontendExitValue} -gt 0 || ${backendExitValue} -gt 0 ]]; then
  306. exit 1
  307. fi
  308. }
  309. # Execute automated tests in services
  310. handleTests()
  311. {
  312. # shellcheck disable=SC2068
  313. servicesString=$(handleServices "frontend" ${services[@]})
  314. if [[ ${servicesString:0:1} != 1 ]]; then
  315. throw "${servicesString:2}\n${YELLOW}Usage: ${1} [frontend]"
  316. fi
  317. set +e
  318. if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *frontend* ]]; then
  319. echo -e "${CYAN}Running frontend tests...${NC}"
  320. ${dockerCompose} exec -T frontend npm run test -- --run
  321. frontendExitValue=$?
  322. fi
  323. set -e
  324. if [[ ${frontendExitValue} -gt 0 ]]; then
  325. exit 1
  326. fi
  327. }
  328. # Execute test coverage in services
  329. handleTestCoverage()
  330. {
  331. servicesString=$(handleServices "frontend" "${@:2}")
  332. if [[ ${servicesString:0:1} != 1 ]]; then
  333. throw "${servicesString:2}\n${YELLOW}Usage: ${1} [frontend]"
  334. fi
  335. set +e
  336. if [[ ${servicesString:2:4} == "all" || "${servicesString:2}" == *frontend* ]]; then
  337. echo -e "${CYAN}Running frontend test coverage report...${NC}"
  338. ${dockerCompose} exec -T frontend npm run coverage
  339. frontendExitValue=$?
  340. fi
  341. set -e
  342. if [[ ${frontendExitValue} -gt 0 ]]; then
  343. exit 1
  344. fi
  345. }
  346. # Update Musare
  347. handleUpdate()
  348. {
  349. musareshModified=$(git diff HEAD -- musare.sh)
  350. git fetch
  351. updated=$(git log --name-only --oneline HEAD..@\{u\})
  352. if [[ ${updated} == "" ]]; then
  353. echo -e "${GREEN}Already up to date${NC}"
  354. exit 0
  355. fi
  356. set +e
  357. breakingConfigChange=$(git rev-list "$(git rev-parse HEAD)" | grep d8b73be1de231821db34c677110b7b97e413451f)
  358. set -e
  359. if [[ -f backend/config/default.json && -z $breakingConfigChange ]]; then
  360. throw "Configuration has breaking changes. Please rename or remove 'backend/config/default.json' and run the update command again to continue."
  361. fi
  362. set +e
  363. musareshChange=$(echo "${updated}" | grep "musare.sh")
  364. dbChange=$(echo "${updated}" | grep "backend/logic/db/schemas")
  365. bcChange=$(echo "${updated}" | grep "backend/config/default.json")
  366. set -e
  367. if [[ ( $2 == "auto" && -z $dbChange && -z $bcChange && -z $musareshChange ) || -z $2 ]]; then
  368. if [[ -n $musareshChange && $(git diff @\{u\} -- musare.sh) != "" ]]; then
  369. if [[ $musareshModified != "" ]]; then
  370. throw "musare.sh has been modified, please reset these changes and run the update command again to continue."
  371. else
  372. git checkout @\{u\} -- musare.sh
  373. throw "${YELLOW}musare.sh has been updated, please run the update command again to continue."
  374. fi
  375. else
  376. git pull
  377. echo -e "${CYAN}Updating...${NC}"
  378. runDockerCommand "$(basename "$0") $1" pull
  379. runDockerCommand "$(basename "$0") $1" build
  380. runDockerCommand "$(basename "$0") $1" restart
  381. echo -e "${GREEN}Updated!${NC}"
  382. if [[ -n $dbChange ]]; then
  383. echo -e "${RED}Database schema has changed, please run migration!${NC}"
  384. fi
  385. if [[ -n $bcChange ]]; then
  386. echo -e "${RED}Backend config has changed, please update!${NC}"
  387. fi
  388. fi
  389. elif [[ $2 == "auto" ]]; then
  390. throw "Auto Update Failed! musare.sh, database and/or config has changed!"
  391. fi
  392. }
  393. # Backup the database
  394. handleBackup()
  395. {
  396. if [[ -z "${BACKUP_LOCATION}" ]]; then
  397. backupLocation="${scriptLocation%x}/backups"
  398. else
  399. backupLocation="${BACKUP_LOCATION%/}"
  400. fi
  401. if [[ ! -d "${backupLocation}" ]]; then
  402. echo -e "${YELLOW}Creating backup directory at ${backupLocation}${NC}"
  403. mkdir "${backupLocation}"
  404. fi
  405. if [[ -z "${BACKUP_NAME}" ]]; then
  406. backupLocation="${backupLocation}/musare-$(date +"%Y-%m-%d-%s").dump"
  407. else
  408. backupLocation="${backupLocation}/${BACKUP_NAME}"
  409. fi
  410. echo -e "${YELLOW}Creating backup at ${backupLocation}${NC}"
  411. ${dockerCompose} exec -T mongo sh -c "mongodump --authenticationDatabase musare -u ${MONGO_USER_USERNAME} -p ${MONGO_USER_PASSWORD} -d musare --archive" > "${backupLocation}"
  412. }
  413. # Restore database from dump
  414. handleRestore()
  415. {
  416. if [[ -z $2 ]]; then
  417. echo -e "${GREEN}Please enter the full path of the dump you wish to restore: ${NC}"
  418. read -r restoreFile
  419. else
  420. restoreFile=$2
  421. fi
  422. if [[ -z ${restoreFile} ]]; then
  423. throw "Error: no restore path given, cancelled restoration."
  424. elif [[ -d ${restoreFile} ]]; then
  425. throw "Error: restore path given is a directory, cancelled restoration."
  426. elif [[ ! -f ${restoreFile} ]]; then
  427. throw "Error: no file at restore path given, cancelled restoration."
  428. else
  429. ${dockerCompose} exec -T mongo sh -c "mongorestore --authenticationDatabase musare -u ${MONGO_USER_USERNAME} -p ${MONGO_USER_PASSWORD} --archive" < "${restoreFile}"
  430. fi
  431. }
  432. # Toggle user admin role
  433. handleAdmin()
  434. {
  435. MONGO_VERSION_INT=${MONGO_VERSION:0:1}
  436. case $2 in
  437. add)
  438. if [[ -z $3 ]]; then
  439. echo -e "${GREEN}Please enter the username of the user you wish to make an admin: ${NC}"
  440. read -r adminUser
  441. else
  442. adminUser=$3
  443. fi
  444. if [[ -z $adminUser ]]; then
  445. throw "Error: Username for new admin not provided."
  446. fi
  447. if [[ $MONGO_VERSION_INT -ge 5 ]]; then
  448. ${dockerCompose} exec mongo mongosh musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "disableTelemetry(); db.users.updateOne({username: '${adminUser}'}, {\$set: {role: 'admin'}})"
  449. else
  450. ${dockerCompose} exec mongo mongo musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "db.users.updateOne({username: '${adminUser}'}, {\$set: {role: 'admin'}})"
  451. fi
  452. ;;
  453. remove)
  454. if [[ -z $3 ]]; then
  455. echo -e "${GREEN}Please enter the username of the user you wish to remove as admin: ${NC}"
  456. read -r adminUser
  457. else
  458. adminUser=$3
  459. fi
  460. if [[ -z $adminUser ]]; then
  461. throw "Error: Username for new admin not provided."
  462. fi
  463. if [[ $MONGO_VERSION_INT -ge 5 ]]; then
  464. ${dockerCompose} exec mongo mongosh musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "disableTelemetry(); db.users.updateOne({username: '${adminUser}'}, {\$set: {role: 'default'}})"
  465. else
  466. ${dockerCompose} exec mongo mongo musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "db.users.updateOne({username: '${adminUser}'}, {\$set: {role: 'default'}})"
  467. fi
  468. ;;
  469. *)
  470. throw "Invalid command $2\n${YELLOW}Usage: ${1} [add,remove] username"
  471. ;;
  472. esac
  473. }
  474. availableCommands=$(cat << COMMANDS
  475. start - Start services
  476. stop - Stop services
  477. restart - Restart services
  478. status - Service status
  479. logs - View logs for services
  480. update - Update Musare
  481. attach [backend,mongo,redis] - Attach to backend service, mongo or redis shell
  482. build - Build services
  483. lint - Run lint on frontend, backend, docs and/or shell
  484. backup - Backup database data to file
  485. restore - Restore database data from backup file
  486. reset - Reset service data
  487. admin [add,remove] - Assign/unassign admin role to/from a user
  488. typescript - Run typescript checks on frontend and/or backend
  489. COMMANDS
  490. )
  491. # Handle command
  492. case $1 in
  493. start)
  494. echo -e "${CYAN}Musare | Start Services${NC}"
  495. # shellcheck disable=SC2068
  496. runDockerCommand "$(basename "$0") $1" start ${@:2}
  497. ;;
  498. stop)
  499. echo -e "${CYAN}Musare | Stop Services${NC}"
  500. # shellcheck disable=SC2068
  501. runDockerCommand "$(basename "$0") $1" stop ${@:2}
  502. ;;
  503. restart)
  504. echo -e "${CYAN}Musare | Restart Services${NC}"
  505. # shellcheck disable=SC2068
  506. runDockerCommand "$(basename "$0") $1" restart ${@:2}
  507. ;;
  508. build)
  509. echo -e "${CYAN}Musare | Build Services${NC}"
  510. # shellcheck disable=SC2068
  511. runDockerCommand "$(basename "$0") $1" pull ${@:2}
  512. # shellcheck disable=SC2068
  513. runDockerCommand "$(basename "$0") $1" build ${@:2}
  514. ;;
  515. status)
  516. echo -e "${CYAN}Musare | Service Status${NC}"
  517. # shellcheck disable=SC2068
  518. runDockerCommand "$(basename "$0") $1" ps ${@:2}
  519. ;;
  520. reset)
  521. echo -e "${CYAN}Musare | Reset Services${NC}"
  522. # shellcheck disable=SC2068
  523. handleReset "$(basename "$0") $1" ${@:2}
  524. ;;
  525. attach)
  526. echo -e "${CYAN}Musare | Attach${NC}"
  527. attachContainer "$(basename "$0") $1" "$2"
  528. ;;
  529. lint|eslint)
  530. echo -e "${CYAN}Musare | Lint${NC}"
  531. # shellcheck disable=SC2068
  532. handleLinting "$(basename "$0") $1" ${@:2}
  533. ;;
  534. typescript|ts)
  535. echo -e "${CYAN}Musare | TypeScript Check${NC}"
  536. # shellcheck disable=SC2068
  537. handleTypescript "$(basename "$0") $1" ${@:2}
  538. ;;
  539. test)
  540. echo -e "${CYAN}Musare | Test${NC}"
  541. # shellcheck disable=SC2068
  542. handleTests "$(basename "$0") $1" ${@:2}
  543. ;;
  544. test:coverage)
  545. echo -e "${CYAN}Musare | Test Coverage${NC}"
  546. # shellcheck disable=SC2068
  547. handleTestCoverage "$(basename "$0") $1" ${@:2}
  548. ;;
  549. update)
  550. echo -e "${CYAN}Musare | Update${NC}"
  551. # shellcheck disable=SC2068
  552. handleUpdate "$(basename "$0") $1" ${@:2}
  553. ;;
  554. logs)
  555. echo -e "${CYAN}Musare | Logs${NC}"
  556. # shellcheck disable=SC2068
  557. runDockerCommand "$(basename "$0") $1" logs ${@:2}
  558. ;;
  559. backup)
  560. echo -e "${CYAN}Musare | Backup${NC}"
  561. # shellcheck disable=SC2068
  562. handleBackup "$(basename "$0") $1" ${@:2}
  563. ;;
  564. restore)
  565. echo -e "${CYAN}Musare | Restore${NC}"
  566. # shellcheck disable=SC2068
  567. handleRestore "$(basename "$0") $1" ${@:2}
  568. ;;
  569. admin)
  570. echo -e "${CYAN}Musare | Add Admin${NC}"
  571. # shellcheck disable=SC2068
  572. handleAdmin "$(basename "$0") $1" ${@:2}
  573. ;;
  574. "")
  575. echo -e "${CYAN}Musare | Available Commands${NC}"
  576. echo -e "${YELLOW}${availableCommands}${NC}"
  577. ;;
  578. *)
  579. echo -e "${CYAN}Musare${NC}"
  580. echo -e "${RED}Error: Invalid Command $1${NC}"
  581. echo -e "${CYAN}Available Commands:${NC}"
  582. echo -e "${YELLOW}${availableCommands}${NC}"
  583. exit 1
  584. ;;
  585. esac