jichoi / lms_front star
[jichoi] 08-01
240801 최정임 페이지 생성
@730242fa011d75cc74b0b5eb45534e21b0883a27
 
.gitignore (added)
+++ .gitignore
@@ -0,0 +1,3 @@
+client/build/
+server/logs/
+node_modules/(파일 끝에 줄바꿈 문자 없음)
 
Global.js (added)
+++ Global.js
@@ -0,0 +1,17 @@
+const PROJECT_NAME = 'NodeJS Web Server Framework(Vue)';
+const PROJECT_VERSION = '1.0';
+const BASE_DIR = __dirname;
+const LOG_BASE_DIR = `${__dirname}/server/logs`;
+const SERVICE_STATUS = process.env.NODE_ENV;//development, production
+const PORT = 80;
+const API_SERVER_HOST = 'localhost:8080';
+
+module.exports = {
+    PROJECT_NAME,
+    PROJECT_VERSION,
+    BASE_DIR,
+    LOG_BASE_DIR,
+    SERVICE_STATUS,
+    PORT,
+    API_SERVER_HOST
+}(파일 끝에 줄바꿈 문자 없음)
 
client/resources/css/common.css (added)
+++ client/resources/css/common.css
@@ -0,0 +1,1072 @@
+@charset "utf-8";
+
+:root {
+    /* color */
+    --color-black: #231815;
+    --color-lightGray: #C6C6C6;
+    --color-gray: #c6c6c6;
+    --color-white: #ffffff;
+    --color-orange: #fbbe28;
+    --color-light-orange: #fff4d7;
+    --color-green: #00A8BA;
+    --color-lightGreen: #EBF7EC;
+    --color-red: #ff5d5d;
+    --color-blue: #213f99;
+    --color-darkG: #434343;
+    --color-blueE: #e3ecff;
+    --color-skyBlue: #f5f8ff;
+    --color-navGreen:#00A8BA;
+    --color-tableGreen:#EBF7EC;
+    --color-tableRightGreen:#f2faf2;
+    --color-darkBlue:#2b53c9;
+    --color-skyDarkBlue:#456ad7;
+    --color-lightBlue:#869de5;
+    --color-lightskyBlue:#96aae8;
+    --color-lightlightBlue:#d6def6;
+    --color-boxBackground:#f9f9f9;
+    --color-imgBox:#f8f8f8;
+    --color-inputBoder:#717171;
+    --color-text:#8E8E8E;
+
+    --color-tableBack:#EDF1F5;
+    --color-buttonBack:#EBF7EC;
+}
+
+
+/* 정렬 */
+.flex {
+    display: flex;
+}
+
+.flex-column {
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+}
+
+
+.justify-start {
+    justify-content: flex-start;
+}
+
+.justify-center {
+    justify-content: center;
+}
+
+.justify-between {
+    justify-content: space-between;
+}
+
+.justify-around {
+    justify-content: space-around;
+}
+
+.justify-end {
+    justify-content: flex-end;
+}
+
+.align-start {
+    align-items: flex-start;
+}
+
+.align-center {
+    align-items: center;
+}
+
+.align-end {
+    align-items: flex-end;
+}
+
+
+.flex5,
+.flex10,
+.flex15,
+.flex20,
+.flex25,
+.flex30,
+.flex35,
+.flex40,
+.flex45,
+.flex50,
+.flex55,
+.flex60,
+.flex65,
+.flex70,
+.flex75,
+.flex80,
+.flex85,
+.flex90,
+.flex95,
+.flex100 {
+    padding-left: 10px;
+    padding-right: 10px;
+}
+
+.no-gutter>.flex5,
+.no-gutter>.flex10,
+.no-gutter>.flex15,
+.no-gutter>.flex20,
+.no-gutter>.flex25,
+.no-gutter>.flex30,
+.no-gutter>.flex35,
+.no-gutter>.flex40,
+.no-gutter>.flex45,
+.no-gutter>.flex50,
+.no-gutter>.flex55,
+.no-gutter>.flex60,
+.no-gutter>.flex65,
+.no-gutter>.flex70,
+.no-gutter>.flex75,
+.no-gutter>.flex80,
+.no-gutter>.flex85,
+.no-gutter>.flex90,
+.no-gutter>.flex95,
+.no-gutter>.flex100 {
+    padding-left: 0;
+    padding-right: 0;
+}
+
+/* 정렬 배율 */
+.flex5 {
+    flex: 0 0 5%
+}
+
+.flex10 {
+    flex: 0 0 10%
+}
+
+.flex15 {
+    flex: 0 0 15%
+}
+
+.flex20 {
+    flex: 0 0 20%
+}
+
+.flex25 {
+    flex: 0 0 25%
+}
+
+.flex30 {
+    flex: 0 0 30%
+}
+
+.flex35 {
+    flex: 0 0 35%
+}
+
+.flex40 {
+    flex: 0 0 40%
+}
+
+.flex45 {
+    flex: 0 0 45%
+}
+
+.flex50 {
+    flex: 0 0 50%
+}
+
+.flex55 {
+    flex: 0 0 55%
+}
+
+.flex60 {
+    flex: 0 0 60%
+}
+
+.flex65 {
+    flex: 0 0 65%
+}
+
+.flex70 {
+    flex: 0 0 70%
+}
+
+.flex75 {
+    flex: 0 0 75%
+}
+
+.flex80 {
+    flex: 0 0 80%
+}
+
+.flex85 {
+    flex: 0 0 85%
+}
+
+
+.flex90 {
+    flex: 0 0 90%
+}
+
+.flex95 {
+    flex: 0 0 95%
+}
+
+.flex100 {
+    flex: 0 0 100%;
+}
+
+/* 너비 */
+.w10 {
+    width: 10%;
+}
+
+.w20 {
+    width: 20%;
+}
+
+.w30 {
+    width: 30%;
+}
+
+.w40 {
+    width: 40%;
+}
+
+.w50 {
+    width: 50%;
+}
+
+.w60 {
+    width: 60%;
+}
+
+.w70 {
+    width: 70%;
+}
+
+.w80 {
+    width: 80%;
+}
+
+.w90 {
+    width: 90%;
+}
+
+.w100 {
+    width: 100%;
+}
+
+
+
+/* 마진 */
+.ml0 {
+    margin-left: 0rem;
+}
+
+.ml5 {
+    margin-left: 0.5rem;
+}
+
+.ml10 {
+    margin-left: 1rem;
+}
+
+.ml20 {
+    margin-left: 2rem;
+}
+.ml25 {
+    margin-left: 2.5rem;
+}
+.ml30 {
+    margin-left: 3rem;
+}
+
+.ml40 {
+    margin-left: 4rem;
+}
+
+.ml50 {
+    margin-left: 5rem;
+}
+
+.ml60 {
+    margin-left: 6rem;
+}
+
+.ml70 {
+    margin-left: 7rem;
+}
+
+.ml80 {
+    margin-left: 8rem;
+}
+
+.ml90 {
+    margin-left: 9rem;
+}
+
+.ml100 {
+    margin-left: 10rem;
+}
+
+.mr0 {
+    margin-right: 0rem;
+}
+
+.mr5 {
+    margin-right: 0.5rem;
+}
+
+.mr10 {
+    margin-right: 1rem;
+}
+.mr15{
+    margin-right: 15px;
+}
+.mr20 {
+    margin-right: 2rem;
+}
+
+.mr30 {
+    margin-right: 3rem;
+}
+
+.mr40 {
+    margin-right: 4rem;
+}
+
+.mr50 {
+    margin-right: 5rem;
+}
+
+.mr60 {
+    margin-right: 6rem;
+}
+
+.mr70 {
+    margin-right: 7rem;
+}
+
+.mr80 {
+    margin-right: 8rem;
+}
+
+.mr90 {
+    margin-right: 9rem;
+}
+
+.mr100 {
+    margin-right: 10rem;
+}
+
+.mt0 {
+    margin-top: 0rem;
+}
+
+.mt5 {
+    margin-top: 0.5rem;
+}
+
+.mt10 {
+    margin-top: 1rem;
+}
+.mt15{margin-top: 15px;}
+.mt20 {
+    margin-top: 2rem;
+}
+.mt25 {
+    margin-top: 2.5rem;
+}
+
+.mt30 {
+    margin-top: 3rem;
+}
+
+.mt40 {
+    margin-top: 4rem;
+}
+
+.mt50 {
+    margin-top: 5rem;
+}
+
+.mt60 {
+    margin-top: 6rem;
+}
+
+.mt70 {
+    margin-top: 7rem;
+}
+
+.mt80 {
+    margin-top: 8rem;
+}
+
+.mt90 {
+    margin-top: 9rem;
+}
+
+.mt100 {
+    margin-top: 10rem;
+}
+
+.mb0 {
+    margin-bottom: 0rem;
+}
+
+.mb5 {
+    margin-bottom: 0.5rem;
+}
+
+.mb10 {
+    margin-bottom: 1rem;
+}
+.mb15{margin-bottom: 15px;}
+.mb20 {
+    margin-bottom: 2rem;
+}
+.mb25{margin-bottom: 25px;}
+.mb30 {
+    margin-bottom: 3rem;
+}
+
+.mb40 {
+    margin-bottom: 4rem;
+}
+
+.mb50 {
+    margin-bottom: 5rem;
+}
+
+.mb60 {
+    margin-bottom: 6rem;
+}
+.mb65{
+    margin-bottom: 65px;
+}
+.mb70 {
+    margin-bottom: 7rem;
+}
+
+.mb80 {
+    margin-bottom: 8rem;
+}
+
+.mb90 {
+    margin-bottom: 9rem;
+}
+
+.mb100 {
+    margin-bottom: 10rem;
+}
+
+/* 패딩 */
+.pd0 {
+    padding: 0;
+}
+
+.pd5 {
+    padding: 0.5rem;
+}
+
+.pd10 {
+    padding: 1rem;
+}
+
+.pd20 {
+    padding: 2rem;
+}
+
+.pd30 {
+    padding: 3rem;
+}
+
+.pd40 {
+    padding: 4rem;
+}
+
+.pd50 {
+    padding: 5rem;
+}
+
+.pd60 {
+    padding: 6rem;
+}
+
+.pd70 {
+    padding: 7rem;
+}
+
+.pd80 {
+    padding: 8rem;
+}
+
+.pd90 {
+    padding: 9rem;
+}
+
+.pd100 {
+    padding: 10rem;
+}
+
+/* 패딩 top */
+
+.pt0 {
+    padding-top: 0;
+}
+
+.pt5 {
+    padding-top: 0.5rem;
+}
+
+.pt10 {
+    padding-top: 1rem;
+}
+
+.pt20 {
+    padding-top: 2rem;
+}
+
+.pt30 {
+    padding-top: 3rem;
+}
+
+.pt40 {
+    padding-top: 4rem;
+}
+
+.pt50 {
+    padding-top: 5rem;
+}
+
+.pt60 {
+    padding-top: 6rem;
+}
+
+.pt70 {
+    padding-top: 7rem;
+}
+
+.pt80 {
+    padding-top: 8rem;
+}
+
+.pt90 {
+    padding-top: 9rem;
+}
+
+.pt100 {
+    padding-top: 10rem;
+}
+.pt120 {
+    padding-top: 12rem;
+}
+
+.pb0 {
+    padding-bottom: 0;
+}
+
+/* 패딩 bottom */
+.pb5 {
+    padding-bottom: 0.5rem;
+}
+
+.pb10 {
+    padding-bottom: 1rem;
+}
+.pb15 {
+    padding-bottom: 1.5rem;
+}
+
+.pb20 {
+    padding-bottom: 2rem;
+}
+
+.pb30 {
+    padding-bottom: 3rem;
+}
+
+.pb40 {
+    padding-bottom: 4rem;
+}
+
+.pb50 {
+    padding-bottom: 5rem;
+}
+
+.pb60 {
+    padding-bottom: 6rem;
+}
+
+.pb70 {
+    padding-bottom: 7rem;
+}
+
+.pb80 {
+    padding-bottom: 8rem;
+}
+
+.pb90 {
+    padding-bottom: 9rem;
+}
+
+.pb100 {
+    padding-bottom: 10rem;
+}
+.pb120 {
+    padding-bottom: 12rem;
+}
+
+/* 패딩 left */
+.pl0 {
+    padding-left: 0rem;
+}
+.pl5 {
+    padding-left: 0.5rem;
+}
+
+.pl10 {
+    padding-left: 1rem;
+}
+
+.pl20 {
+    padding-left: 2rem;
+}
+
+.pl30 {
+    padding-left: 3rem;
+}
+
+.pl40 {
+    padding-left: 4rem;
+}
+
+.pl50 {
+    padding-left: 5rem;
+}
+
+.pl60 {
+    padding-left: 6rem;
+}
+
+.pl70 {
+    padding-left: 7rem;
+}
+
+.pl80 {
+    padding-left: 8rem;
+}
+
+.pl90 {
+    padding-left: 9rem;
+}
+
+.pl100 {
+    padding-left: 10rem;
+}
+
+/* 패딩 right */
+.pr0 {
+    padding-right: 0rem;
+}
+.pr5 {
+    padding-right: 0.5rem;
+}
+
+.pr10 {
+    padding-right: 1rem;
+}
+
+.pr20 {
+    padding-right: 2rem;
+}
+
+.pr30 {
+    padding-right: 3rem;
+}
+
+.pr40 {
+    padding-right: 4rem;
+}
+
+.pr50 {
+    padding-right: 5rem;
+}
+
+.pr60 {
+    padding-right: 6rem;
+}
+
+.pr70 {
+    padding-right: 7rem;
+}
+
+.pr80 {
+    padding-right: 8rem;
+}
+
+.pr90 {
+    padding-right: 9rem;
+}
+
+.pr100 {
+    padding-right: 10rem;
+}
+
+/* btn */
+.small-btn {
+    width: 120px;
+    padding: 5px 10px;
+    border-radius: 5px;
+}
+
+.set-btn {
+    width: 50px;
+    padding: 5px 10px;
+    border-radius: 5px;
+}
+
+.large-btn {
+    width: 100%;
+    padding: 5px 15px;
+    border-radius: 5px;
+}
+
+.icon-btn {
+    padding: 5px;
+    border-radius: 50%;
+
+}
+
+.custom-toggle {
+    position: absolute;
+    bottom: 0;
+    background-color: var(--color-skyBlue);
+    margin-left: 0;
+    border: 1px solid #eee;
+    border-left: 0;
+}
+
+.custom-toggle::after {
+    content: "";
+    position: absolute;
+    left: 0;
+    width: 5px;
+    height: 5px;
+    background-color: var(--color-skyBlue);
+    bottom: 0;
+}
+
+.logout-btn {
+    padding: 5px 10px;
+    color: #aaa;
+    position: relative;
+}
+
+.logout-btn::before {
+    content: "";
+    width: 1px;
+    height: 10px;
+    position: absolute;
+    top: 50%;
+    left: 0;
+    transform: translateY(-50%);
+    background-color: #aaa;
+}
+
+.close-btn {
+    color: #d6def6;
+}
+
+.style-btn {
+    border: 1px solid #eee;
+    border-radius: 3px;
+    background-color: var(--color-white);
+}
+
+.style-btn>svg {
+    color: #aaa;
+}
+
+.btn-active {
+    border: 1px solid var(--color-blue);
+}
+
+.btn-active>svg {
+    color: var(--color-blue);
+}
+
+.attribute-btn {
+    position: relative;
+}
+
+.blue-btn,
+.blue-border-btn:hover {
+    background-color: var(--color-blue);
+    color: var(--color-white);
+    transition: all 0.3s ease-in-out;
+}
+
+.red-btn,
+.red-border-btn:hover {
+    background-color: var(--color-red);
+    color: var(--color-white);
+    transition: all 0.3s ease-in-out;
+}
+
+.green-btn,
+.green-border-btn:hover {
+    background-color: var(--color-green);
+    color: var(--color-white);
+    transition: all 0.3s ease-in-out;
+}
+
+.orange-btn,
+.orange-border-btn:hover {
+    background-color: var(--color-orange);
+    color: var(--color-white);
+    transition: all 0.3s ease-in-out;
+}
+
+.darkg-btn,
+.darkg-border-btn:hover {
+    background-color: var(--color-darkG);
+    color: var(--color-white);
+    transition: all 0.3s ease-in-out;
+}
+
+.gray-btn,
+.gray-border-btn:hover {
+    background-color: #eee;
+    color: #333;
+    transition: all 0.3s ease-in-out;
+}
+
+
+.blue-border-btn {
+    border: 1px solid var(--color-blue);
+    color: var(--color-blue);
+    background-color: var(--color-white);
+}
+
+.red-border-btn {
+    border: 1px solid var(--color-red);
+    color: var(--color-red);
+    background-color: var(--color-white);
+}
+
+.green-border-btn {
+    border: 1px solid var(--color-green);
+    color: var(--color-green);
+    background-color: var(--color-white);
+}
+
+.orange-border-btn {
+    border: 1px solid var(--color-orange);
+    color: var(--color-orange);
+    background-color: #fff;
+}
+
+.darkg-border-btn {
+    border: 1px solid #434343;
+    color: #434343;
+    background-color: var(--color-white);
+}
+
+.gray-border-btn {
+    border: 1px solid #aaa;
+    color: #aaa;
+    background-color: var(--color-white);
+}
+
+.tp-btn {
+    background-color: transparent;
+    width: 15px;
+    height: 15px;
+    margin-left: 10px;
+}
+
+button:disabled {
+    background-color: #eee;
+    color: #333;
+}
+
+/* .del-icon-btn{
+    width: 25px;
+    height: 25px;
+    padding: 5px;
+    background-color: var(--color-red);
+    color: var(--color-white);
+    border-radius: 50%;
+}
+
+.set-icon-btn{
+    width: 25px;
+    height: 25px;
+    padding: 5px;
+    background-color: var(--color-darkG);
+    color: var(--color-white);
+    border-radius: 50%;
+} */
+
+
+
+/* text 정렬 */
+.text-lf {
+    text-align: left;
+}
+
+.text-ct {
+    text-align: center;
+}
+
+.text-rg {
+    text-align: right;
+}
+
+/* text color */
+.orange {
+    color: var(--color-orange);
+}
+
+.green {
+    color: var(--color-green);
+}
+
+.blue {
+    color: var(--color-blue);
+}
+
+.red {
+    color: var(--color-red);
+}
+
+.cursor {
+    cursor: pointer;
+}
+
+
+/* checkbox settings �� */
+input[type="radio"] {
+    display: inline-block;
+    width: 18px !important;
+    height: 18px;
+    margin: -2px 10px 0 0;
+    vertical-align: middle;
+    cursor: pointer;
+    -moz-border-radius: 50%;
+    border-radius: 50%;
+    border: 3px solid #ffffff;
+    accent-color: #00A8BA;
+}
+  /* Global CSS */
+  fieldset {
+    display: flex;
+    justify-content: center;
+    border: none;
+    margin: 0;
+    padding: 40px 20px;
+  }
+  
+  *,
+  *::before,
+  *::after {
+    box-sizing: border-box;
+  }
+.ui-checkbox {
+    --primary-color: #00A8BA;
+    --secondary-color: #fff;
+    --primary-hover-color: #00A8BA;
+    /* checkbox */
+    --checkbox-diameter: 22px;
+    --checkbox-border-radius: 3px;
+    --checkbox-border-color: #d9d9d9;
+    --checkbox-border-width: 1px;
+    --checkbox-border-style: solid;
+    /* checkmark */
+    --checkmark-size: 1.2;
+
+  }
+  
+  .ui-checkbox, 
+  .ui-checkbox *, 
+  .ui-checkbox *::before, 
+  .ui-checkbox *::after {
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+  }
+  
+  .ui-checkbox {
+    -webkit-appearance: none;
+    -moz-appearance: none;
+    appearance: none;
+    width: var(--checkbox-diameter);
+    height: var(--checkbox-diameter);
+    border-radius: var(--checkbox-border-radius);
+    background: var(--secondary-color);
+    border: var(--checkbox-border-width) var(--checkbox-border-style) var(--checkbox-border-color);
+    -webkit-transition: all 0.3s;
+    -o-transition: all 0.3s;
+    transition: all 0.3s;
+    cursor: pointer;
+    position: relative;
+  }
+  
+  .ui-checkbox::after {
+    content: "";
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    -webkit-box-shadow: 0 0 0 calc(var(--checkbox-diameter) / 2.5) var(--primary-color);
+    box-shadow: 0 0 0 calc(var(--checkbox-diameter) / 2.5) var(--primary-color);
+    border-radius: inherit;
+    opacity: 0;
+    -webkit-transition: all 0.5s cubic-bezier(0.12, 0.4, 0.29, 1.46);
+    -o-transition: all 0.5s cubic-bezier(0.12, 0.4, 0.29, 1.46);
+    transition: all 0.5s cubic-bezier(0.12, 0.4, 0.29, 1.46);
+  }
+  
+  .ui-checkbox::before {
+    top: 40%;
+    left: 50%;
+    content: "";
+    position: absolute;
+    width: 4px;
+    height: 7px;
+    border-right: 2px solid var(--secondary-color);
+    border-bottom: 2px solid var(--secondary-color);
+    -webkit-transform: translate(-50%, -50%) rotate(45deg) scale(0);
+    -ms-transform: translate(-50%, -50%) rotate(45deg) scale(0);
+    transform: translate(-50%, -50%) rotate(45deg) scale(0);
+    opacity: 0;
+    -webkit-transition: all 0.1s cubic-bezier(0.71, -0.46, 0.88, 0.6),opacity 0.1s;
+    -o-transition: all 0.1s cubic-bezier(0.71, -0.46, 0.88, 0.6),opacity 0.1s;
+    transition: all 0.1s cubic-bezier(0.71, -0.46, 0.88, 0.6),opacity 0.1s;
+  }
+  
+  /* actions */
+  
+  .ui-checkbox:hover {
+    border-color: var(--primary-color);
+  }
+  
+  .ui-checkbox:checked {
+    background: var(--primary-color);
+    border-color: transparent;
+  }
+  
+  .ui-checkbox:checked::before {
+    opacity: 1;
+    -webkit-transform: translate(-50%, -50%) rotate(45deg) scale(var(--checkmark-size));
+    -ms-transform: translate(-50%, -50%) rotate(45deg) scale(var(--checkmark-size));
+    transform: translate(-50%, -50%) rotate(45deg) scale(var(--checkmark-size));
+    -webkit-transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s;
+    -o-transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s;
+    transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s;
+  }
+  
+  .ui-checkbox:active:not(:checked)::after {
+    -webkit-transition: none;
+    -o-transition: none;
+    -webkit-box-shadow: none;
+    box-shadow: none;
+    transition: none;
+    opacity: 1;
+  }
+
+ (파일 끝에 줄바꿈 문자 없음)
 
client/resources/css/grid.css (added)
+++ client/resources/css/grid.css
@@ -0,0 +1,331 @@
+@charset "utf-8";
+
+.container {
+    width: 100%;
+    padding-right: 15px;
+    padding-left: 15px;
+    margin-right: auto;
+    margin-left: auto;
+    
+}
+
+/* 
+@media (min-width: 576px) {
+    .container {
+        max-width: 540px;
+    }
+}
+
+@media (min-width: 768px) {
+    .container {
+        max-width: 720px;
+    }
+}
+
+@media (min-width: 992px) {
+    .container {
+        max-width: 960px;
+    }
+}
+
+@media (min-width: 1480px) {
+    .container {
+        max-width: 1140px;
+    }
+} */
+
+.flex-column {
+    display: flex;
+    flex-direction: column;
+}
+
+.no-space {
+    margin-right: 0;
+    margin-left: 0;
+    padding-right: 0 !important;
+    padding-left: 0 !important;
+}
+
+
+.no-space>.gd,
+.no-space>[class*="gd-"] {
+    padding-right: 0;
+    padding-left: 0;
+}
+
+.gd-1,
+.gd-2,
+.gd-3,
+.gd-4,
+.gd-5,
+.gd-6,
+.gd-7,
+.gd-8,
+.gd-9,
+.gd-10,
+.gd-11,
+.gd-12,
+.gd,
+.gd-auto,
+.gd-sm-1,
+.gd-sm-2,
+.gd-sm-3,
+.gd-sm-4,
+.gd-sm-5,
+.gd-sm-6,
+.gd-sm-7,
+.gd-sm-8,
+.gd-sm-9,
+.gd-sm-10,
+.gd-sm-11,
+.gd-sm-12,
+.gd-sm,
+.gd-sm-auto,
+.gd-md-1,
+.gd-md-2,
+.gd-md-3,
+.gd-md-4,
+.gd-md-5,
+.gd-md-6,
+.gd-md-7,
+.gd-md-8,
+.gd-md-9,
+.gd-md-10,
+.gd-md-11,
+.gd-md-12,
+.gd-md,
+.gd-md-auto,
+.gd-lg-1,
+.gd-lg-2,
+.gd-lg-3,
+.gd-lg-4,
+.gd-lg-5,
+.gd-lg-6,
+.gd-lg-7,
+.gd-lg-8,
+.gd-lg-9,
+.gd-lg-10,
+.gd-lg-11,
+.gd-lg-12,
+.gd-lg,
+.gd-lg-auto,
+.gd-xl-1,
+.gd-xl-2,
+.gd-xl-3,
+.gd-xl-4,
+.gd-xl-5,
+.gd-xl-6,
+.gd-xl-7,
+.gd-xl-8,
+.gd-xl-9,
+.gd-xl-10,
+.gd-xl-11,
+.gd-xl-12,
+.gd-xl,
+.gd-xl-auto {
+    position: relative;
+    width: 100%;
+    min-height: 1px;
+}
+
+
+.gd {
+    -ms-flex-preferred-size: 0;
+    flex-basis: 0;
+    -ms-flex-positive: 1;
+    flex-grow: 1;
+    max-width: 100%;
+}
+
+.gd-auto {
+    -ms-flex: 0 0 auto;
+    flex: 0 0 auto;
+    width: auto;
+    max-width: none;
+}
+
+.gd-1 {
+    -ms-flex: 0 0 8.333333%;
+    flex: 0 0 8.333333%;
+    max-width: 8.333333%;
+}
+
+.gd-2 {
+    -ms-flex: 0 0 16.666667%;
+    flex: 0 0 16.666667%;
+    max-width: 16.666667%;
+}
+
+.gd-3 {
+    -ms-flex: 0 0 25%;
+    flex: 0 0 25%;
+    max-width: 25%;
+}
+
+.gd-4 {
+    -ms-flex: 0 0 33.333333%;
+    flex: 0 0 33.333333%;
+    max-width: 33.333333%;
+}
+
+.gd-5 {
+    -ms-flex: 0 0 41.666667%;
+    flex: 0 0 41.666667%;
+    max-width: 41.666667%;
+}
+
+.gd-6 {
+    -ms-flex: 0 0 50%;
+    flex: 0 0 50%;
+    max-width: 50%;
+}
+
+.gd-7 {
+    -ms-flex: 0 0 58.333333%;
+    flex: 0 0 58.333333%;
+    max-width: 58.333333%;
+}
+
+.gd-8 {
+    -ms-flex: 0 0 66.666667%;
+    flex: 0 0 66.666667%;
+    max-width: 66.666667%;
+}
+
+.gd-9 {
+    -ms-flex: 0 0 75%;
+    flex: 0 0 75%;
+    max-width: 75%;
+}
+
+.gd-10 {
+    -ms-flex: 0 0 83.333333%;
+    flex: 0 0 83.333333%;
+    max-width: 83.333333%;
+}
+
+.gd-11 {
+    -ms-flex: 0 0 91.666667%;
+    flex: 0 0 91.666667%;
+    max-width: 91.666667%;
+}
+
+.gd-12 {
+    -ms-flex: 0 0 100%;
+    flex: 0 0 100%;
+    max-width: 100%;
+}
+.gd-col2{    display: grid;
+    grid-template-columns: 1fr 1fr;
+    }
+
+
+.justify-start {
+    justify-content: flex-start;
+}
+
+.justify-center {
+    justify-content: center;
+}
+
+.justify-end {
+    justify-content: flex-end;
+}
+
+.justify-between {
+    justify-content: space-between;
+}
+
+.justify-around {
+    justify-content: space-around;
+}
+
+.align-start {
+    align-items: flex-start;
+}
+
+
+.align-center {
+    align-items: center;
+}
+
+.align-end {
+    align-items: flex-end;
+}
+
+.flex-auto {
+    flex: 0 0 auto;
+}
+
+.flex1 {
+    flex: 1;
+}
+
+.flex2 {
+    flex: 2;
+}
+
+.flex3 {
+    flex: 3;
+}
+
+.flex4 {
+    flex: 4;
+}
+
+.flex5 {
+    flex: 5;
+}
+
+.flex6 {
+    flex: 6;
+}
+
+.flex7 {
+    flex: 7;
+}
+
+.flex8 {
+    flex: 8;
+}
+
+
+.gap1 {
+    gap: 1%;
+}
+
+.gap2 {
+    gap: 2%;
+}
+
+.gap3 {
+    gap: 3%;
+}
+
+.gap4 {
+    gap: 4%;
+}
+
+.gap5 {
+    gap: 5%;
+}
+
+.gap6 {
+    gap: 6%;
+}
+
+.gap7 {
+    gap: 7%;
+}
+
+.gap8 {
+    gap: 8%;
+}
+
+.gap9 {
+    gap: 9%;
+}
+
+.gap10 {
+    gap: 10%;
+}(파일 끝에 줄바꿈 문자 없음)
 
client/resources/css/reset.css (added)
+++ client/resources/css/reset.css
@@ -0,0 +1,76 @@
+@charset "utf-8";
+@font-face {
+	font-family: 'Pretendard';
+	font-weight: 100;
+	font-display: swap;
+	src: local('Pretendard Thin'), url(../font/Pretendard-Thin.woff2) format('woff2'), url(../font/Pretendard-Thin.woff) format('woff');
+}
+@font-face {
+	font-family: 'Pretendard-Bold';
+	font-weight: 100;
+	font-display: swap;
+	src: local('Pretendard Bold'), url(../font/Pretendard-Bold.woff2) format('woff2'), url(../font/Pretendard-Bold.woff2) format('woff');
+}
+@font-face {
+	font-family: 'Pretendard-Regular';
+	font-weight: 100;
+	font-display: swap;
+	src: local('Pretendard Regular'), url(../font/Pretendard-Regular.woff2) format('woff2'), url(../font/Pretendard-Regular.woff2) format('woff');
+}
+
+@font-face {
+	font-family: 'ONEMobilePOP';
+    src: url('../font/ONEMobilePOP.ttf') format('truetype');
+}
+@font-face {
+	font-family: 'ONEMobileOTF-Regular';
+    src: url('../font/ONEMobileOTF-Regular.otf') format('opentype');
+}
+@font-face {
+	font-family: 'ONEMobileOTF-Light';
+    src: url('../font/ONEMobileOTF-Light.otf') format('opentype');
+}
+@font-face {
+	font-family: 'ONEMobileOTF-Bold';
+    src: url('../font/ONEMobileOTF-Bold.otf') format('opentype');
+}
+@font-face {
+	font-family: 'ONEMobilePOPOTF';
+    src: url('../font/ONEMobilePOPOTF.otf') format('opentype');
+}
+
+
+* {
+    padding: 0;
+    margin: 0;
+    box-sizing: border-box;
+}
+
+
+html,
+body,
+#root {
+    font-size: 10px;
+    color: #2E2F30;
+    font-family: 'ONEMobileOTF-Regular';
+}
+html,
+body{height: 100%}
+body{position:relative;text-align: left; overflow-x: hidden; width: 1920px;}
+::-webkit-scrollbar {width: 10px; }
+::-webkit-scrollbar-track {border-radius: 5px;background-color: #EAEDF4;}
+::-webkit-scrollbar-thumb {	border-radius: 5px; background-color: #FFBA08;}
+#root{padding: 15px 60px 90px 60px; 
+    height: 920px; 
+    background-color: #eaedf4;}
+input, select, span,p, label {
+    font-size: 16px;
+}
+input::placeholder{color: #8C8E92;}
+
+button{
+    border: none;
+    background-color: transparent;
+    cursor: pointer;
+}
+textarea{resize: none; border: 0; outline: 0; font-size: 20px; font-family: 'ONEMobileOTF-Regular';}(파일 끝에 줄바꿈 문자 없음)
 
client/resources/css/style.css (added)
+++ client/resources/css/style.css
@@ -0,0 +1,445 @@
+/* 로그인페이지 */
+.login-container {
+  padding: 40px 60px;
+}
+
+.login h2 {
+  font-size: 30px;
+  color: #fff;
+  font-family: 'ONEMobilePOPOTF';
+}
+
+.login-bg {
+  position: absolute;
+  z-index: -10;
+  left: 0;
+  top: 0;
+}
+
+.login-box {
+  width: 712px;
+  /* height: 560px; */
+  margin: 0 auto;
+}
+
+.login-form {
+  background-color: #fff;
+  padding: 60px 45px;
+  border-radius: 20px;
+}
+
+.login-form p {
+  font-family: 'ONEMobileOTF-Bold';
+  font-size: 24px;
+}
+
+.login-form input {
+  border: 3px solid #FFD56B;
+  border-radius: 10px;
+  padding: 22px 19px;
+  width: 100%;
+  font-size: 24px;
+}
+
+.login-btn {
+  position: relative;
+}
+
+.login-btn p {
+  position: absolute;
+  top: 42%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  font-family: 'ONEMobilePOPOTF';
+  font-size: 36px;
+}
+
+
+/* 레이아웃 */
+.side {
+  width: 42rem;
+}
+
+.main-wrap {
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+  padding: 65px 15px 70px 60px;
+}
+
+.main-wrap {
+  width: 134rem;
+  height: 70rem;
+  background-color: #fff;
+  border-radius: 10px;
+  position: absolute;
+  right: 60px;
+  top: 179px;
+  z-index: 1;
+}
+
+.header img {
+  margin-left: 20px;
+  object-fit: contain;
+}
+
+/* 사이드 */
+.side button p {
+  font-size: 24px;
+}
+
+.side .profile {
+  height: 24rem;
+  background-color: #fff;
+  border-radius: 10px;
+  padding: 25px 48px;
+  font-size: 16px;
+  font-family: 'ONEMobileOTF-Regular';
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+}
+
+.side .profile .name {
+  font-family: 'ONEMobilePOPOTF';
+  font-size: 24px;
+}
+
+.side .profile img {
+  object-fit: contain;
+}
+
+.side .profile span {
+  font-family: 'Pretendard';
+  font-weight: bold;
+  font-size: 14px;
+}
+
+.side .profile span.brown {
+  color: #331600;
+}
+
+.side .ask {
+  height: 32rem;
+  background-color: #fff;
+  border-radius: 10px;
+  padding: 25px 48px;
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+}
+
+.side .ask .memo {
+  background-image: url('../img/img10_s.png');
+  background-repeat: no-repeat;
+  width: 324px;
+  height: 174px;
+  position: relative;
+  padding: 25px 30px;
+}
+
+.side .ask .memo textarea {
+  background-color: #ddf0ff;
+  width: -webkit-fill-available;
+  height: 117px;
+}
+
+.side .ask button {
+  padding: 10px 30px;
+  border: #FFD56B 3px solid;
+  border-radius: 30px;
+  font-family: 'ONEMobilePOPOTF';
+  font-size: 18px;
+  color: #331600;
+}
+
+
+/* 메뉴 */
+.menu {
+  margin-top: 63px;
+  width: 1324px;
+  position: absolute;
+  left: 579px;
+}
+
+.menu a:first-child button {
+  background-image: url('../../resources/img/btn04_s.png');
+  width: 186px;
+}
+
+.menu a:nth-child(2) button {
+  background-image: url('../../resources/img/btn06_s.png');
+  width: 225px;
+}
+
+.menu a:last-child button {
+  background-image: url('../../resources/img/btn05_s.png');
+  width: 207px;
+}
+
+.menu a:first-child button.active {
+  background-image: url('../../resources/img/btn05_1_s.png');
+  width: 252px;
+  /* 마이페이지 활성화 이미지 */
+}
+
+.menu a:nth-child(2) button.active {
+  background-image: url('../../resources/img/btn06_1_s.png');
+  width: 297px;
+  /* 대시보드 활성화 이미지 */
+}
+
+.menu a:last-child button.active {
+  background-image: url('../../resources/img/btn04_1_s.png');
+  width: 259px;
+  /* 학습일정계획 활성화 이미지 */
+}
+
+.menu button p {
+  font-size: 32px;
+  color: #fff;
+  height: 50px;
+}
+
+.menu button {
+  background-repeat: no-repeat;
+  height: 72px;
+  text-align: -webkit-center;
+}
+
+.menu button.active {
+  height: 118px;
+  margin-top: -18px;
+}
+
+.menu button p.active {
+  display: none;
+  /* 원하는 색상으로 변경 */
+}
+
+
+/* 대시보드 */
+.main {
+  max-height: 600px;
+  overflow: auto;
+}
+
+.main .race-wrap {
+  background-image: url('../img/img20_1_s.png');
+  background-repeat: no-repeat;
+  width: 1242px;
+  height: 599px;
+  position: relative;
+}
+
+.complete-wrap {
+  width: 1244px;
+  height: 617px;
+}
+
+button p {
+  font-family: 'ONEMobilePOPOTF';
+  width: max-content;
+}
+
+.race-wrap .title-box {
+  position: absolute;
+  top: 68px;
+  left: 120px;
+  text-align: center;
+}
+
+.race-wrap .title-box .title {
+  font-size: 32px;
+  font-family: 'ONEMobilePOPOTF';
+}
+
+.race-wrap .title-box .subtitle {
+  font-size: 16px;
+  background-color: #441E03;
+  color: #fff;
+  padding: 5px 15px;
+  width: fit-content;
+  border-radius: 20px;
+  display: inline-block;
+  font-family: 'ONEMobileOTF-Bold';
+}
+
+.race-box {
+  width: 1063px;
+  height: 516px;
+  position: absolute;
+  left: 114px;
+  top: 60px;
+}
+
+.race-box .rcon,
+.race-box .lcon {
+  gap: 42px;
+  width: 1063px;
+}
+
+.rabbit {
+  position: absolute;
+  top: -45px;
+  left: 393px;
+}
+
+.rabbit img {
+  transform: scaleX(-1);
+}
+
+.race-btn {
+  position: relative;
+  cursor: pointer;
+}
+
+.race-btn p {
+  position: absolute;
+  text-align: center;
+  width: 76px;
+  top: 16px;
+  right: 9px;
+  font-family: 'ONEMobilePOPOTF';
+  font-size: 28px;
+  color: #3A241D;
+}
+
+.race-btn p.long {
+  width: fit-content;
+}
+
+.complete-wrap h2 {
+  font-size: 32px;
+  color: #331600;
+  font-family: 'ONEMobilePOPOTF';
+  font-weight: 100;
+}
+
+
+/* 챕터 */
+.content-wrap {
+  width: 1808px;
+  
+}
+
+.content-wrap::before {
+  background-image: url('../img/logo2.png');
+  background-size: 155px 58px;
+  width: 155px;
+  height: 58px;
+  content: "";
+  display: block;
+  position: absolute;
+  top: 17px;
+}
+.content-wrap > .title-box{margin-left: 75px;}
+.content p.title-bg {
+  width: max-content;
+  height: max-content;
+  background: linear-gradient(to right, #eaedf4, #fff);
+  padding: 20px 60px;
+  margin-bottom: 30px;
+}
+.content {
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+  width: 1670px;
+  height: 710px;
+  background-color: #fff;
+  border-radius: 20px;
+}
+
+/* step1 */
+.videoCon {
+  position: relative;
+  text-align: center;
+  width: 100%;
+  display: inline-block;
+}
+
+
+.videoCon .videoStart {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translateY(-50%) translateX(-50%);
+}
+.look-text{position: absolute; right: 60px; bottom: 0;}
+.look-text button{position: relative;}
+.look-text p{    position: absolute;
+  top: 45%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  font-size: 28px;
+  
+ }
+
+/* step1-1 */
+.imgGroup, .textareaGroup{width: 100%; text-align: center;}
+.textareaGroup{margin-top: 40px;}
+.textareaGroup textarea{width: 1460px; height: 200px; background-color: #eff2f7; border-radius: 10px; padding: 30px 40px; 
+  line-height: 30px; font-size: 24px; font-family: 'Pretendard-Regular';}
+  /* step1-1-팝업 */
+  .popup {
+    /* display: none; */
+    position: absolute;
+    width: 355px;
+    height: 327px;
+    background-color: white;
+    border: 3px solid #FFBD14;
+    border-radius: 10px;
+    padding: 20px 40px;    
+ }
+
+ .popup h3{font-size: 42px;}
+ .popup .yellow-box{width: 33px; height: 33px; color: #FFBA08; background-color: #FFF3D7; padding: 7px;
+  border-radius: 5px; margin-right: 10px;}
+
+
+   /* step1-2 */
+   .readGroup{
+
+   }
+   .readGroup .icon{text-align: center;}
+   .readGroup p.read{
+    width: max-content;
+    border-radius: 10px;
+    font-size: 24px; font-family: 'Pretendard-Regular'; background-color: #EAEDF4; padding: 10px 20px;}
+
+
+.next-btn, .pre-btn{cursor: pointer;}
+
+
+
+input.borderx {
+  border: none;
+}
+
+.underline {
+  text-decoration: underline;
+}
+
+hr {
+  color: #C6C6C6;
+  margin: 10px 0 20px 0;
+}
+
+.title2 {
+  font-size: 20px;
+  font-weight: bold;
+}
+
+.title1 {
+  font-size: 24px;
+  font-weight: bold;
+}
+
+.title-box .title {
+  font-size: 32px;
+  font-family: 'ONEMobilePOPOTF';
+}
+
+.title-box .subtitle {
+  font-size: 16px;
+  background-color: #441E03;
+  color: #fff;
+  padding: 5px 15px;
+  width: fit-content;
+  border-radius: 20px;
+  display: inline-block;
+  font-family: 'ONEMobileOTF-Bold';
+}(파일 끝에 줄바꿈 문자 없음)
 
client/resources/font/ONEMobileOTF-Bold.otf (Binary) (added)
+++ client/resources/font/ONEMobileOTF-Bold.otf
Binary file is not shown
 
client/resources/font/ONEMobileOTF-Light.otf (Binary) (added)
+++ client/resources/font/ONEMobileOTF-Light.otf
Binary file is not shown
 
client/resources/font/ONEMobileOTF-Regular.otf (Binary) (added)
+++ client/resources/font/ONEMobileOTF-Regular.otf
Binary file is not shown
 
client/resources/font/ONEMobilePOP.ttf (Binary) (added)
+++ client/resources/font/ONEMobilePOP.ttf
Binary file is not shown
 
client/resources/font/ONEMobilePOPOTF.otf (Binary) (added)
+++ client/resources/font/ONEMobilePOPOTF.otf
Binary file is not shown
 
client/resources/font/Pretendard-Bold.woff2 (Binary) (added)
+++ client/resources/font/Pretendard-Bold.woff2
Binary file is not shown
 
client/resources/font/Pretendard-Light.woff2 (Binary) (added)
+++ client/resources/font/Pretendard-Light.woff2
Binary file is not shown
 
client/resources/font/Pretendard-Medium.woff2 (Binary) (added)
+++ client/resources/font/Pretendard-Medium.woff2
Binary file is not shown
 
client/resources/font/Pretendard-Regular.woff2 (Binary) (added)
+++ client/resources/font/Pretendard-Regular.woff2
Binary file is not shown
 
client/resources/font/Pretendard-Thin.woff2 (Binary) (added)
+++ client/resources/font/Pretendard-Thin.woff2
Binary file is not shown
 
client/resources/img/bg.png (Binary) (added)
+++ client/resources/img/bg.png
Binary file is not shown
 
client/resources/img/btn01.png (Binary) (added)
+++ client/resources/img/btn01.png
Binary file is not shown
 
client/resources/img/btn02.png (Binary) (added)
+++ client/resources/img/btn02.png
Binary file is not shown
 
client/resources/img/btn03.png (Binary) (added)
+++ client/resources/img/btn03.png
Binary file is not shown
 
client/resources/img/btn04_1_s.png (Binary) (added)
+++ client/resources/img/btn04_1_s.png
Binary file is not shown
 
client/resources/img/btn04_s.png (Binary) (added)
+++ client/resources/img/btn04_s.png
Binary file is not shown
 
client/resources/img/btn05_1_s.png (Binary) (added)
+++ client/resources/img/btn05_1_s.png
Binary file is not shown
 
client/resources/img/btn05_s.png (Binary) (added)
+++ client/resources/img/btn05_s.png
Binary file is not shown
 
client/resources/img/btn06_1_s.png (Binary) (added)
+++ client/resources/img/btn06_1_s.png
Binary file is not shown
 
client/resources/img/btn06_s.png (Binary) (added)
+++ client/resources/img/btn06_s.png
Binary file is not shown
 
client/resources/img/btn07_s.png (Binary) (added)
+++ client/resources/img/btn07_s.png
Binary file is not shown
 
client/resources/img/btn08_s.png (Binary) (added)
+++ client/resources/img/btn08_s.png
Binary file is not shown
 
client/resources/img/btn09_s.png (Binary) (added)
+++ client/resources/img/btn09_s.png
Binary file is not shown
 
client/resources/img/btn_.png (Binary) (added)
+++ client/resources/img/btn_.png
Binary file is not shown
 
client/resources/img/button.png (Binary) (added)
+++ client/resources/img/button.png
Binary file is not shown
 
client/resources/img/icon1.png (Binary) (added)
+++ client/resources/img/icon1.png
Binary file is not shown
 
client/resources/img/icon2.png (Binary) (added)
+++ client/resources/img/icon2.png
Binary file is not shown
 
client/resources/img/icon2_1.png (Binary) (added)
+++ client/resources/img/icon2_1.png
Binary file is not shown
 
client/resources/img/icon3.png (Binary) (added)
+++ client/resources/img/icon3.png
Binary file is not shown
 
client/resources/img/icon4.png (Binary) (added)
+++ client/resources/img/icon4.png
Binary file is not shown
 
client/resources/img/img01.png (Binary) (added)
+++ client/resources/img/img01.png
Binary file is not shown
 
client/resources/img/img02.png (Binary) (added)
+++ client/resources/img/img02.png
Binary file is not shown
 
client/resources/img/img03.png (Binary) (added)
+++ client/resources/img/img03.png
Binary file is not shown
 
client/resources/img/img04.png (Binary) (added)
+++ client/resources/img/img04.png
Binary file is not shown
 
client/resources/img/img05.png (Binary) (added)
+++ client/resources/img/img05.png
Binary file is not shown
 
client/resources/img/img06.png (Binary) (added)
+++ client/resources/img/img06.png
Binary file is not shown
 
client/resources/img/img07.png (Binary) (added)
+++ client/resources/img/img07.png
Binary file is not shown
 
client/resources/img/img08.png (Binary) (added)
+++ client/resources/img/img08.png
Binary file is not shown
 
client/resources/img/img09_s.png (Binary) (added)
+++ client/resources/img/img09_s.png
Binary file is not shown
 
client/resources/img/img10_s.png (Binary) (added)
+++ client/resources/img/img10_s.png
Binary file is not shown
 
client/resources/img/img11_1_s.png (Binary) (added)
+++ client/resources/img/img11_1_s.png
Binary file is not shown
 
client/resources/img/img11_2_s.png (Binary) (added)
+++ client/resources/img/img11_2_s.png
Binary file is not shown
 
client/resources/img/img11_s.png (Binary) (added)
+++ client/resources/img/img11_s.png
Binary file is not shown
 
client/resources/img/img12_1_s.png (Binary) (added)
+++ client/resources/img/img12_1_s.png
Binary file is not shown
 
client/resources/img/img12_2_s.png (Binary) (added)
+++ client/resources/img/img12_2_s.png
Binary file is not shown
 
client/resources/img/img12_s.png (Binary) (added)
+++ client/resources/img/img12_s.png
Binary file is not shown
 
client/resources/img/img13_s.png (Binary) (added)
+++ client/resources/img/img13_s.png
Binary file is not shown
 
client/resources/img/img14_s.png (Binary) (added)
+++ client/resources/img/img14_s.png
Binary file is not shown
 
client/resources/img/img15_s.png (Binary) (added)
+++ client/resources/img/img15_s.png
Binary file is not shown
 
client/resources/img/img16_s.png (Binary) (added)
+++ client/resources/img/img16_s.png
Binary file is not shown
 
client/resources/img/img17_s.png (Binary) (added)
+++ client/resources/img/img17_s.png
Binary file is not shown
 
client/resources/img/img18_s.png (Binary) (added)
+++ client/resources/img/img18_s.png
Binary file is not shown
 
client/resources/img/img19_s.png (Binary) (added)
+++ client/resources/img/img19_s.png
Binary file is not shown
 
client/resources/img/img20_1_s.png (Binary) (added)
+++ client/resources/img/img20_1_s.png
Binary file is not shown
 
client/resources/img/img20_s.png (Binary) (added)
+++ client/resources/img/img20_s.png
Binary file is not shown
 
client/resources/img/img21_s.png (Binary) (added)
+++ client/resources/img/img21_s.png
Binary file is not shown
 
client/resources/img/img22_s.png (Binary) (added)
+++ client/resources/img/img22_s.png
Binary file is not shown
 
client/resources/img/img23_s.png (Binary) (added)
+++ client/resources/img/img23_s.png
Binary file is not shown
 
client/resources/img/img24_s.png (Binary) (added)
+++ client/resources/img/img24_s.png
Binary file is not shown
 
client/resources/img/img25_s.png (Binary) (added)
+++ client/resources/img/img25_s.png
Binary file is not shown
 
client/resources/img/img26_s.png (Binary) (added)
+++ client/resources/img/img26_s.png
Binary file is not shown
 
client/resources/img/img27_s.png (Binary) (added)
+++ client/resources/img/img27_s.png
Binary file is not shown
 
client/resources/img/img28_s.png (Binary) (added)
+++ client/resources/img/img28_s.png
Binary file is not shown
 
client/resources/img/img29_s.png (Binary) (added)
+++ client/resources/img/img29_s.png
Binary file is not shown
 
client/resources/img/img30_s.png (Binary) (added)
+++ client/resources/img/img30_s.png
Binary file is not shown
 
client/resources/img/img31_s.png (Binary) (added)
+++ client/resources/img/img31_s.png
Binary file is not shown
 
client/resources/img/img32_s.png (Binary) (added)
+++ client/resources/img/img32_s.png
Binary file is not shown
 
client/resources/img/img33_s.png (Binary) (added)
+++ client/resources/img/img33_s.png
Binary file is not shown
 
client/resources/img/img34_s.png (Binary) (added)
+++ client/resources/img/img34_s.png
Binary file is not shown
 
client/resources/img/img35_s.png (Binary) (added)
+++ client/resources/img/img35_s.png
Binary file is not shown
 
client/resources/img/img36_s.png (Binary) (added)
+++ client/resources/img/img36_s.png
Binary file is not shown
 
client/resources/img/img37_s.png (Binary) (added)
+++ client/resources/img/img37_s.png
Binary file is not shown
 
client/resources/img/img38_s.png (Binary) (added)
+++ client/resources/img/img38_s.png
Binary file is not shown
 
client/resources/img/img39_s.png (Binary) (added)
+++ client/resources/img/img39_s.png
Binary file is not shown
 
client/resources/img/left.png (Binary) (added)
+++ client/resources/img/left.png
Binary file is not shown
 
client/resources/img/logo.png (Binary) (added)
+++ client/resources/img/logo.png
Binary file is not shown
 
client/resources/img/logo2.png (Binary) (added)
+++ client/resources/img/logo2.png
Binary file is not shown
 
client/resources/img/look.png (Binary) (added)
+++ client/resources/img/look.png
Binary file is not shown
 
client/resources/img/right.png (Binary) (added)
+++ client/resources/img/right.png
Binary file is not shown
 
client/resources/img/setting.png (Binary) (added)
+++ client/resources/img/setting.png
Binary file is not shown
 
client/views/App.vue (added)
+++ client/views/App.vue
@@ -0,0 +1,61 @@
+<template>
+   <div id="app">
+      <Header></Header>
+               <router-view />
+                  <v-app >
+                  </v-app>
+   </div>
+   <!-- <div >
+      
+      <div class="flex justify-between">
+         <Side></Side>
+         <div>
+            <Menu></Menu>
+            <div class="main-wrap">
+                 
+               <router-view />
+                  <v-app id="app">
+                  </v-app>
+            </div>
+         </div>
+      </div>
+   </div> -->
+</template>
+
+<script>
+import Header from '../views/layout/Header.vue';
+import Menu from '../views/layout/Menu.vue';
+import Side from '../views/layout/Side.vue';
+// import Footer from '../views/layout/Footer.vue';
+
+const App = {
+   data: () => {
+      return {
+      }
+   },
+   methods: {
+
+   },
+   watch: {
+
+   },
+   computed: {
+
+   },
+   components: {
+      Header: Header,
+      Menu: Menu,
+      // Footer:Footer,
+      Side:Side,
+   },
+   mounted: () => {
+      console.log('Vue mounted');
+   }
+}
+
+export default App;
+</script>
+
+<style scoped>
+
+</style>
 
client/views/Login.vue (added)
+++ client/views/Login.vue
@@ -0,0 +1,53 @@
+<template>
+   <div class="login-container">
+      <img class="login-bg" src="../resources/img/bg.png" alt="">
+      <div class="login ">
+         <div class="logo flex justify-end"><img src="../resources/img/logo.png" alt=""></div>
+
+         <div class="login-box">
+            <div class="flex align-center justify-start mb40">
+               <img src="../resources/img/icon1.png" alt="" class="mr20">
+               <h2> 로그인 하기</h2>
+            </div>
+            <form @submit.prevent="submitForm" class="login-form ">
+               <div class="mb30">
+                  <p class="mb15" for="username">아이디</p>
+                  <input type="text" id="username" v-model="username" placeholder="아이디를 입력하세요.">
+               </div>
+               <div>
+                  <p class="mb15" for="password">비밀번호</p>
+                  <input type="password" id="password" v-model="password" placeholder="비밀번호를 입력하세요.">
+               </div>
+               <button class="login-btn mt50" type="submit" @click="goToApp"><img src="../resources/img/button.png" alt=""> <p >로그인</p></button>
+               <div class="flex justify-between mt40">
+                  <p class="underline">아이디/비밀번호 찾기</p>
+                  <p class="underline">회원가입</p>
+               </div>
+            </form>
+         </div>
+      </div>
+   </div>
+</template>
+
+<script>
+export default {
+   data() {
+      return {
+         username: '',
+         password: ''
+      }
+   },
+   methods: {
+      submitForm() {
+         // 여기에 로그인 로직을 추가하세요.
+         console.log('Username:', this.username);
+         console.log('Password:', this.password);
+      },
+      goToApp() {
+    this.$router.push('/');
+  }
+   }
+}
+</script>
+
+<style scoped></style>(파일 끝에 줄바꿈 문자 없음)
 
client/views/component/ProgressBar.vue (added)
+++ client/views/component/ProgressBar.vue
@@ -0,0 +1,35 @@
+<template>
+    <div class="progress-bar">
+      <div class="progress-bar-fill" :style="{ width: progress + '%' }"></div>
+    </div>
+  </template>
+  
+  <script>
+  export default {
+    props: {
+      progress: {
+        type: Number,
+        required: true
+      }
+    }
+  };
+  </script>
+  
+  <style>
+  .progress-bar {
+    width: 100%;
+    height: 15px;
+    background-color: #f3f3f3;
+    border: 3px solid #331600;
+    border-radius: 20px;
+    overflow: hidden;
+  }
+  
+  .progress-bar-fill {
+    height: 20px;
+    background-color: #FFBA08;
+    width: 0;
+    transition: width 0.5s ease-in-out;
+  }
+  </style>
+  (파일 끝에 줄바꿈 문자 없음)
 
client/views/index.html (added)
+++ client/views/index.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+    <meta name="description" content="Node Vue Web">
+    <link rel="stylesheet" href="../../client/resources/css/reset.css">
+    <link rel="stylesheet" href="../../client/resources/css/style.css">
+    <link rel="stylesheet" href="../../client/resources/css/grid.css">
+    <link rel="stylesheet" href="../../client/resources/css/common.css">
+    <link rel="icon" href="" />
+    <title>Node Vue Web</title>
+</head>
+
+<body>
+    <div id="root"></div>
+    <script src="/client/build/bundle.js"></script>
+    <script>
+        function resizer(data) {
+            const width = window.innerWidth;
+            const ratio = width / 1920;
+            if (data.zoom) {
+                document.getElementsByTagName('body')[0].style.zoom = ratio * data.zoom / 100;
+            } else {
+                document.getElementsByTagName('body')[0].style.zoom = ratio;
+            }
+        };
+        window.addEventListener('resize', resizer);
+        resizer(100); 
+    </script>
+</body>
+
+</html>(파일 끝에 줄바꿈 문자 없음)
 
client/views/index.js (added)
+++ client/views/index.js
@@ -0,0 +1,16 @@
+/**
+ * @author : 최정우
+ * @since : 2022.10.19
+ * @dscription : Vue를 활용한 Client단 구현의 시작점(Index) Component 입니다.
+ */
+import { createApp } from 'vue';
+
+import AppRouter from './pages/AppRouter.js';
+import App from './App.vue';
+// import Login from './Login.vue';
+
+const vue = createApp(App).use(AppRouter)
+// .component('login-page', Login)
+.mount('#root');
+
+
 
client/views/layout/Header.vue (added)
+++ client/views/layout/Header.vue
@@ -0,0 +1,28 @@
+<template>
+    <div class="header flex justify-end">
+        <img src="../../resources/img/setting.png" alt="">
+        <img src="../../resources/img/icon2.png" alt="">
+        <img src="../../resources/img/img03.png" alt="">
+    </div>
+</template>
+
+<script>
+export default {
+    data () {
+        return {
+        }
+    },
+    methods: {
+
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    mounted() {
+        console.log('Header mounted');
+    }
+}
+</script>(파일 끝에 줄바꿈 문자 없음)
 
client/views/layout/Menu.vue (added)
+++ client/views/layout/Menu.vue
@@ -0,0 +1,43 @@
+<template>
+    <div class="menu flex" style="gap: 30px;">
+        <router-link to="/MyPage.page">
+            <button :class="{ active: activeButton === 'mypage' }" type="submit" @click="goToApp('mypage')">
+                <p :class="{ active: activeButton === 'mypage' }">마이페이지</p>
+            </button>
+        </router-link>
+        <router-link to="/Dashboard.page">
+          <button :class="{ active: activeButton === 'dashboard' }" type="submit" @click="goToApp('dashboard')">
+            <p :class="{ active: activeButton === 'dashboard' }">Dashboard</p>
+          </button>
+        </router-link>
+      <router-link to="/MyPlan.page">
+        <button :class="{ active: activeButton === 'schedule' }" type="submit" @click="goToApp('schedule')">
+          <p :class="{ active: activeButton === 'schedule' }">학습일정계획</p>
+        </button>
+      </router-link>
+    </div>
+  </template>
+  
+  <script>
+  
+  
+  export default {
+    data() {
+      return {
+        activeButton: '',
+      };
+    },
+    methods: {
+      goToApp(button) {
+        this.activeButton = button;
+      },
+    },
+    mounted() {
+      console.log('Menu mounted');
+    }
+  };
+  </script>
+  
+  <style>
+  </style>
+  (파일 끝에 줄바꿈 문자 없음)
 
client/views/layout/Side.vue (added)
+++ client/views/layout/Side.vue
@@ -0,0 +1,65 @@
+<template>
+    <div class="side">
+        <div class="logo mb25"><img src="../../resources/img/logo2.png" alt=""></div>
+        <div class="profile mb30">
+            <div class="flex align-start">
+                <img src="../../resources/img/img16_s.png" alt="">
+                <div class="ml25">
+                    <p class="name mb10">학생이름</p>
+                    <p class="mb5">xx중학교 3학년 x반</p>
+                    <progress-bar :progress="progress"></progress-bar>
+                    <span @click="increaseProgress">오늘의 공부</span>
+                    <span class="brown ml10">{{ progress }}%</span>
+                </div>                
+            </div>
+            <hr>
+            <p class="title2 mb25">최근 학습 히스토리</p>
+            <ul class="flex justify-between ml30">
+                <li>자학사 3학년 2학기</li>
+                <li>자학사 3학년 2학기</li>
+            </ul>
+        </div>
+        <div class="ask mb30">
+            <p class="title1 mb15">선생님께 질문 있어요~</p>
+
+            <div class="memo mb15"><textarea name="" id="" placeholder="궁금한 것을 적어보세요."></textarea></div>
+            <div class="flex justify-end"><button>질문하기</button></div>
+        </div>
+        <div class="btn-wrap flex justify-between">
+            <button class="login-btn" type="submit" ><img src="../../resources/img/btn07_s.png" alt=""> <p >오답노트</p></button>
+            <button class="login-btn" type="submit" ><img src="../../resources/img/btn07_s.png" alt=""> <p >오늘 할 다른 공부</p></button>
+        </div>
+    </div>
+</template>
+ 
+<script>
+import ProgressBar from '../component/ProgressBar.vue';
+
+export default {
+    data () {
+        return {
+            progress: 20
+        }
+    },
+    methods: {
+        increaseProgress() {
+      if (this.progress < 100) {
+        this.progress += 10;
+      }
+    }
+
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    components: {
+    ProgressBar
+  },
+    mounted() {
+        console.log('Menu mounted');
+    }
+}
+</script>(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/AppRouter.js (added)
+++ client/views/pages/AppRouter.js
@@ -0,0 +1,73 @@
+import { createWebHistory, createRouter } from "vue-router";
+
+// import App from "../App.vue";
+import login from "../Login.vue"
+import MyPage from './main/MyPage.vue';
+import MyPlan from './main/MyPlan.vue';
+import Dashboard from './main/Dashboard.vue';
+import Main from "./main/Main.vue";
+import Chapter1 from "./main/Chapter/Chapter1.vue";
+import Chapter1_1 from "./main/Chapter/Chapter1_1.vue";
+import Chapter1_2 from "./main/Chapter/Chapter1_2.vue";
+import Chapter1_3 from "./main/Chapter/Chapter1_3.vue";
+import Chapter2 from "./main/Chapter/Chapter2.vue";
+import Chapter3 from "./main/Chapter/Chapter3.vue";
+import Chapter4 from "./main/Chapter/Chapter4.vue";
+import Chapter5 from "./main/Chapter/Chapter5.vue";
+import Chapter6 from "./main/Chapter/Chapter6.vue";
+import Chapter7 from "./main/Chapter/Chapter7.vue";
+import Chapter8 from "./main/Chapter/Chapter8.vue";
+import Chapter9 from "./main/Chapter/Chapter9.vue";
+import Chapter10 from "./main/Chapter/Chapter10.vue";
+import Chapter11 from "./main/Chapter/Chapter11.vue";
+
+import Main_p from "./parents/Main_p.vue";
+
+import Main_t from "./teacher/Main_t.vue";
+
+const routes = [
+    { path: '/login.page', name: 'login', component: login},
+    // { path: '/App.page', name: 'App', component: App,
+    //     children:[
+        
+          
+    //     ]
+    // },
+    // { path: '/Main.page', name: 'Main', component: Main},
+    /* 학생 */
+    { path: '/', 
+    name: 'Main', 
+    component: Main,
+    children:[
+        { path: '/Dashboard.page', name: 'Dashboard', component: Dashboard},        
+    { path: '/MyPage.page', name: 'MyPage', component: MyPage},
+    { path: '/MyPlan.page', name: 'MyPlan', component: MyPlan},
+    ]
+},
+{ path: '/Chapter1.page', name: 'Chapter1', component: Chapter1},
+{ path: '/Chapter1_1.page', name: 'Chapter1_1', component: Chapter1_1},
+{ path: '/Chapter1_2.page', name: 'Chapter1_2', component: Chapter1_2},
+{ path: '/Chapter1_3.page', name: 'Chapter1_3', component: Chapter1_3},
+    { path: '/Chapter2.page', name: 'Chapter2', component: Chapter2},
+    { path: '/Chapter3.page', name: 'Chapter3', component: Chapter3},
+    { path: '/Chapter4.page', name: 'Chapter4', component: Chapter4},
+    { path: '/Chapter5.page', name: 'Chapter5', component: Chapter5},
+    { path: '/Chapter6.page', name: 'Chapter6', component: Chapter6},
+    { path: '/Chapter7.page', name: 'Chapter7', component: Chapter7},
+    { path: '/Chapter8.page', name: 'Chapter8', component: Chapter8},
+    { path: '/Chapter9.page', name: 'Chapter9', component: Chapter9},
+    { path: '/Chapter10.page', name: 'Chapter10', component: Chapter10},
+    { path: '/Chapter11.page', name: 'Chapter11', component: Chapter11},
+
+   /* 부모님 */
+   { path: '/Main_p.page', name: 'Main_p', component: Main_p},
+   /* 선생님 */
+   { path: '/Main_t.page', name: 'Main_t', component: Main_t},
+];
+
+const AppRouter = createRouter({
+    history: createWebHistory(),
+    routes,
+});
+
+export default AppRouter;(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/Login copy.vue (added)
+++ client/views/pages/Login copy.vue
@@ -0,0 +1,53 @@
+<template>
+   <div class="login-container">
+      <img class="login-bg" src="../../resources/img/bg.png" alt="">
+      <div class="login ">
+         <div class="logo flex justify-end"><img src="../../resources/img/logo.png" alt=""></div>
+
+         <div class="login-box">
+            <div class="flex align-center justify-start mb40">
+               <img src="../../resources/img/icon1.png" alt="" class="mr20">
+               <h2> 로그인 하기</h2>
+            </div>
+            <form @submit.prevent="submitForm" class="login-form ">
+               <div class="mb30">
+                  <p class="mb15" for="username">아이디</p>
+                  <input type="text" id="username" v-model="username" placeholder="아이디를 입력하세요.">
+               </div>
+               <div>
+                  <p class="mb15" for="password">비밀번호</p>
+                  <input type="password" id="password" v-model="password" placeholder="비밀번호를 입력하세요.">
+               </div>
+               <button class="login-btn mt50" type="submit" @click="goToApp"><img src="../../resources/img/button.png" alt=""> <p >로그인</p></button>
+               <div class="flex justify-between mt40">
+                  <p class="underline">아이디/비밀번호 찾기</p>
+                  <p class="underline">회원가입</p>
+               </div>
+            </form>
+         </div>
+      </div>
+   </div>
+</template>
+
+<script>
+export default {
+   data() {
+      return {
+         username: '',
+         password: ''
+      }
+   },
+   methods: {
+      submitForm() {
+         // 여기에 로그인 로직을 추가하세요.
+         console.log('Username:', this.username);
+         console.log('Password:', this.password);
+      },
+      goToApp() {
+    this.$router.push('/app.page');
+  }
+   }
+}
+</script>
+
+<style scoped></style>(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/main/Chapter/Chapter1.vue (added)
+++ client/views/pages/main/Chapter/Chapter1.vue
@@ -0,0 +1,45 @@
+<template>
+    <div id="Chapter1" class="content-wrap">
+        <div class="title-box mb25 flex align-center mt40">
+            <span class="title mr40">1. Hello WORLD</span>
+            <span class="subtitle">my name is dd</span>
+        </div>
+        <div class="flex justify-between align-center">
+            <div class="pre-btn"><img src="../../../../resources/img/left.png" alt=""></div>
+            <div class="content title-box">
+                <p class="title mt25 title-bg">step1. Hello WORLD</p>
+                <div class="videoCon">
+                    <img src="../../../../resources/img/img34_s.png" data-num="1">
+                    <button class="videoStart" data-video="1" tabindex="0" aria-label="동영상 재생"><img src="../../../../resources/img/btn09_s.png"
+                            data-num="1"></button>
+                           <div class="look-text"> <button ><img src="../../../../resources/img/btn08_s.png" alt=""><p>지문 보기</p></button></div>
+                </div>
+            </div>
+            <div class="next-btn"  @click="goToPage('Chapter1_1')"><img src="../../../../resources/img/right.png" alt=""></div>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+        }
+    },
+    methods: {
+        goToPage(page) {
+            this.$router.push({ name: page });
+        }
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    components: {
+    },
+    mounted() {
+    }
+}
+</script>(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/main/Chapter/Chapter10.vue (added)
+++ client/views/pages/main/Chapter/Chapter10.vue
@@ -0,0 +1,0 @@
 
client/views/pages/main/Chapter/Chapter11.vue (added)
+++ client/views/pages/main/Chapter/Chapter11.vue
@@ -0,0 +1,0 @@
 
client/views/pages/main/Chapter/Chapter1_1.vue (added)
+++ client/views/pages/main/Chapter/Chapter1_1.vue
@@ -0,0 +1,83 @@
+<template>
+  <div id="Chapter1_1" class="content-wrap">
+    <div class="title-box mb25 flex align-center mt40">
+      <span class="title mr40">1. Hello WORLD</span>
+      <span class="subtitle">my name is dd</span>
+    </div>
+    <div class="flex justify-between align-center">
+      <div class="pre-btn" @click="goToPage('Chapter1')"><img src="../../../../resources/img/left.png" alt=""></div>
+      <div class="content title-box">
+        <p class="title mt25 title-bg">step1. Hello WORLD</p>
+
+        <div class="imgGroup">
+          <img src="../../../../resources/img/img35_s.png" data-num="1">
+
+        </div>
+        <div class="textareaGroup">
+          <textarea>Bike lanes are important because they ket, bike riders and all other people safe. Before bike lanes, people rode on the sidewalk or in the same lanes as the cars on the street. Riding a bike on the sidewalk can cause you to crash into someone who is walking by. And riding a bike in the same lanes as cars can be unsafe, too, Bikes move more slowly than cars, so people driving behind bikes will try to go around them. These cars could hit the bike riders or other cars. </textarea>
+          <div id="popup" class="popup">
+            <div class="imgGroup mb10">
+              <img src="../../../../resources/img/img36_s.png" data-num="1">
+            </div>
+              <h3>sidewalk</h3>
+             <div class="flex align-center  justify-center mt10">
+                <p class="yellow-box">명</p>
+                <span class="title1">보도</span>
+             </div>
+          </div>
+        </div>
+      </div>
+      <div class="next-btn" @click="goToPage('Chapter1_2')"><img src="../../../../resources/img/right.png" alt=""></div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+    }
+  },
+  methods: {
+    goToPage(page) {
+      this.$router.push({ name: page });
+    }
+  },
+  watch: {
+
+  },
+  computed: {
+
+  },
+  components: {
+  },
+  mounted() {
+    const textArea = this.$refs.textArea;
+      const popup = this.$refs.popup;
+
+      textArea.addEventListener('mousemove', (event) => {
+         const text = textArea.value;
+         const words = text.split(' ');
+         const selectionStart = textArea.selectionStart;
+         const selectionEnd = textArea.selectionEnd;
+
+         if (selectionStart !== selectionEnd) {
+            const selectedText = text.substring(selectionStart, selectionEnd);
+            const rect = textArea.getBoundingClientRect();
+            popup.style.left = `${event.clientX}px`;
+            popup.style.top = `${event.clientY + window.scrollY}px`;
+            popup.innerHTML = `You selected: ${selectedText}`;
+            popup.style.display = 'block';
+         } else {
+            popup.style.display = 'none';
+         }
+      });
+
+      document.addEventListener('click', (event) => {
+         if (!textArea.contains(event.target) && !popup.contains(event.target)) {
+            popup.style.display = 'none';
+         }
+      });
+  }
+}
+</script>(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/main/Chapter/Chapter1_2.vue (added)
+++ client/views/pages/main/Chapter/Chapter1_2.vue
@@ -0,0 +1,97 @@
+<template>
+  <div id="Chapter1_2" class="content-wrap">
+    <div class="title-box mb25 flex align-center mt40">
+      <span class="title mr40">1. Hello WORLD</span>
+      <span class="subtitle">my name is dd</span>
+    </div>
+    <div class="flex justify-between align-center">
+      <div class="pre-btn"  @click="goToPage('Chapter1_1')"><img src="../../../../resources/img/left.png" alt=""></div>
+      <div class="content title-box">
+        <p class="title mt25 title-bg">step1. Hello WORLD</p>
+<h4>각 인물들의 대화를 집중해서 읽어보세요</h4>
+        <div class="readGroup">
+          <article class="flex align-start mb10">
+            <div class="icon mr40">
+              <img src="../../../../resources/img/img37_s.png" alt="">
+              <p class="name">발화좌</p>
+            </div>
+            <p class="read">What’s up man, nice to meet you Minsu. how are you today?</p>
+          </article>
+          <article class="flex align-start mb10 justify-end">
+            <p class="read mr40">What’s up man, nice to meet you Minsu. how are you today?</p>
+            <div class="icon ">
+              <img src="../../../../resources/img/img37_s.png" alt="">
+              <p class="name">발화좌</p>
+            </div>
+          </article>
+          <article class="flex align-start mb10">
+            <div class="icon mr40">
+              <img src="../../../../resources/img/img37_s.png" alt="">
+              <p class="name">발화좌</p>
+            </div>
+            <p class="read">What’s up man, nice to meet you Minsu. how are you today?</p>
+          </article>
+          <article class="flex align-start mb10 justify-end">
+            <p class="read mr40">What’s up man, nice to meet you Minsu. how are you today?</p>
+            <div class="icon ">
+              <img src="../../../../resources/img/img37_s.png" alt="">
+              <p class="name">발화좌</p>
+            </div>
+          </article>
+
+        </div>
+      </div>
+      <div class="next-btn" @click="goToPage('Chapter1_3')"><img src="../../../../resources/img/right.png" alt=""></div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+    }
+  },
+  methods: {
+    goToPage(page) {
+      this.$router.push({ name: page });
+    }
+  },
+  watch: {
+
+  },
+  computed: {
+
+  },
+  components: {
+  },
+  mounted() {
+    const textArea = this.$refs.textArea;
+      const popup = this.$refs.popup;
+
+      textArea.addEventListener('mousemove', (event) => {
+         const text = textArea.value;
+         const words = text.split(' ');
+         const selectionStart = textArea.selectionStart;
+         const selectionEnd = textArea.selectionEnd;
+
+         if (selectionStart !== selectionEnd) {
+            const selectedText = text.substring(selectionStart, selectionEnd);
+            const rect = textArea.getBoundingClientRect();
+            popup.style.left = `${event.clientX}px`;
+            popup.style.top = `${event.clientY + window.scrollY}px`;
+            popup.innerHTML = `You selected: ${selectedText}`;
+            popup.style.display = 'block';
+         } else {
+            popup.style.display = 'none';
+         }
+      });
+
+      document.addEventListener('click', (event) => {
+         if (!textArea.contains(event.target) && !popup.contains(event.target)) {
+            popup.style.display = 'none';
+         }
+      });
+  }
+}
+</script>(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/main/Chapter/Chapter1_3.vue (added)
+++ client/views/pages/main/Chapter/Chapter1_3.vue
@@ -0,0 +1,45 @@
+<template>
+    <div id="Chapter1" class="content-wrap">
+        <div class="title-box mb25 flex align-center mt40">
+            <span class="title mr40">1. Hello WORLD</span>
+            <span class="subtitle">my name is dd</span>
+        </div>
+        <div class="flex justify-between align-center">
+            <div class="pre-btn"  @click="goToPage('Chapter1_2')"><img src="../../../../resources/img/left.png" alt=""></div>
+            <div class="content title-box">
+                <p class="title mt25 title-bg">step1. Hello WORLD</p>
+                <div class="videoCon">
+                    <img src="../../../../resources/img/img34_s.png" data-num="1">
+                    <button class="videoStart" data-video="1" tabindex="0" aria-label="동영상 재생"><img src="../../../../resources/img/btn09_s.png"
+                            data-num="1"></button>
+                           <div class="look-text"> <button ><img src="../../../../resources/img/btn08_s.png" alt=""><p>지문 보기</p></button></div>
+                </div>
+            </div>
+            <div class="next-btn"  @click="goToPage('Chapter1_4')"><img src="../../../../resources/img/right.png" alt=""></div>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+        }
+    },
+    methods: {
+        goToPage(page) {
+            this.$router.push({ name: page });
+        }
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    components: {
+    },
+    mounted() {
+    }
+}
+</script>(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/main/Chapter/Chapter2.vue (added)
+++ client/views/pages/main/Chapter/Chapter2.vue
@@ -0,0 +1,0 @@
 
client/views/pages/main/Chapter/Chapter3.vue (added)
+++ client/views/pages/main/Chapter/Chapter3.vue
@@ -0,0 +1,0 @@
 
client/views/pages/main/Chapter/Chapter4.vue (added)
+++ client/views/pages/main/Chapter/Chapter4.vue
@@ -0,0 +1,0 @@
 
client/views/pages/main/Chapter/Chapter5.vue (added)
+++ client/views/pages/main/Chapter/Chapter5.vue
@@ -0,0 +1,0 @@
 
client/views/pages/main/Chapter/Chapter6.vue (added)
+++ client/views/pages/main/Chapter/Chapter6.vue
@@ -0,0 +1,0 @@
 
client/views/pages/main/Chapter/Chapter7.vue (added)
+++ client/views/pages/main/Chapter/Chapter7.vue
@@ -0,0 +1,0 @@
 
client/views/pages/main/Chapter/Chapter8.vue (added)
+++ client/views/pages/main/Chapter/Chapter8.vue
@@ -0,0 +1,0 @@
 
client/views/pages/main/Chapter/Chapter9.vue (added)
+++ client/views/pages/main/Chapter/Chapter9.vue
@@ -0,0 +1,0 @@
 
client/views/pages/main/Dashboard.vue (added)
+++ client/views/pages/main/Dashboard.vue
@@ -0,0 +1,93 @@
+<template>
+    <div class="main">
+        <div class="race-wrap">
+            <div class="title-box">
+                <p class="title">hello world!</p>
+                <p class="subtitle">hi my name is dd!</p>
+            </div>
+            <div class="race-box">
+                <div class="rabbit"><img src="../../../resources/img/img09_s.png" alt=""></div>
+                <div class="rcon flex justify-end mb5">
+                    <div class="race-btn" @click="goToPage('Chapter1')">
+                        <img src="../../../resources/img/img11_1_s.png" alt="" data-num="1">
+                        <p>지문1</p>
+                    </div>
+                    <div class="race-btn" @click="goToPage('Chapter2')">
+                        <img src="../../../resources/img/img11_1_s.png" alt="" data-num="2">
+                        <p>단어장</p>
+                    </div>
+                </div>
+                <div class="lcon flex justify-between mb5">
+                    <div class="race-btn" @click="goToPage('Chapter7')">
+                        <img src="../../../resources/img/img11_1_s.png" alt="" data-num="7">
+                        <p>문제1</p>
+                    </div>
+                    <div class="race-btn" @click="goToPage('Chapter6')">
+                        <img src="../../../resources/img/img11_1_s.png" alt="" data-num="6">
+                        <p>단어장</p>
+                    </div>
+                    <div class="race-btn" @click="goToPage('Chapter5')">
+                        <img src="../../../resources/img/img11_1_s.png" alt="" data-num="5">
+                        <p>지문2</p>
+                    </div>
+                    <div class="race-btn" @click="goToPage('Chapter4')">
+                        <img src="../../../resources/img/img11_1_s.png" alt="" data-num="4">
+                        <p>문제2</p>
+                    </div>
+                    <div class="race-btn" @click="goToPage('Chapter3')">
+                        <img src="../../../resources/img/img11_1_s.png" alt="" data-num="3">
+                        <p>문제1</p>
+                    </div>
+                </div>
+                <div class="rcon flex">
+                    <div class="race-btn" @click="goToPage('Chapter8')">
+                        <img src="../../../resources/img/img11_2_s.png" alt="" data-num="8">
+                        <p class="long">중간 평가</p>
+                    </div>
+                    <div class="race-btn" @click="goToPage('Chapter9')">
+                        <img src="../../../resources/img/img11_1_s.png" alt="" data-num="9">
+                        <p>지문3</p>
+                    </div>
+                    <div class="race-btn" @click="goToPage('Chapter10')">
+                        <img src="../../../resources/img/img11_1_s.png" alt="" data-num="10">
+                        <p>단어장</p>
+                    </div>
+                    <div class="race-btn" @click="goToPage('Chapter11')">
+                        <img src="../../../resources/img/img11_2_s.png" alt="" data-num="11">
+                        <p class="long">최종 평가</p>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="complete-wrap mt90 ">
+            <h2 class="mb40">전체 진행률</h2>
+        </div>
+
+    </div>
+</template>
+
+<script>
+
+export default {
+    data() {
+        return {
+        }
+    },
+    methods: {
+        goToPage(page) {
+            this.$router.push({ name: page });
+        }
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    components: {
+    },
+    mounted() {
+        console.log('main mounted');
+    }
+}
+</script>(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/main/Main.vue (added)
+++ client/views/pages/main/Main.vue
@@ -0,0 +1,43 @@
+<template>
+      <div class="flex justify-between">
+         <Side></Side>
+         <div>
+            <Menu></Menu>
+            <div class="main-wrap">
+                <router-view />
+            </div>
+         </div>
+      </div>
+
+</template>
+
+<script>
+import Header from '../../layout/Header.vue';
+import Menu from '../../layout/Menu.vue';
+import Side from '../../layout/Side.vue';
+
+export default {
+    data() {
+        return {
+        }
+    },
+    methods: {
+       
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    components: {
+        Header: Header,
+      Menu: Menu,
+      // Footer:Footer,
+      Side:Side,
+    },
+    mounted() {
+        console.log('main mounted');
+    }
+}
+</script>(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/main/MyPage.vue (added)
+++ client/views/pages/main/MyPage.vue
@@ -0,0 +1,24 @@
+<template>
+    <div>마이페이지</div>
+</template>
+
+<script>
+export default {
+    data () {
+        return {
+        }
+    },
+    methods: {
+
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    mounted() {
+        console.log('Main2 mounted');
+    }
+}
+</script>(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/main/MyPlan.vue (added)
+++ client/views/pages/main/MyPlan.vue
@@ -0,0 +1,24 @@
+<template>
+    <div>학습일정계획</div>
+</template>
+
+<script>
+export default {
+    data () {
+        return {
+        }
+    },
+    methods: {
+
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    mounted() {
+        console.log('Main2 mounted');
+    }
+}
+</script>(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/parents/Main_p.vue (added)
+++ client/views/pages/parents/Main_p.vue
@@ -0,0 +1,27 @@
+<template>
+    <div>Main.vue</div>
+</template>
+
+<script>
+
+export default {
+    data () {
+        return {
+        }
+    },
+    methods: {
+
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    components: {
+    },
+    mounted() {
+        console.log('main mounted');
+    }
+}
+</script>(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/teacher/Main_t.vue (added)
+++ client/views/pages/teacher/Main_t.vue
@@ -0,0 +1,27 @@
+<template>
+    <div>Main.vue</div>
+</template>
+
+<script>
+
+export default {
+    data () {
+        return {
+        }
+    },
+    methods: {
+
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    components: {
+    },
+    mounted() {
+        console.log('main mounted');
+    }
+}
+</script>(파일 끝에 줄바꿈 문자 없음)
 
package-lock.json (added)
+++ package-lock.json
@@ -0,0 +1,3866 @@
+{
+  "name": "lms_front",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "dependencies": {
+        "@babel/cli": "7.19.3",
+        "@babel/core": "7.19.3",
+        "babel-loader": "8.2.5",
+        "css-loader": "6.7.1",
+        "express": "^4.18.1",
+        "express-http-proxy": "^2.0.0",
+        "file-loader": "6.2.0",
+        "fs": "0.0.1-security",
+        "new-line": "^1.1.1",
+        "pg": "8.8.0",
+        "url-loader": "4.1.1",
+        "vue": "3.2.40",
+        "vue-loader": "^17.0.0",
+        "vue-router": "4.1.5",
+        "vue-style-loader": "4.1.3",
+        "vue3-sfc-loader": "^0.8.4",
+        "webpack": "5.74.0",
+        "webpack-cli": "4.10.0"
+      }
+    },
+    "node_modules/@ampproject/remapping": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+      "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/cli": {
+      "version": "7.19.3",
+      "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.19.3.tgz",
+      "integrity": "sha512-643/TybmaCAe101m2tSVHi9UKpETXP9c/Ff4mD2tAwkdP6esKIfaauZFc67vGEM6r9fekbEGid+sZhbEnSe3dg==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/trace-mapping": "^0.3.8",
+        "commander": "^4.0.1",
+        "convert-source-map": "^1.1.0",
+        "fs-readdir-recursive": "^1.1.0",
+        "glob": "^7.2.0",
+        "make-dir": "^2.1.0",
+        "slash": "^2.0.0"
+      },
+      "bin": {
+        "babel": "bin/babel.js",
+        "babel-external-helpers": "bin/babel-external-helpers.js"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "optionalDependencies": {
+        "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3",
+        "chokidar": "^3.4.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/code-frame": {
+      "version": "7.24.7",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz",
+      "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/highlight": "^7.24.7",
+        "picocolors": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/compat-data": {
+      "version": "7.25.0",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.0.tgz",
+      "integrity": "sha512-P4fwKI2mjEb3ZU5cnMJzvRsRKGBUcs8jvxIoRmr6ufAY9Xk2Bz7JubRTTivkw55c7WQJfTECeqYVa+HZ0FzREg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/core": {
+      "version": "7.19.3",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz",
+      "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@ampproject/remapping": "^2.1.0",
+        "@babel/code-frame": "^7.18.6",
+        "@babel/generator": "^7.19.3",
+        "@babel/helper-compilation-targets": "^7.19.3",
+        "@babel/helper-module-transforms": "^7.19.0",
+        "@babel/helpers": "^7.19.0",
+        "@babel/parser": "^7.19.3",
+        "@babel/template": "^7.18.10",
+        "@babel/traverse": "^7.19.3",
+        "@babel/types": "^7.19.3",
+        "convert-source-map": "^1.7.0",
+        "debug": "^4.1.0",
+        "gensync": "^1.0.0-beta.2",
+        "json5": "^2.2.1",
+        "semver": "^6.3.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/babel"
+      }
+    },
+    "node_modules/@babel/generator": {
+      "version": "7.25.0",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz",
+      "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.25.0",
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.25",
+        "jsesc": "^2.5.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-compilation-targets": {
+      "version": "7.24.8",
+      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz",
+      "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/compat-data": "^7.24.8",
+        "@babel/helper-validator-option": "^7.24.8",
+        "browserslist": "^4.23.1",
+        "lru-cache": "^5.1.1",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-imports": {
+      "version": "7.24.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz",
+      "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/traverse": "^7.24.7",
+        "@babel/types": "^7.24.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-transforms": {
+      "version": "7.25.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.0.tgz",
+      "integrity": "sha512-bIkOa2ZJYn7FHnepzr5iX9Kmz8FjIz4UKzJ9zhX3dnYuVW0xul9RuR3skBfoLu+FPTQw90EHW9rJsSZhyLQ3fQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-module-imports": "^7.24.7",
+        "@babel/helper-simple-access": "^7.24.7",
+        "@babel/helper-validator-identifier": "^7.24.7",
+        "@babel/traverse": "^7.25.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-simple-access": {
+      "version": "7.24.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz",
+      "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/traverse": "^7.24.7",
+        "@babel/types": "^7.24.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.24.8",
+      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz",
+      "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.24.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz",
+      "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-option": {
+      "version": "7.24.8",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz",
+      "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helpers": {
+      "version": "7.25.0",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz",
+      "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/template": "^7.25.0",
+        "@babel/types": "^7.25.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/highlight": {
+      "version": "7.24.7",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz",
+      "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-validator-identifier": "^7.24.7",
+        "chalk": "^2.4.2",
+        "js-tokens": "^4.0.0",
+        "picocolors": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.25.0",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.0.tgz",
+      "integrity": "sha512-CzdIU9jdP0dg7HdyB+bHvDJGagUv+qtzZt5rYCWwW6tITNqV9odjp6Qu41gkG0ca5UfdDUWrKkiAnHHdGRnOrA==",
+      "license": "MIT",
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/template": {
+      "version": "7.25.0",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz",
+      "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/code-frame": "^7.24.7",
+        "@babel/parser": "^7.25.0",
+        "@babel/types": "^7.25.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/traverse": {
+      "version": "7.25.1",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.1.tgz",
+      "integrity": "sha512-LrHHoWq08ZpmmFqBAzN+hUdWwy5zt7FGa/hVwMcOqW6OVtwqaoD5utfuGYU87JYxdZgLUvktAsn37j/sYR9siA==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/code-frame": "^7.24.7",
+        "@babel/generator": "^7.25.0",
+        "@babel/parser": "^7.25.0",
+        "@babel/template": "^7.25.0",
+        "@babel/types": "^7.25.0",
+        "debug": "^4.3.1",
+        "globals": "^11.1.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.25.0",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.0.tgz",
+      "integrity": "sha512-LcnxQSsd9aXOIgmmSpvZ/1yo46ra2ESYyqLcryaBZOghxy5qqOBjvCWP5JfkI8yl9rlxRgdLTTMCQQRcN2hdCg==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.24.8",
+        "@babel/helper-validator-identifier": "^7.24.7",
+        "to-fast-properties": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@discoveryjs/json-ext": {
+      "version": "0.5.7",
+      "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
+      "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.5",
+      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+      "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/set-array": "^1.2.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+      "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/set-array": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+      "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/source-map": {
+      "version": "0.3.6",
+      "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
+      "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.25"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+      "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
+      "license": "MIT"
+    },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.25",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+      "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
+      }
+    },
+    "node_modules/@nicolo-ribaudo/chokidar-2": {
+      "version": "2.1.8-no-fsevents.3",
+      "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz",
+      "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/@types/eslint": {
+      "version": "9.6.0",
+      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz",
+      "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/estree": "*",
+        "@types/json-schema": "*"
+      }
+    },
+    "node_modules/@types/eslint-scope": {
+      "version": "3.7.7",
+      "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
+      "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/eslint": "*",
+        "@types/estree": "*"
+      }
+    },
+    "node_modules/@types/estree": {
+      "version": "0.0.51",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz",
+      "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==",
+      "license": "MIT"
+    },
+    "node_modules/@types/json-schema": {
+      "version": "7.0.15",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+      "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+      "license": "MIT"
+    },
+    "node_modules/@types/node": {
+      "version": "22.0.0",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-22.0.0.tgz",
+      "integrity": "sha512-VT7KSYudcPOzP5Q0wfbowyNLaVR8QWUdw+088uFWwfvpY6uCWaXpqV6ieLAu9WBcnTa7H4Z5RLK8I5t2FuOcqw==",
+      "license": "MIT",
+      "dependencies": {
+        "undici-types": "~6.11.1"
+      }
+    },
+    "node_modules/@vue/compiler-core": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.40.tgz",
+      "integrity": "sha512-2Dc3Stk0J/VyQ4OUr2yEC53kU28614lZS+bnrCbFSAIftBJ40g/2yQzf4mPBiFuqguMB7hyHaujdgZAQ67kZYA==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.16.4",
+        "@vue/shared": "3.2.40",
+        "estree-walker": "^2.0.2",
+        "source-map": "^0.6.1"
+      }
+    },
+    "node_modules/@vue/compiler-dom": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.40.tgz",
+      "integrity": "sha512-OZCNyYVC2LQJy4H7h0o28rtk+4v+HMQygRTpmibGoG9wZyomQiS5otU7qo3Wlq5UfHDw2RFwxb9BJgKjVpjrQw==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-core": "3.2.40",
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "node_modules/@vue/compiler-sfc": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.40.tgz",
+      "integrity": "sha512-tzqwniIN1fu1PDHC3CpqY/dPCfN/RN1thpBC+g69kJcrl7mbGiHKNwbA6kJ3XKKy8R6JLKqcpVugqN4HkeBFFg==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.16.4",
+        "@vue/compiler-core": "3.2.40",
+        "@vue/compiler-dom": "3.2.40",
+        "@vue/compiler-ssr": "3.2.40",
+        "@vue/reactivity-transform": "3.2.40",
+        "@vue/shared": "3.2.40",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.25.7",
+        "postcss": "^8.1.10",
+        "source-map": "^0.6.1"
+      }
+    },
+    "node_modules/@vue/compiler-ssr": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.40.tgz",
+      "integrity": "sha512-80cQcgasKjrPPuKcxwuCx7feq+wC6oFl5YaKSee9pV3DNq+6fmCVwEEC3vvkf/E2aI76rIJSOYHsWSEIxK74oQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-dom": "3.2.40",
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "node_modules/@vue/devtools-api": {
+      "version": "6.6.3",
+      "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.3.tgz",
+      "integrity": "sha512-0MiMsFma/HqA6g3KLKn+AGpL1kgKhFWszC9U29NfpWK5LE7bjeXxySWJrOJ77hBz+TBrBQ7o4QJqbPbqbs8rJw==",
+      "license": "MIT"
+    },
+    "node_modules/@vue/reactivity": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.40.tgz",
+      "integrity": "sha512-N9qgGLlZmtUBMHF9xDT4EkD9RdXde1Xbveb+niWMXuHVWQP5BzgRmE3SFyUBBcyayG4y1lhoz+lphGRRxxK4RA==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "node_modules/@vue/reactivity-transform": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.40.tgz",
+      "integrity": "sha512-HQUCVwEaacq6fGEsg2NUuGKIhUveMCjOk8jGHqLXPI2w6zFoPrlQhwWEaINTv5kkZDXKEnCijAp+4gNEHG03yw==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.16.4",
+        "@vue/compiler-core": "3.2.40",
+        "@vue/shared": "3.2.40",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.25.7"
+      }
+    },
+    "node_modules/@vue/runtime-core": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.40.tgz",
+      "integrity": "sha512-U1+rWf0H8xK8aBUZhnrN97yoZfHbjgw/bGUzfgKPJl69/mXDuSg8CbdBYBn6VVQdR947vWneQBFzdhasyzMUKg==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/reactivity": "3.2.40",
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "node_modules/@vue/runtime-dom": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.40.tgz",
+      "integrity": "sha512-AO2HMQ+0s2+MCec8hXAhxMgWhFhOPJ/CyRXnmTJ6XIOnJFLrH5Iq3TNwvVcODGR295jy77I6dWPj+wvFoSYaww==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/runtime-core": "3.2.40",
+        "@vue/shared": "3.2.40",
+        "csstype": "^2.6.8"
+      }
+    },
+    "node_modules/@vue/server-renderer": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.40.tgz",
+      "integrity": "sha512-gtUcpRwrXOJPJ4qyBpU3EyxQa4EkV8I4f8VrDePcGCPe4O/hd0BPS7v9OgjIQob6Ap8VDz9G+mGTKazE45/95w==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-ssr": "3.2.40",
+        "@vue/shared": "3.2.40"
+      },
+      "peerDependencies": {
+        "vue": "3.2.40"
+      }
+    },
+    "node_modules/@vue/shared": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.40.tgz",
+      "integrity": "sha512-0PLQ6RUtZM0vO3teRfzGi4ltLUO5aO+kLgwh4Um3THSR03rpQWLTuRCkuO5A41ITzwdWeKdPHtSARuPkoo5pCQ==",
+      "license": "MIT"
+    },
+    "node_modules/@webassemblyjs/ast": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz",
+      "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==",
+      "license": "MIT",
+      "dependencies": {
+        "@webassemblyjs/helper-numbers": "1.11.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.1"
+      }
+    },
+    "node_modules/@webassemblyjs/floating-point-hex-parser": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz",
+      "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==",
+      "license": "MIT"
+    },
+    "node_modules/@webassemblyjs/helper-api-error": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz",
+      "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==",
+      "license": "MIT"
+    },
+    "node_modules/@webassemblyjs/helper-buffer": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz",
+      "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==",
+      "license": "MIT"
+    },
+    "node_modules/@webassemblyjs/helper-numbers": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz",
+      "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@webassemblyjs/floating-point-hex-parser": "1.11.1",
+        "@webassemblyjs/helper-api-error": "1.11.1",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "node_modules/@webassemblyjs/helper-wasm-bytecode": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz",
+      "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==",
+      "license": "MIT"
+    },
+    "node_modules/@webassemblyjs/helper-wasm-section": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz",
+      "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==",
+      "license": "MIT",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/helper-buffer": "1.11.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+        "@webassemblyjs/wasm-gen": "1.11.1"
+      }
+    },
+    "node_modules/@webassemblyjs/ieee754": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz",
+      "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@xtuc/ieee754": "^1.2.0"
+      }
+    },
+    "node_modules/@webassemblyjs/leb128": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz",
+      "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "node_modules/@webassemblyjs/utf8": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz",
+      "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==",
+      "license": "MIT"
+    },
+    "node_modules/@webassemblyjs/wasm-edit": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz",
+      "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==",
+      "license": "MIT",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/helper-buffer": "1.11.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+        "@webassemblyjs/helper-wasm-section": "1.11.1",
+        "@webassemblyjs/wasm-gen": "1.11.1",
+        "@webassemblyjs/wasm-opt": "1.11.1",
+        "@webassemblyjs/wasm-parser": "1.11.1",
+        "@webassemblyjs/wast-printer": "1.11.1"
+      }
+    },
+    "node_modules/@webassemblyjs/wasm-gen": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz",
+      "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==",
+      "license": "MIT",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+        "@webassemblyjs/ieee754": "1.11.1",
+        "@webassemblyjs/leb128": "1.11.1",
+        "@webassemblyjs/utf8": "1.11.1"
+      }
+    },
+    "node_modules/@webassemblyjs/wasm-opt": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz",
+      "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==",
+      "license": "MIT",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/helper-buffer": "1.11.1",
+        "@webassemblyjs/wasm-gen": "1.11.1",
+        "@webassemblyjs/wasm-parser": "1.11.1"
+      }
+    },
+    "node_modules/@webassemblyjs/wasm-parser": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz",
+      "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==",
+      "license": "MIT",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/helper-api-error": "1.11.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+        "@webassemblyjs/ieee754": "1.11.1",
+        "@webassemblyjs/leb128": "1.11.1",
+        "@webassemblyjs/utf8": "1.11.1"
+      }
+    },
+    "node_modules/@webassemblyjs/wast-printer": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz",
+      "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==",
+      "license": "MIT",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "node_modules/@webpack-cli/configtest": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz",
+      "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==",
+      "license": "MIT",
+      "peerDependencies": {
+        "webpack": "4.x.x || 5.x.x",
+        "webpack-cli": "4.x.x"
+      }
+    },
+    "node_modules/@webpack-cli/info": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz",
+      "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==",
+      "license": "MIT",
+      "dependencies": {
+        "envinfo": "^7.7.3"
+      },
+      "peerDependencies": {
+        "webpack-cli": "4.x.x"
+      }
+    },
+    "node_modules/@webpack-cli/serve": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz",
+      "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==",
+      "license": "MIT",
+      "peerDependencies": {
+        "webpack-cli": "4.x.x"
+      },
+      "peerDependenciesMeta": {
+        "webpack-dev-server": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@xtuc/ieee754": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+      "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+      "license": "BSD-3-Clause"
+    },
+    "node_modules/@xtuc/long": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+      "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+      "license": "Apache-2.0"
+    },
+    "node_modules/accepts": {
+      "version": "1.3.8",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+      "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+      "license": "MIT",
+      "dependencies": {
+        "mime-types": "~2.1.34",
+        "negotiator": "0.6.3"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/acorn": {
+      "version": "8.12.1",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
+      "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
+      "license": "MIT",
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/acorn-import-assertions": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz",
+      "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==",
+      "license": "MIT",
+      "peerDependencies": {
+        "acorn": "^8"
+      }
+    },
+    "node_modules/ajv": {
+      "version": "6.12.6",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+      "license": "MIT",
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/ajv-keywords": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+      "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+      "license": "MIT",
+      "peerDependencies": {
+        "ajv": "^6.9.1"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/anymatch": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+      "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/array-flatten": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+      "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+      "license": "MIT"
+    },
+    "node_modules/babel-loader": {
+      "version": "8.2.5",
+      "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.5.tgz",
+      "integrity": "sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ==",
+      "license": "MIT",
+      "dependencies": {
+        "find-cache-dir": "^3.3.1",
+        "loader-utils": "^2.0.0",
+        "make-dir": "^3.1.0",
+        "schema-utils": "^2.6.5"
+      },
+      "engines": {
+        "node": ">= 8.9"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0",
+        "webpack": ">=2"
+      }
+    },
+    "node_modules/babel-loader/node_modules/make-dir": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+      "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+      "license": "MIT",
+      "dependencies": {
+        "semver": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "license": "MIT"
+    },
+    "node_modules/big.js": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+      "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+      "license": "MIT",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/binary-extensions": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+      "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/body-parser": {
+      "version": "1.20.0",
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
+      "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
+      "license": "MIT",
+      "dependencies": {
+        "bytes": "3.1.2",
+        "content-type": "~1.0.4",
+        "debug": "2.6.9",
+        "depd": "2.0.0",
+        "destroy": "1.2.0",
+        "http-errors": "2.0.0",
+        "iconv-lite": "0.4.24",
+        "on-finished": "2.4.1",
+        "qs": "6.10.3",
+        "raw-body": "2.5.1",
+        "type-is": "~1.6.18",
+        "unpipe": "1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8",
+        "npm": "1.2.8000 || >= 1.4.16"
+      }
+    },
+    "node_modules/body-parser/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "license": "MIT",
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/body-parser/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "license": "MIT"
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/braces": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "fill-range": "^7.1.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/browserslist": {
+      "version": "4.23.2",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz",
+      "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "caniuse-lite": "^1.0.30001640",
+        "electron-to-chromium": "^1.4.820",
+        "node-releases": "^2.0.14",
+        "update-browserslist-db": "^1.1.0"
+      },
+      "bin": {
+        "browserslist": "cli.js"
+      },
+      "engines": {
+        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+      }
+    },
+    "node_modules/buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+      "license": "MIT"
+    },
+    "node_modules/buffer-writer": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
+      "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/bytes": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+      "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/call-bind": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+      "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
+      "license": "MIT",
+      "dependencies": {
+        "es-define-property": "^1.0.0",
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2",
+        "get-intrinsic": "^1.2.4",
+        "set-function-length": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/caniuse-lite": {
+      "version": "1.0.30001643",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz",
+      "integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "CC-BY-4.0"
+    },
+    "node_modules/chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/chokidar": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+      "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "anymatch": "~3.1.2",
+        "braces": "~3.0.2",
+        "glob-parent": "~5.1.2",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.6.0"
+      },
+      "engines": {
+        "node": ">= 8.10.0"
+      },
+      "funding": {
+        "url": "https://paulmillr.com/funding/"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/chrome-trace-event": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
+      "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.0"
+      }
+    },
+    "node_modules/clone-deep": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+      "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+      "license": "MIT",
+      "dependencies": {
+        "is-plain-object": "^2.0.4",
+        "kind-of": "^6.0.2",
+        "shallow-clone": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+      "license": "MIT"
+    },
+    "node_modules/colorette": {
+      "version": "2.0.20",
+      "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
+      "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
+      "license": "MIT"
+    },
+    "node_modules/commander": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+      "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/commondir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+      "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
+      "license": "MIT"
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+      "license": "MIT"
+    },
+    "node_modules/content-disposition": {
+      "version": "0.5.4",
+      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+      "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+      "license": "MIT",
+      "dependencies": {
+        "safe-buffer": "5.2.1"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/content-type": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+      "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/convert-source-map": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+      "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
+      "license": "MIT"
+    },
+    "node_modules/cookie": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
+      "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/cookie-signature": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+      "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
+      "license": "MIT"
+    },
+    "node_modules/cross-spawn": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+      "license": "MIT",
+      "dependencies": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/css-loader": {
+      "version": "6.7.1",
+      "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz",
+      "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==",
+      "license": "MIT",
+      "dependencies": {
+        "icss-utils": "^5.1.0",
+        "postcss": "^8.4.7",
+        "postcss-modules-extract-imports": "^3.0.0",
+        "postcss-modules-local-by-default": "^4.0.0",
+        "postcss-modules-scope": "^3.0.0",
+        "postcss-modules-values": "^4.0.0",
+        "postcss-value-parser": "^4.2.0",
+        "semver": "^7.3.5"
+      },
+      "engines": {
+        "node": ">= 12.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "webpack": "^5.0.0"
+      }
+    },
+    "node_modules/css-loader/node_modules/semver": {
+      "version": "7.6.3",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+      "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/cssesc": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+      "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+      "license": "MIT",
+      "bin": {
+        "cssesc": "bin/cssesc"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/csstype": {
+      "version": "2.6.21",
+      "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz",
+      "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==",
+      "license": "MIT"
+    },
+    "node_modules/debug": {
+      "version": "4.3.6",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
+      "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
+      "license": "MIT",
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/define-data-property": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+      "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+      "license": "MIT",
+      "dependencies": {
+        "es-define-property": "^1.0.0",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/depd": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+      "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/destroy": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+      "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8",
+        "npm": "1.2.8000 || >= 1.4.16"
+      }
+    },
+    "node_modules/ee-first": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+      "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+      "license": "MIT"
+    },
+    "node_modules/electron-to-chromium": {
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.2.tgz",
+      "integrity": "sha512-kc4r3U3V3WLaaZqThjYz/Y6z8tJe+7K0bbjUVo3i+LWIypVdMx5nXCkwRe6SWbY6ILqLdc1rKcKmr3HoH7wjSQ==",
+      "license": "ISC"
+    },
+    "node_modules/emojis-list": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+      "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/encodeurl": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+      "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/enhanced-resolve": {
+      "version": "5.17.1",
+      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
+      "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
+      "license": "MIT",
+      "dependencies": {
+        "graceful-fs": "^4.2.4",
+        "tapable": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/envinfo": {
+      "version": "7.13.0",
+      "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz",
+      "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==",
+      "license": "MIT",
+      "bin": {
+        "envinfo": "dist/cli.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/es-define-property": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+      "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+      "license": "MIT",
+      "dependencies": {
+        "get-intrinsic": "^1.2.4"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-errors": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-module-lexer": {
+      "version": "0.9.3",
+      "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz",
+      "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==",
+      "license": "MIT"
+    },
+    "node_modules/es6-promise": {
+      "version": "4.2.8",
+      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
+      "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
+      "license": "MIT"
+    },
+    "node_modules/escalade": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
+      "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+      "license": "MIT"
+    },
+    "node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/eslint-scope": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+      "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "esrecurse": "^4.3.0",
+        "estraverse": "^4.1.1"
+      },
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/esrecurse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/esrecurse/node_modules/estraverse": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/estraverse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+      "license": "MIT"
+    },
+    "node_modules/etag": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+      "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/events": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+      "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.8.x"
+      }
+    },
+    "node_modules/express": {
+      "version": "4.18.1",
+      "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
+      "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
+      "license": "MIT",
+      "dependencies": {
+        "accepts": "~1.3.8",
+        "array-flatten": "1.1.1",
+        "body-parser": "1.20.0",
+        "content-disposition": "0.5.4",
+        "content-type": "~1.0.4",
+        "cookie": "0.5.0",
+        "cookie-signature": "1.0.6",
+        "debug": "2.6.9",
+        "depd": "2.0.0",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "finalhandler": "1.2.0",
+        "fresh": "0.5.2",
+        "http-errors": "2.0.0",
+        "merge-descriptors": "1.0.1",
+        "methods": "~1.1.2",
+        "on-finished": "2.4.1",
+        "parseurl": "~1.3.3",
+        "path-to-regexp": "0.1.7",
+        "proxy-addr": "~2.0.7",
+        "qs": "6.10.3",
+        "range-parser": "~1.2.1",
+        "safe-buffer": "5.2.1",
+        "send": "0.18.0",
+        "serve-static": "1.15.0",
+        "setprototypeof": "1.2.0",
+        "statuses": "2.0.1",
+        "type-is": "~1.6.18",
+        "utils-merge": "1.0.1",
+        "vary": "~1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.10.0"
+      }
+    },
+    "node_modules/express-http-proxy": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/express-http-proxy/-/express-http-proxy-2.0.0.tgz",
+      "integrity": "sha512-TXxcPFTWVUMSEmyM6iX2sT/JtmqhqngTq29P+eXTVFdtxZrTmM8THUYK59rUXiln0FfPGvxEpGRnVrgvHksXDw==",
+      "license": "MIT",
+      "dependencies": {
+        "debug": "^3.0.1",
+        "es6-promise": "^4.1.1",
+        "raw-body": "^2.3.0"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/express-http-proxy/node_modules/debug": {
+      "version": "3.2.7",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+      "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+      "license": "MIT",
+      "dependencies": {
+        "ms": "^2.1.1"
+      }
+    },
+    "node_modules/express/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "license": "MIT",
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/express/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "license": "MIT"
+    },
+    "node_modules/fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+      "license": "MIT"
+    },
+    "node_modules/fast-json-stable-stringify": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+      "license": "MIT"
+    },
+    "node_modules/fastest-levenshtein": {
+      "version": "1.0.16",
+      "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
+      "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4.9.1"
+      }
+    },
+    "node_modules/file-loader": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz",
+      "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==",
+      "license": "MIT",
+      "dependencies": {
+        "loader-utils": "^2.0.0",
+        "schema-utils": "^3.0.0"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "webpack": "^4.0.0 || ^5.0.0"
+      }
+    },
+    "node_modules/file-loader/node_modules/schema-utils": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+      "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/json-schema": "^7.0.8",
+        "ajv": "^6.12.5",
+        "ajv-keywords": "^3.5.2"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      }
+    },
+    "node_modules/fill-range": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "to-regex-range": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/finalhandler": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
+      "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
+      "license": "MIT",
+      "dependencies": {
+        "debug": "2.6.9",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "on-finished": "2.4.1",
+        "parseurl": "~1.3.3",
+        "statuses": "2.0.1",
+        "unpipe": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/finalhandler/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "license": "MIT",
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/finalhandler/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "license": "MIT"
+    },
+    "node_modules/find-cache-dir": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
+      "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
+      "license": "MIT",
+      "dependencies": {
+        "commondir": "^1.0.1",
+        "make-dir": "^3.0.2",
+        "pkg-dir": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/avajs/find-cache-dir?sponsor=1"
+      }
+    },
+    "node_modules/find-cache-dir/node_modules/make-dir": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+      "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+      "license": "MIT",
+      "dependencies": {
+        "semver": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "license": "MIT",
+      "dependencies": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/flat": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+      "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+      "license": "BSD-3-Clause",
+      "bin": {
+        "flat": "cli.js"
+      }
+    },
+    "node_modules/forwarded": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+      "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/fresh": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+      "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/fs": {
+      "version": "0.0.1-security",
+      "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
+      "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==",
+      "license": "ISC"
+    },
+    "node_modules/fs-readdir-recursive": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
+      "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==",
+      "license": "MIT"
+    },
+    "node_modules/fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+      "license": "ISC"
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/gensync": {
+      "version": "1.0.0-beta.2",
+      "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/get-intrinsic": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+      "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2",
+        "has-proto": "^1.0.1",
+        "has-symbols": "^1.0.3",
+        "hasown": "^2.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/glob": {
+      "version": "7.2.3",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+      "deprecated": "Glob versions prior to v9 are no longer supported",
+      "license": "ISC",
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.1.1",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "is-glob": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/glob-to-regexp": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+      "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+      "license": "BSD-2-Clause"
+    },
+    "node_modules/globals": {
+      "version": "11.12.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+      "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/gopd": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+      "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+      "license": "MIT",
+      "dependencies": {
+        "get-intrinsic": "^1.1.3"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+      "license": "ISC"
+    },
+    "node_modules/has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/has-property-descriptors": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+      "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+      "license": "MIT",
+      "dependencies": {
+        "es-define-property": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-proto": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
+      "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-symbols": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+      "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/hash-sum": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz",
+      "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==",
+      "license": "MIT"
+    },
+    "node_modules/hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "license": "MIT",
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/http-errors": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+      "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+      "license": "MIT",
+      "dependencies": {
+        "depd": "2.0.0",
+        "inherits": "2.0.4",
+        "setprototypeof": "1.2.0",
+        "statuses": "2.0.1",
+        "toidentifier": "1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/iconv-lite": {
+      "version": "0.4.24",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+      "license": "MIT",
+      "dependencies": {
+        "safer-buffer": ">= 2.1.2 < 3"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/icss-utils": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
+      "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
+      "license": "ISC",
+      "engines": {
+        "node": "^10 || ^12 || >= 14"
+      },
+      "peerDependencies": {
+        "postcss": "^8.1.0"
+      }
+    },
+    "node_modules/import-local": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
+      "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
+      "license": "MIT",
+      "dependencies": {
+        "pkg-dir": "^4.2.0",
+        "resolve-cwd": "^3.0.0"
+      },
+      "bin": {
+        "import-local-fixture": "fixtures/cli.js"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+      "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+      "license": "ISC",
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "license": "ISC"
+    },
+    "node_modules/interpret": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz",
+      "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/ipaddr.js": {
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+      "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "binary-extensions": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-core-module": {
+      "version": "2.15.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz",
+      "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==",
+      "license": "MIT",
+      "dependencies": {
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/is-plain-object": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+      "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+      "license": "MIT",
+      "dependencies": {
+        "isobject": "^3.0.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+      "license": "ISC"
+    },
+    "node_modules/isobject": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+      "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/jest-worker": {
+      "version": "27.5.1",
+      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
+      "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/node": "*",
+        "merge-stream": "^2.0.0",
+        "supports-color": "^8.0.0"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      }
+    },
+    "node_modules/jest-worker/node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/jest-worker/node_modules/supports-color": {
+      "version": "8.1.1",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+      "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+      "license": "MIT",
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/supports-color?sponsor=1"
+      }
+    },
+    "node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "license": "MIT"
+    },
+    "node_modules/jsesc": {
+      "version": "2.5.2",
+      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+      "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+      "license": "MIT",
+      "bin": {
+        "jsesc": "bin/jsesc"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/json-parse-even-better-errors": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+      "license": "MIT"
+    },
+    "node_modules/json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+      "license": "MIT"
+    },
+    "node_modules/json5": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+      "license": "MIT",
+      "bin": {
+        "json5": "lib/cli.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/kind-of": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/loader-runner": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
+      "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.11.5"
+      }
+    },
+    "node_modules/loader-utils": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+      "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+      "license": "MIT",
+      "dependencies": {
+        "big.js": "^5.2.2",
+        "emojis-list": "^3.0.0",
+        "json5": "^2.1.2"
+      },
+      "engines": {
+        "node": ">=8.9.0"
+      }
+    },
+    "node_modules/locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "license": "MIT",
+      "dependencies": {
+        "p-locate": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/lru-cache": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+      "license": "ISC",
+      "dependencies": {
+        "yallist": "^3.0.2"
+      }
+    },
+    "node_modules/magic-string": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
+      "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
+      "license": "MIT",
+      "dependencies": {
+        "sourcemap-codec": "^1.4.8"
+      }
+    },
+    "node_modules/make-dir": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+      "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+      "license": "MIT",
+      "dependencies": {
+        "pify": "^4.0.1",
+        "semver": "^5.6.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/make-dir/node_modules/semver": {
+      "version": "5.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver"
+      }
+    },
+    "node_modules/media-typer": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+      "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/merge-descriptors": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+      "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
+      "license": "MIT"
+    },
+    "node_modules/merge-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+      "license": "MIT"
+    },
+    "node_modules/methods": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+      "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "license": "MIT",
+      "bin": {
+        "mime": "cli.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "license": "MIT",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/minimist": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "license": "MIT"
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.7",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+      "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/negotiator": {
+      "version": "0.6.3",
+      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+      "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/neo-async": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+      "license": "MIT"
+    },
+    "node_modules/new-line": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/new-line/-/new-line-1.1.1.tgz",
+      "integrity": "sha512-BHhU5J48wv56aU2DaYnR0brR7PDTaJOeZW/R1koEt03ygvmX/WDnsXsxAq4JLK15vJeP4HHQHBGCfg3npp7onQ==",
+      "license": "MIT"
+    },
+    "node_modules/node-releases": {
+      "version": "2.0.18",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
+      "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
+      "license": "MIT"
+    },
+    "node_modules/normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/object-inspect": {
+      "version": "1.13.2",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
+      "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/on-finished": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+      "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+      "license": "MIT",
+      "dependencies": {
+        "ee-first": "1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+      "license": "ISC",
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "license": "MIT",
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "license": "MIT",
+      "dependencies": {
+        "p-limit": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/packet-reader": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
+      "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==",
+      "license": "MIT"
+    },
+    "node_modules/parseurl": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/path-key": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+      "license": "MIT"
+    },
+    "node_modules/path-to-regexp": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+      "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
+      "license": "MIT"
+    },
+    "node_modules/pg": {
+      "version": "8.8.0",
+      "resolved": "https://registry.npmjs.org/pg/-/pg-8.8.0.tgz",
+      "integrity": "sha512-UXYN0ziKj+AeNNP7VDMwrehpACThH7LUl/p8TDFpEUuSejCUIwGSfxpHsPvtM6/WXFy6SU4E5RG4IJV/TZAGjw==",
+      "license": "MIT",
+      "dependencies": {
+        "buffer-writer": "2.0.0",
+        "packet-reader": "1.0.0",
+        "pg-connection-string": "^2.5.0",
+        "pg-pool": "^3.5.2",
+        "pg-protocol": "^1.5.0",
+        "pg-types": "^2.1.0",
+        "pgpass": "1.x"
+      },
+      "engines": {
+        "node": ">= 8.0.0"
+      },
+      "peerDependencies": {
+        "pg-native": ">=3.0.1"
+      },
+      "peerDependenciesMeta": {
+        "pg-native": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/pg-connection-string": {
+      "version": "2.6.4",
+      "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.4.tgz",
+      "integrity": "sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==",
+      "license": "MIT"
+    },
+    "node_modules/pg-int8": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
+      "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
+      "license": "ISC",
+      "engines": {
+        "node": ">=4.0.0"
+      }
+    },
+    "node_modules/pg-pool": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.2.tgz",
+      "integrity": "sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==",
+      "license": "MIT",
+      "peerDependencies": {
+        "pg": ">=8.0"
+      }
+    },
+    "node_modules/pg-protocol": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.1.tgz",
+      "integrity": "sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==",
+      "license": "MIT"
+    },
+    "node_modules/pg-types": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
+      "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
+      "license": "MIT",
+      "dependencies": {
+        "pg-int8": "1.0.1",
+        "postgres-array": "~2.0.0",
+        "postgres-bytea": "~1.0.0",
+        "postgres-date": "~1.0.4",
+        "postgres-interval": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/pgpass": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
+      "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
+      "license": "MIT",
+      "dependencies": {
+        "split2": "^4.1.0"
+      }
+    },
+    "node_modules/picocolors": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
+      "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
+      "license": "ISC"
+    },
+    "node_modules/picomatch": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=8.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/pify": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+      "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/pkg-dir": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+      "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+      "license": "MIT",
+      "dependencies": {
+        "find-up": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/postcss": {
+      "version": "8.4.40",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz",
+      "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "nanoid": "^3.3.7",
+        "picocolors": "^1.0.1",
+        "source-map-js": "^1.2.0"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/postcss-modules-extract-imports": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz",
+      "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==",
+      "license": "ISC",
+      "engines": {
+        "node": "^10 || ^12 || >= 14"
+      },
+      "peerDependencies": {
+        "postcss": "^8.1.0"
+      }
+    },
+    "node_modules/postcss-modules-local-by-default": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz",
+      "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==",
+      "license": "MIT",
+      "dependencies": {
+        "icss-utils": "^5.0.0",
+        "postcss-selector-parser": "^6.0.2",
+        "postcss-value-parser": "^4.1.0"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >= 14"
+      },
+      "peerDependencies": {
+        "postcss": "^8.1.0"
+      }
+    },
+    "node_modules/postcss-modules-scope": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz",
+      "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==",
+      "license": "ISC",
+      "dependencies": {
+        "postcss-selector-parser": "^6.0.4"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >= 14"
+      },
+      "peerDependencies": {
+        "postcss": "^8.1.0"
+      }
+    },
+    "node_modules/postcss-modules-values": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz",
+      "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==",
+      "license": "ISC",
+      "dependencies": {
+        "icss-utils": "^5.0.0"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >= 14"
+      },
+      "peerDependencies": {
+        "postcss": "^8.1.0"
+      }
+    },
+    "node_modules/postcss-selector-parser": {
+      "version": "6.1.1",
+      "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz",
+      "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==",
+      "license": "MIT",
+      "dependencies": {
+        "cssesc": "^3.0.0",
+        "util-deprecate": "^1.0.2"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/postcss-value-parser": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+      "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+      "license": "MIT"
+    },
+    "node_modules/postgres-array": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
+      "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/postgres-bytea": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
+      "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/postgres-date": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
+      "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/postgres-interval": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
+      "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
+      "license": "MIT",
+      "dependencies": {
+        "xtend": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/proxy-addr": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+      "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+      "license": "MIT",
+      "dependencies": {
+        "forwarded": "0.2.0",
+        "ipaddr.js": "1.9.1"
+      },
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/punycode": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+      "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/qs": {
+      "version": "6.10.3",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
+      "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "side-channel": "^1.0.4"
+      },
+      "engines": {
+        "node": ">=0.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/randombytes": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+      "license": "MIT",
+      "dependencies": {
+        "safe-buffer": "^5.1.0"
+      }
+    },
+    "node_modules/range-parser": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/raw-body": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
+      "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
+      "license": "MIT",
+      "dependencies": {
+        "bytes": "3.1.2",
+        "http-errors": "2.0.0",
+        "iconv-lite": "0.4.24",
+        "unpipe": "1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/readdirp": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "picomatch": "^2.2.1"
+      },
+      "engines": {
+        "node": ">=8.10.0"
+      }
+    },
+    "node_modules/rechoir": {
+      "version": "0.7.1",
+      "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
+      "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==",
+      "license": "MIT",
+      "dependencies": {
+        "resolve": "^1.9.0"
+      },
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/resolve": {
+      "version": "1.22.8",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+      "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+      "license": "MIT",
+      "dependencies": {
+        "is-core-module": "^2.13.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      },
+      "bin": {
+        "resolve": "bin/resolve"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/resolve-cwd": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+      "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+      "license": "MIT",
+      "dependencies": {
+        "resolve-from": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "license": "MIT"
+    },
+    "node_modules/safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "license": "MIT"
+    },
+    "node_modules/schema-utils": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz",
+      "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/json-schema": "^7.0.5",
+        "ajv": "^6.12.4",
+        "ajv-keywords": "^3.5.2"
+      },
+      "engines": {
+        "node": ">= 8.9.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      }
+    },
+    "node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/send": {
+      "version": "0.18.0",
+      "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
+      "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+      "license": "MIT",
+      "dependencies": {
+        "debug": "2.6.9",
+        "depd": "2.0.0",
+        "destroy": "1.2.0",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "fresh": "0.5.2",
+        "http-errors": "2.0.0",
+        "mime": "1.6.0",
+        "ms": "2.1.3",
+        "on-finished": "2.4.1",
+        "range-parser": "~1.2.1",
+        "statuses": "2.0.1"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/send/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "license": "MIT",
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/send/node_modules/debug/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "license": "MIT"
+    },
+    "node_modules/send/node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "license": "MIT"
+    },
+    "node_modules/serialize-javascript": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
+      "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "randombytes": "^2.1.0"
+      }
+    },
+    "node_modules/serve-static": {
+      "version": "1.15.0",
+      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
+      "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
+      "license": "MIT",
+      "dependencies": {
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "parseurl": "~1.3.3",
+        "send": "0.18.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/set-function-length": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+      "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+      "license": "MIT",
+      "dependencies": {
+        "define-data-property": "^1.1.4",
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2",
+        "get-intrinsic": "^1.2.4",
+        "gopd": "^1.0.1",
+        "has-property-descriptors": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/setprototypeof": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+      "license": "ISC"
+    },
+    "node_modules/shallow-clone": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+      "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+      "license": "MIT",
+      "dependencies": {
+        "kind-of": "^6.0.2"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-command": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "license": "MIT",
+      "dependencies": {
+        "shebang-regex": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/side-channel": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
+      "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
+      "license": "MIT",
+      "dependencies": {
+        "call-bind": "^1.0.7",
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.4",
+        "object-inspect": "^1.13.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/slash": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+      "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
+      "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-support": {
+      "version": "0.5.21",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+      "license": "MIT",
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "node_modules/sourcemap-codec": {
+      "version": "1.4.8",
+      "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+      "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+      "deprecated": "Please use @jridgewell/sourcemap-codec instead",
+      "license": "MIT"
+    },
+    "node_modules/split2": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
+      "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
+      "license": "ISC",
+      "engines": {
+        "node": ">= 10.x"
+      }
+    },
+    "node_modules/statuses": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+      "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "license": "MIT",
+      "dependencies": {
+        "has-flag": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/tapable": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+      "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/terser": {
+      "version": "5.31.3",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz",
+      "integrity": "sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "@jridgewell/source-map": "^0.3.3",
+        "acorn": "^8.8.2",
+        "commander": "^2.20.0",
+        "source-map-support": "~0.5.20"
+      },
+      "bin": {
+        "terser": "bin/terser"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/terser-webpack-plugin": {
+      "version": "5.3.10",
+      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
+      "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/trace-mapping": "^0.3.20",
+        "jest-worker": "^27.4.5",
+        "schema-utils": "^3.1.1",
+        "serialize-javascript": "^6.0.1",
+        "terser": "^5.26.0"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "webpack": "^5.1.0"
+      },
+      "peerDependenciesMeta": {
+        "@swc/core": {
+          "optional": true
+        },
+        "esbuild": {
+          "optional": true
+        },
+        "uglify-js": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/terser-webpack-plugin/node_modules/schema-utils": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+      "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/json-schema": "^7.0.8",
+        "ajv": "^6.12.5",
+        "ajv-keywords": "^3.5.2"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      }
+    },
+    "node_modules/terser/node_modules/commander": {
+      "version": "2.20.3",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+      "license": "MIT"
+    },
+    "node_modules/to-fast-properties": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+      "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "is-number": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=8.0"
+      }
+    },
+    "node_modules/toidentifier": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+      "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.6"
+      }
+    },
+    "node_modules/type-is": {
+      "version": "1.6.18",
+      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+      "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+      "license": "MIT",
+      "dependencies": {
+        "media-typer": "0.3.0",
+        "mime-types": "~2.1.24"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/undici-types": {
+      "version": "6.11.1",
+      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.11.1.tgz",
+      "integrity": "sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==",
+      "license": "MIT"
+    },
+    "node_modules/unpipe": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+      "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/update-browserslist-db": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
+      "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "escalade": "^3.1.2",
+        "picocolors": "^1.0.1"
+      },
+      "bin": {
+        "update-browserslist-db": "cli.js"
+      },
+      "peerDependencies": {
+        "browserslist": ">= 4.21.0"
+      }
+    },
+    "node_modules/uri-js": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "node_modules/url-loader": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz",
+      "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==",
+      "license": "MIT",
+      "dependencies": {
+        "loader-utils": "^2.0.0",
+        "mime-types": "^2.1.27",
+        "schema-utils": "^3.0.0"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "file-loader": "*",
+        "webpack": "^4.0.0 || ^5.0.0"
+      },
+      "peerDependenciesMeta": {
+        "file-loader": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/url-loader/node_modules/schema-utils": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+      "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/json-schema": "^7.0.8",
+        "ajv": "^6.12.5",
+        "ajv-keywords": "^3.5.2"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      }
+    },
+    "node_modules/util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+      "license": "MIT"
+    },
+    "node_modules/utils-merge": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+      "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/vary": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+      "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/vue": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.40.tgz",
+      "integrity": "sha512-1mGHulzUbl2Nk3pfvI5aXYYyJUs1nm4kyvuz38u4xlQkLUn1i2R7nDbI4TufECmY8v1qNBHYy62bCaM+3cHP2A==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-dom": "3.2.40",
+        "@vue/compiler-sfc": "3.2.40",
+        "@vue/runtime-dom": "3.2.40",
+        "@vue/server-renderer": "3.2.40",
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "node_modules/vue-loader": {
+      "version": "17.4.2",
+      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.4.2.tgz",
+      "integrity": "sha512-yTKOA4R/VN4jqjw4y5HrynFL8AK0Z3/Jt7eOJXEitsm0GMRHDBjCfCiuTiLP7OESvsZYo2pATCWhDqxC5ZrM6w==",
+      "license": "MIT",
+      "dependencies": {
+        "chalk": "^4.1.0",
+        "hash-sum": "^2.0.0",
+        "watchpack": "^2.4.0"
+      },
+      "peerDependencies": {
+        "webpack": "^4.1.0 || ^5.0.0-0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/compiler-sfc": {
+          "optional": true
+        },
+        "vue": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-loader/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/vue-loader/node_modules/chalk": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/vue-loader/node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/vue-loader/node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "license": "MIT"
+    },
+    "node_modules/vue-loader/node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/vue-loader/node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "license": "MIT",
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/vue-router": {
+      "version": "4.1.5",
+      "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.5.tgz",
+      "integrity": "sha512-IsvoF5D2GQ/EGTs/Th4NQms9gd2NSqV+yylxIyp/OYp8xOwxmU8Kj/74E9DTSYAyH5LX7idVUngN3JSj1X4xcQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-api": "^6.1.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/posva"
+      },
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
+    "node_modules/vue-style-loader": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
+      "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==",
+      "license": "MIT",
+      "dependencies": {
+        "hash-sum": "^1.0.2",
+        "loader-utils": "^1.0.2"
+      }
+    },
+    "node_modules/vue-style-loader/node_modules/hash-sum": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
+      "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
+      "license": "MIT"
+    },
+    "node_modules/vue-style-loader/node_modules/json5": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+      "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+      "license": "MIT",
+      "dependencies": {
+        "minimist": "^1.2.0"
+      },
+      "bin": {
+        "json5": "lib/cli.js"
+      }
+    },
+    "node_modules/vue-style-loader/node_modules/loader-utils": {
+      "version": "1.4.2",
+      "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
+      "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
+      "license": "MIT",
+      "dependencies": {
+        "big.js": "^5.2.2",
+        "emojis-list": "^3.0.0",
+        "json5": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=4.0.0"
+      }
+    },
+    "node_modules/vue3-sfc-loader": {
+      "version": "0.8.4",
+      "resolved": "https://registry.npmjs.org/vue3-sfc-loader/-/vue3-sfc-loader-0.8.4.tgz",
+      "integrity": "sha512-eziaIrk/N9f9OCpyFEkR6vMsZUHcF5mQslXjffwcb5Iq6EuU74QrlpBeJqA04MvAGT7f5O8la2v9k3NtQnJb3Q==",
+      "license": "MIT"
+    },
+    "node_modules/watchpack": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz",
+      "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==",
+      "license": "MIT",
+      "dependencies": {
+        "glob-to-regexp": "^0.4.1",
+        "graceful-fs": "^4.1.2"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/webpack": {
+      "version": "5.74.0",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz",
+      "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/eslint-scope": "^3.7.3",
+        "@types/estree": "^0.0.51",
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/wasm-edit": "1.11.1",
+        "@webassemblyjs/wasm-parser": "1.11.1",
+        "acorn": "^8.7.1",
+        "acorn-import-assertions": "^1.7.6",
+        "browserslist": "^4.14.5",
+        "chrome-trace-event": "^1.0.2",
+        "enhanced-resolve": "^5.10.0",
+        "es-module-lexer": "^0.9.0",
+        "eslint-scope": "5.1.1",
+        "events": "^3.2.0",
+        "glob-to-regexp": "^0.4.1",
+        "graceful-fs": "^4.2.9",
+        "json-parse-even-better-errors": "^2.3.1",
+        "loader-runner": "^4.2.0",
+        "mime-types": "^2.1.27",
+        "neo-async": "^2.6.2",
+        "schema-utils": "^3.1.0",
+        "tapable": "^2.1.1",
+        "terser-webpack-plugin": "^5.1.3",
+        "watchpack": "^2.4.0",
+        "webpack-sources": "^3.2.3"
+      },
+      "bin": {
+        "webpack": "bin/webpack.js"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependenciesMeta": {
+        "webpack-cli": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/webpack-cli": {
+      "version": "4.10.0",
+      "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz",
+      "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==",
+      "license": "MIT",
+      "dependencies": {
+        "@discoveryjs/json-ext": "^0.5.0",
+        "@webpack-cli/configtest": "^1.2.0",
+        "@webpack-cli/info": "^1.5.0",
+        "@webpack-cli/serve": "^1.7.0",
+        "colorette": "^2.0.14",
+        "commander": "^7.0.0",
+        "cross-spawn": "^7.0.3",
+        "fastest-levenshtein": "^1.0.12",
+        "import-local": "^3.0.2",
+        "interpret": "^2.2.0",
+        "rechoir": "^0.7.0",
+        "webpack-merge": "^5.7.3"
+      },
+      "bin": {
+        "webpack-cli": "bin/cli.js"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "webpack": "4.x.x || 5.x.x"
+      },
+      "peerDependenciesMeta": {
+        "@webpack-cli/generators": {
+          "optional": true
+        },
+        "@webpack-cli/migrate": {
+          "optional": true
+        },
+        "webpack-bundle-analyzer": {
+          "optional": true
+        },
+        "webpack-dev-server": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/webpack-cli/node_modules/commander": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+      "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/webpack-merge": {
+      "version": "5.10.0",
+      "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz",
+      "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==",
+      "license": "MIT",
+      "dependencies": {
+        "clone-deep": "^4.0.1",
+        "flat": "^5.0.2",
+        "wildcard": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
+    "node_modules/webpack-sources": {
+      "version": "3.2.3",
+      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
+      "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/webpack/node_modules/schema-utils": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+      "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/json-schema": "^7.0.8",
+        "ajv": "^6.12.5",
+        "ajv-keywords": "^3.5.2"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      }
+    },
+    "node_modules/which": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "license": "ISC",
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "node-which": "bin/node-which"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/wildcard": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz",
+      "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==",
+      "license": "MIT"
+    },
+    "node_modules/wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+      "license": "ISC"
+    },
+    "node_modules/xtend": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+      "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.4"
+      }
+    },
+    "node_modules/yallist": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "license": "ISC"
+    }
+  }
+}
 
package.json (added)
+++ package.json
@@ -0,0 +1,32 @@
+{
+  "dependencies": {
+    "@babel/cli": "7.19.3",
+    "@babel/core": "7.19.3",
+    "babel-loader": "8.2.5",
+    "css-loader": "6.7.1",
+    "express": "^4.18.1",
+    "express-http-proxy": "^2.0.0",
+    "file-loader": "6.2.0",
+    "fs": "0.0.1-security",
+    "new-line": "^1.1.1",
+    "pg": "8.8.0",
+    "url-loader": "4.1.1",
+    "vue": "3.2.40",
+    "vue-loader": "^17.0.0",
+    "vue-router": "4.1.5",
+    "vue-style-loader": "4.1.3",
+    "vue3-sfc-loader": "^0.8.4",
+    "webpack": "5.74.0",
+    "webpack-cli": "4.10.0"
+  },
+  "scripts": {
+    "prod": "set NODE_ENV=production&&node ./server/modules/web/server.js",
+    "dev": "set NODE_ENV=development&&node ./server/modules/web/server.js",
+    "windows-prod": "set NODE_ENV=production&&node ./server/modules/web/server.js",
+    "windows-dev": "set NODE_ENV=development&&node ./server/modules/web/server.js",
+    "linux-prod": "export NODE_ENV=production&&node ./server/modules/web/server.js",
+    "linux-dev": "export NODE_ENV=development&&node ./server/modules/web/server.js",
+    "webpack-build": "webpack",
+    "webpack-build-watch": "webpack --watch"
+  }
+}
 
server/modules/db/mysql/MysqlConnection.js (added)
+++ server/modules/db/mysql/MysqlConnection.js
@@ -0,0 +1,62 @@
+/**
+ * @author : 최정우
+ * @since : 2022.10.21
+ * @dscription : Mysql DB Connection Pool 생성 관리 모듈 입니다. (private와 public object 환경 구성)
+ */
+ const MysqlConnection = (function () {
+
+    //Mysql DB Connection 라이브러리 모듈
+    const mysql = require('mysql');
+
+    //Connection Pool 객체 - private object(변수)
+    const connectionPool = mysql.createPool({
+        host: 'localhost',
+        user: 'root',
+        password: '1234',
+        database: 'test',
+        ssl: false,
+        port: 3306,
+        max: 10,
+    });
+
+    return {
+        getConnectionPool: function () {
+            return connectionPool;
+        },
+        queryExcute: function (sql, params) {
+            const result = new Promise((resolve, reject) => {
+                connectionPool.getConnection(function (connectionError, connection) {
+                    if (!connectionError) {
+                        try {
+                            connection.query(sql, params, function (queryError, rows, columns) {
+                                if (!queryError) {
+                                    resolve({'rows': rows, 'columns': columns});
+                                } else {
+                                    reject(queryError);
+                                }
+                            })
+                        } catch (proccessError) {
+                            reject(proccessError);
+                        } finally {
+                            connection.release(); 
+                        }
+                    } else {
+                        reject(connectionError);
+                    }
+                })
+
+                /* connectionPool.getConnection().then(async (connection) => {
+                    let queryResult = await connection.query(sql);
+                    resolve(queryResult);
+                    connection.release();
+                }).catch((error) => {
+                    reject(error);
+                }); */
+            })
+            return result;
+        },
+    }
+
+})();
+
+module.exports = MysqlConnection;(파일 끝에 줄바꿈 문자 없음)
 
server/modules/db/oracle/OracleConnection.js (added)
+++ server/modules/db/oracle/OracleConnection.js
@@ -0,0 +1,62 @@
+/**
+ * @author : 방선주
+ * @since : 2022.09.22
+ * @dscription : Oracle DB Connection Pool 생성 관리 모듈 입니다.
+ * 
+ * @modifier : 최정우
+ * @modified : 2022.10.30
+ */
+ const { BASE_DIR } = require('../../../../Global');
+
+ const OracleConnection = function () {
+   //오라클 라이브러리 import
+   const oracledb = require('oracledb');
+   //라이브러리 초기화(oracle client setting)
+   oracledb.initOracleClient({ libDir: `${BASE_DIR}/server/modules/db/oracle/client/client_19.16` });
+ 
+   //DB Connection Pool
+   let connectionPool = null;
+ 
+   //DB Connection Pool 생성
+   oracledb.createPool({
+     user: 'ajin_data',
+     password: 'ajinvldosvl1121',  // myhrpw contains the hr schema password
+     connectString: '(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 211.216.206.147)(PORT = 1521)))(CONNECT_DATA = (SID = XE)))',
+     poolMin: 0,
+     poolMax: 20,
+     //poolAlias: 'ajin_odbcp'//poolAlias가 정의되지 않으면, default pool로 정의됨
+   }).then((result) => {
+     connectionPool = result;
+     console.log("Successfully connected to Oracle Database");
+   }).catch((error) => {
+     console.error(error);
+   });
+ 
+   return {
+     getConnectionPool: function () {
+       return connectionPool;
+     },
+     getConnection: function () {
+       return oracledb.getConnection();
+     },
+     queryExcute: function (sql, params) {
+       const result = new Promise((resolve, reject) => {
+         oracledb.getConnection().then(async (connection) => {
+           let queryResult = null;
+           if (!params) {
+             queryResult = await connection.execute(sql);
+           } else {
+             queryResult = await connection.execute(sql, params);
+           }
+           resolve(queryResult);
+           connection.close();
+         }).catch((error) => {
+           reject(error);
+         });
+       })
+       return result;
+     },
+   }
+ }();
+ 
+ module.exports = OracleConnection;(파일 끝에 줄바꿈 문자 없음)
 
server/modules/db/oracle/client/client_19.16/BASIC_LICENSE (added)
+++ server/modules/db/oracle/client/client_19.16/BASIC_LICENSE
@@ -0,0 +1,123 @@
+Oracle Free Use Terms and Conditions
+
+Definitions
+
+"Oracle" refers to Oracle America, Inc. "You" and "Your" refers to (a)
+a company or organization (each an "Entity") accessing the Programs,
+if use of the Programs will be on behalf of such Entity; or (b) an
+individual accessing the Programs, if use of the Programs will not be
+on behalf of an Entity. "Program(s)" refers to Oracle software
+provided by Oracle pursuant to the following terms and any updates,
+error corrections, and/or Program Documentation provided by
+Oracle. "Program Documentation" refers to Program user manuals and
+Program installation manuals, if any. If available, Program
+Documentation may be delivered with the Programs and/or may be
+accessed from www.oracle.com/documentation. "Separate Terms" refers to
+separate license terms that are specified in the Program
+Documentation, readmes or notice files and that apply to Separately
+Licensed Technology. "Separately Licensed Technology" refers to Oracle
+or third party technology that is licensed under Separate Terms and
+not under the terms of this license.
+
+Separately Licensed Technology
+
+Oracle may provide certain notices to You in Program Documentation,
+readmes or notice files in connection with Oracle or third party
+technology provided as or with the Programs. If specified in the
+Program Documentation, readmes or notice files, such technology will
+be licensed to You under Separate Terms. Your rights to use Separately
+Licensed Technology under Separate Terms are not restricted in any way
+by the terms herein. For clarity, notwithstanding the existence of a
+notice, third party technology that is not Separately Licensed
+Technology shall be deemed part of the Programs licensed to You under
+the terms of this license.
+
+Source Code for Open Source Software
+
+For software that You receive from Oracle in binary form that is
+licensed under an open source license that gives You the right to
+receive the source code for that binary, You can obtain a copy of the
+applicable source code from https://oss.oracle.com/sources/ or
+http://www.oracle.com/goto/opensourcecode. If the source code for such
+software was not provided to You with the binary, You can also receive
+a copy of the source code on physical media by submitting a written
+request pursuant to the instructions in the "Written Offer for Source
+Code" section of the latter website.
+
+-------------------------------------------------------------------------------
+
+The following license terms apply to those Programs that are not
+provided to You under Separate Terms.
+
+License Rights and Restrictions
+
+Oracle grants to You, as a recipient of this Program, a nonexclusive,
+nontransferable, limited license to, subject to the conditions stated
+herein, (a) internally use the unmodified Programs for the purposes of
+developing, testing, prototyping and demonstrating your applications,
+and running the Programs for your own internal business operations;
+and (b) redistribute unmodified Programs and Programs Documentation,
+under the terms of this License, provided that You do not charge Your
+end users any additional fees for the use of the Programs. You may
+make copies of the Programs to the extent reasonably necessary for
+exercising the license rights granted herein and for backup
+purposes. You are granted the right to use the Programs to provide
+third party training in the use of the Programs and associated
+Separately Licensed Technology only if there is express authorization
+of such use by Oracle on the Program's download page or in the Program
+Documentation.
+
+Your license is contingent on Your compliance with the following conditions:
+
+    - You include a copy of this license with any distribution by You
+      of the Programs;
+
+    - You do not remove markings or notices of either Oracle's or a
+      licensor's proprietary rights from the Programs or Program
+      Documentation;
+
+    - You comply with all U.S. and applicable export control and
+      economic sanctions laws and regulations that govern Your use of
+      the Programs (including technical data);
+
+    - You do not cause or permit reverse engineering, disassembly or
+      decompilation of the Programs (except as allowed by law) by You
+      nor allow an associated party to do so.
+
+For clarity, any source code that may be included in the distribution
+with the Programs is provided solely for reference purposes and may
+not be modified, unless such source code is under Separate Terms
+permitting modification.
+
+Ownership
+
+Oracle or its licensors retain all ownership and intellectual property
+rights to the Programs.
+
+Information Collection
+
+The Programs' installation and/or auto-update processes, if any, may
+transmit a limited amount of data to Oracle or its service provider
+about those processes to help Oracle understand and optimize
+them. Oracle does not associate the data with personally identifiable
+information. Refer to Oracle's Privacy Policy at
+www.oracle.com/privacy.
+
+Disclaimer of Warranties; Limitation of Liability
+
+THE PROGRAMS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. ORACLE
+FURTHER DISCLAIMS ALL WARRANTIES, EXPRESS AND IMPLIED, INCLUDING
+WITHOUT LIMITATION, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE, OR NONINFRINGEMENT.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL ORACLE BE LIABLE TO
+YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+Last updated:  8 October 2018
+
 
server/modules/db/oracle/client/client_19.16/BASIC_README (added)
+++ server/modules/db/oracle/client/client_19.16/BASIC_README
@@ -0,0 +1,30 @@
+Basic Package Information 
+========================= 
+Sun Jul 17 14:46:23 MDT 2022
+Client Shared Library 64-bit - 19.16.0.0.0
+
+Windows NT Version V6.2  
+CPU                 : 4 - type 86644 physical cores
+Process Affinity    : 0x0000000000000000
+Memory (Avail/Total): Ph:10181M/16381M, Ph+PgF:12546M/18813M 
+
+
+TIMEZONE INFORMATION
+--------------------
+Operating in ORACLE_HOME environment.
+
+Small timezone file = timezone_32.dat
+Large timezone file = timezlrg_32.dat
+
+LICENSE AGREEMENT
+-----------------------------
+Your use of this copy of Oracle Instant Client software product is subject to, and may not exceed the conditions of use for which you are authorized under one of the following:
+
+(i) the license or cloud services terms that you accepted when you obtained the right to use Oracle Instant Client software; or
+(ii) the license terms that you agreed to when you placed your order with Oracle for an Oracle product containing Oracle Instant Client software; or
+(iii) the Oracle Instant Client software license terms, if any, included with the hardware that you acquired from Oracle; or
+(iv) the Oracle Technology Network License Agreement (which you acknowledge you have read and agree to) available at http://www.oracle.com/technetwork/licenses/distribution-license-152002.html; or, if (i), (ii), (iii), and or (iv) are not applicable, then,
+(v) the Oracle Free Use Terms and Conditions available at BASIC_LICENSE.
+
+Oracle's obligations with respect to your use of the Oracle Instant Client, including, without limitation, obligations to indemnify you, if any, shall only be as set forth in the specific license under which you are authorized and choose to use Oracle Instant Client.
+
 
server/modules/db/oracle/client/client_19.16/adrci.exe (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/adrci.exe
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/adrci.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/adrci.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/genezi.exe (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/genezi.exe
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/genezi.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/genezi.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/oci.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/oci.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/oci.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/oci.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/ocijdbc19.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/ocijdbc19.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/ocijdbc19.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/ocijdbc19.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/ociw32.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/ociw32.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/ociw32.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/ociw32.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/ojdbc8.jar (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/ojdbc8.jar
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/oramysql19.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/oramysql19.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/oramysql19.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/oramysql19.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/orannzsbb19.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/orannzsbb19.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/orannzsbb19.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/orannzsbb19.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/oraocci19.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/oraocci19.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/oraocci19.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/oraocci19.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/oraocci19d.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/oraocci19d.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/oraocci19d.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/oraocci19d.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/oraociei19.dll (added)
+++ server/modules/db/oracle/client/client_19.16/oraociei19.dll
This file is too big to display.
 
server/modules/db/oracle/client/client_19.16/oraociei19.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/oraociei19.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/oraons.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/oraons.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/orasql19.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/orasql19.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/orasql19.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/orasql19.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/ucp.jar (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/ucp.jar
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/uidrvci.exe (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/uidrvci.exe
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/uidrvci.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/uidrvci.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/vc14/oraocci19.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/vc14/oraocci19.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/vc14/oraocci19.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/vc14/oraocci19.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/vc14/oraocci19d.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/vc14/oraocci19d.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/vc14/oraocci19d.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/vc14/oraocci19d.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_19.16/xstreams.jar (Binary) (added)
+++ server/modules/db/oracle/client/client_19.16/xstreams.jar
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/BASIC_LICENSE (added)
+++ server/modules/db/oracle/client/client_21.6/BASIC_LICENSE
@@ -0,0 +1,123 @@
+Oracle Free Use Terms and Conditions
+
+Definitions
+
+"Oracle" refers to Oracle America, Inc. "You" and "Your" refers to (a)
+a company or organization (each an "Entity") accessing the Programs,
+if use of the Programs will be on behalf of such Entity; or (b) an
+individual accessing the Programs, if use of the Programs will not be
+on behalf of an Entity. "Program(s)" refers to Oracle software
+provided by Oracle pursuant to the following terms and any updates,
+error corrections, and/or Program Documentation provided by
+Oracle. "Program Documentation" refers to Program user manuals and
+Program installation manuals, if any. If available, Program
+Documentation may be delivered with the Programs and/or may be
+accessed from www.oracle.com/documentation. "Separate Terms" refers to
+separate license terms that are specified in the Program
+Documentation, readmes or notice files and that apply to Separately
+Licensed Technology. "Separately Licensed Technology" refers to Oracle
+or third party technology that is licensed under Separate Terms and
+not under the terms of this license.
+
+Separately Licensed Technology
+
+Oracle may provide certain notices to You in Program Documentation,
+readmes or notice files in connection with Oracle or third party
+technology provided as or with the Programs. If specified in the
+Program Documentation, readmes or notice files, such technology will
+be licensed to You under Separate Terms. Your rights to use Separately
+Licensed Technology under Separate Terms are not restricted in any way
+by the terms herein. For clarity, notwithstanding the existence of a
+notice, third party technology that is not Separately Licensed
+Technology shall be deemed part of the Programs licensed to You under
+the terms of this license.
+
+Source Code for Open Source Software
+
+For software that You receive from Oracle in binary form that is
+licensed under an open source license that gives You the right to
+receive the source code for that binary, You can obtain a copy of the
+applicable source code from https://oss.oracle.com/sources/ or
+http://www.oracle.com/goto/opensourcecode. If the source code for such
+software was not provided to You with the binary, You can also receive
+a copy of the source code on physical media by submitting a written
+request pursuant to the instructions in the "Written Offer for Source
+Code" section of the latter website.
+
+-------------------------------------------------------------------------------
+
+The following license terms apply to those Programs that are not
+provided to You under Separate Terms.
+
+License Rights and Restrictions
+
+Oracle grants to You, as a recipient of this Program, a nonexclusive,
+nontransferable, limited license to, subject to the conditions stated
+herein, (a) internally use the unmodified Programs for the purposes of
+developing, testing, prototyping and demonstrating your applications,
+and running the Programs for your own internal business operations;
+and (b) redistribute unmodified Programs and Programs Documentation,
+under the terms of this License, provided that You do not charge Your
+end users any additional fees for the use of the Programs. You may
+make copies of the Programs to the extent reasonably necessary for
+exercising the license rights granted herein and for backup
+purposes. You are granted the right to use the Programs to provide
+third party training in the use of the Programs and associated
+Separately Licensed Technology only if there is express authorization
+of such use by Oracle on the Program's download page or in the Program
+Documentation.
+
+Your license is contingent on Your compliance with the following conditions:
+
+    - You include a copy of this license with any distribution by You
+      of the Programs;
+
+    - You do not remove markings or notices of either Oracle's or a
+      licensor's proprietary rights from the Programs or Program
+      Documentation;
+
+    - You comply with all U.S. and applicable export control and
+      economic sanctions laws and regulations that govern Your use of
+      the Programs (including technical data);
+
+    - You do not cause or permit reverse engineering, disassembly or
+      decompilation of the Programs (except as allowed by law) by You
+      nor allow an associated party to do so.
+
+For clarity, any source code that may be included in the distribution
+with the Programs is provided solely for reference purposes and may
+not be modified, unless such source code is under Separate Terms
+permitting modification.
+
+Ownership
+
+Oracle or its licensors retain all ownership and intellectual property
+rights to the Programs.
+
+Information Collection
+
+The Programs' installation and/or auto-update processes, if any, may
+transmit a limited amount of data to Oracle or its service provider
+about those processes to help Oracle understand and optimize
+them. Oracle does not associate the data with personally identifiable
+information. Refer to Oracle's Privacy Policy at
+www.oracle.com/privacy.
+
+Disclaimer of Warranties; Limitation of Liability
+
+THE PROGRAMS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. ORACLE
+FURTHER DISCLAIMS ALL WARRANTIES, EXPRESS AND IMPLIED, INCLUDING
+WITHOUT LIMITATION, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE, OR NONINFRINGEMENT.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL ORACLE BE LIABLE TO
+YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+Last updated:  8 October 2018
+
 
server/modules/db/oracle/client/client_21.6/BASIC_README (added)
+++ server/modules/db/oracle/client/client_21.6/BASIC_README
@@ -0,0 +1,30 @@
+Basic Package Information 
+========================= 
+Fri May 27 02:14:20 MDT 2022
+Client Shared Library 64-bit - 21.6.0.0.0
+
+Windows NT Version V6.3  OS Build 9600
+CPU                 : 4 - type 86644 physical cores
+Process Affinity    : 0x0000000000000000
+Memory (Avail/Total): Ph:10006M/16381M, Ph+PgF:12115M/18813M 
+
+
+TIMEZONE INFORMATION
+--------------------
+Operating in ORACLE_HOME environment.
+
+Small timezone file = timezone_35.dat
+Large timezone file = timezlrg_35.dat
+
+LICENSE AGREEMENT
+-----------------------------
+Your use of this copy of Oracle Instant Client software product is subject to, and may not exceed the conditions of use for which you are authorized under one of the following:
+
+(i) the license or cloud services terms that you accepted when you obtained the right to use Oracle Instant Client software; or
+(ii) the license terms that you agreed to when you placed your order with Oracle for an Oracle product containing Oracle Instant Client software; or
+(iii) the Oracle Instant Client software license terms, if any, included with the hardware that you acquired from Oracle; or
+(iv) the Oracle Technology Network License Agreement (which you acknowledge you have read and agree to) available at http://www.oracle.com/technetwork/licenses/distribution-license-152002.html; or, if (i), (ii), (iii), and or (iv) are not applicable, then,
+(v) the Oracle Free Use Terms and Conditions available at BASIC_LICENSE.
+
+Oracle's obligations with respect to your use of the Oracle Instant Client, including, without limitation, obligations to indemnify you, if any, shall only be as set forth in the specific license under which you are authorized and choose to use Oracle Instant Client.
+
 
server/modules/db/oracle/client/client_21.6/adrci.exe (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/adrci.exe
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/adrci.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/adrci.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/genezi.exe (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/genezi.exe
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/genezi.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/genezi.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/network/admin/README (added)
+++ server/modules/db/oracle/client/client_21.6/network/admin/README
@@ -0,0 +1,9 @@
+============================================================================= 
+This is the default directory for Oracle Network and Oracle Client 
+configuration files. You can place files such as tnsnames.ora, sqlnet.ora 
+and oraaccess.xml in this directory. 
+NOTE: 
+If you set an environment variable TNS_ADMIN to another directory containing 
+configuration files, they will be used instead of the files in this default 
+directory. 
+============================================================================= 
 
server/modules/db/oracle/client/client_21.6/oci.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/oci.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/oci.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/oci.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/ocijdbc21.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/ocijdbc21.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/ocijdbc21.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/ocijdbc21.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/ociw32.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/ociw32.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/ociw32.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/ociw32.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/ojdbc8.jar (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/ojdbc8.jar
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/oramysql.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/oramysql.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/oramysql.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/oramysql.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/orannzsbb.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/orannzsbb.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/orannzsbb.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/orannzsbb.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/oraocci21.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/oraocci21.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/oraocci21.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/oraocci21.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/oraocci21d.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/oraocci21d.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/oraocci21d.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/oraocci21d.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/oraociei.dll (added)
+++ server/modules/db/oracle/client/client_21.6/oraociei.dll
This file is too big to display.
 
server/modules/db/oracle/client/client_21.6/oraociei.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/oraociei.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/orasql.dll (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/orasql.dll
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/orasql.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/orasql.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/ucp.jar (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/ucp.jar
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/uidrvci.exe (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/uidrvci.exe
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/uidrvci.sym (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/uidrvci.sym
Binary file is not shown
 
server/modules/db/oracle/client/client_21.6/xstreams.jar (Binary) (added)
+++ server/modules/db/oracle/client/client_21.6/xstreams.jar
Binary file is not shown
 
server/modules/db/postgresql/PostgresqlConnection.js (added)
+++ server/modules/db/postgresql/PostgresqlConnection.js
@@ -0,0 +1,41 @@
+/**
+ * @author : 최정우
+ * @since : 2022.09.20
+ * @dscription : PostgreSQL DB Connection Pool 생성 관리 모듈 입니다. (private와 public object 환경 구성)
+ */
+const PostgresqlConnection = (function () {
+
+    //PostgreSQL DB Connection 라이브러리 모듈
+    const pg = require('pg');
+
+    //Connection Pool 객체 - private object(변수)
+    const connectionPool = new pg.Pool({
+        //host: 'localhost',
+        host: '192.168.0.250',
+        user: 'test_user',
+        password: '1234',
+        database: 'test_db',
+        ssl: false,
+        port: 5432,
+        max: 10,
+    });
+
+    //public object
+    return {
+        getConnectionPool: function () {
+            return connectionPool;
+        },
+        getConnectionPoolClient: function () {
+            return connectionPool.connect();
+        },
+        queryExcute: function (sql, params) {
+            return connectionPool.query(sql, params);
+        },
+    }
+
+})();
+
+//Module Export
+module.exports = PostgresqlConnection;
+
+
 
server/modules/log/Logger.js (added)
+++ server/modules/log/Logger.js
@@ -0,0 +1,131 @@
+const { LOG_BASE_DIR, SERVICE_STATUS } = require('../../../Global');
+const fs = require('fs');
+const Queue = require('../util/Queue');
+
+/**
+ * @author : 최정우
+ * @since : 2022.09.21
+ * @dscription : Log 생성기 모듈 입니다.
+ */
+const Logger = (function () {
+
+    /* let testInterval = setInterval(() => {
+        const date = new Date();
+        var now = `${date.getFullYear()}.${(date.getMonth()+1)}.${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}.${date.getMilliseconds()}`;
+        console.log('now :', now);
+    }, 1000) */
+
+    //로그 쓰기 전, 대기 저장소
+    const eventQueue = new Queue();
+    //로그 쓰는 중인지 아닌지 상태값
+    let isLogging = false;
+
+    /**
+     * @author : 최정우
+     * @since : 2022.09.21
+     * @dscription : Log 처리
+     */
+    const logging = (message) => {
+        const date = new Date();
+        let year = date.getFullYear();
+        let month = prefixZero((date.getMonth() + 1), 2);
+        let day = prefixZero(date.getDate(), 2);
+        let hour = prefixZero(date.getHours(), 2);
+        let minute = prefixZero(date.getMinutes(), 2);
+        let second = prefixZero(date.getSeconds(), 2);
+        let millisecond = prefixZero(date.getMilliseconds(), 3);
+
+        //로그에 쓰일 정보
+        const logMessage = {
+            message: message,
+            datetime: `${year}.${month}.${day} ${hour}:${minute}:${second}.${millisecond}`,
+            logFolderDir: `${LOG_BASE_DIR}/${year}${month}`,//log 폴더 경로
+            logFileName: `log-${year}${month}${day}.log`//log 파일명
+        }
+
+        //로그 쓰는 중이면, 대기 저장소에 등록
+        if (isLogging == true) {
+            eventQueue.push(logMessage);
+        } else {//로그 쓰는 중이 아니면, 로그 쓰는 중인 상태로 변경 후, 로그 쓰기
+            isLogging = true;
+
+            try {
+                //log 폴더 생성
+                if (!fs.existsSync(logMessage.logFolderDir)) {
+                    fs.mkdirSync(logMessage.logFolderDir, { recursive: true/*재귀적 폴더 생성*/ });
+                }
+
+                //log 파일 Full Path
+                let logFileFullPath = `${logMessage.logFolderDir}/${logMessage.logFileName}`;
+                //log 내용
+                let logContent = `[${logMessage.datetime}] ${logMessage.message}`;
+
+                //log 내용 쓰기
+                writeLogFile(logFileFullPath, logContent);
+            } catch (error) {
+                console.log('logging error : ', error);
+            } finally {
+                isLogging = false;
+            }
+        }
+    }
+
+    /**
+     * @author : 최정우
+     * @since : 2022.09.21
+     * @dscription : Log 내용 쓰기
+     */
+    const writeLogFile = (path, content) => {
+        if (SERVICE_STATUS == 'development') {
+            console.log(content);
+        }
+        
+        //파일 쓰기
+        fs.appendFileSync(path, `${content}\n`, 'utf8');
+
+        //로그 쓰기 저장소에서 로그 메세지 꺼내기
+        let logMessage = eventQueue.pop();
+        //메세지가 존재하면 => Log 내용 쓰기 (재귀 호출)
+        if (logMessage != undefined) {
+            //log 파일 Full Path
+            let logFileFullPath = `${logMessage.logFolderDir}/${logMessage.logFileName}`;
+            //log 내용
+            let logContent = `[${logMessage.datetime}] ${logMessage.message}`;
+            //Log 내용 쓰기 (재귀 호출)
+            writeLogFile(logFileFullPath, logContent);
+        } else {
+            return;
+        }
+    }
+
+    /**
+     * @author : 최정우
+     * @since : 2022.09.21
+     * @dscription : 특정 길이만큼 앞에 '0' 붙이기
+     */
+    const prefixZero = (target, length) => {
+        let zero = '';
+        let suffix = target;
+        let result = '';
+
+        if ((typeof target) === "number") {
+            suffix = target.toString();
+        }
+        if (suffix.length < length) {
+            for (i = 0; i < length - suffix.length; i++) {
+                zero += '0';
+            }
+        }
+        result = zero + suffix;
+        return result;
+    }
+
+
+    return {
+        logging: logging
+    }
+
+})();
+
+//Module Export
+module.exports = Logger;(파일 끝에 줄바꿈 문자 없음)
 
server/modules/util/Queue.js (added)
+++ server/modules/util/Queue.js
@@ -0,0 +1,32 @@
+/**
+ * @author : 최정우
+ * @since : 2022.09.21
+ * @dscription : Queue(선입선출) 자료형 객체 입니다.
+ */
+class Queue {
+    constructor() {
+        this._arr = [];
+    }
+
+    //입력
+    push (item) {
+        this._arr.push(item);
+    }
+
+    //출력 후, 제거
+    pop () {
+        return this._arr.shift();
+    }
+
+    //출력 대기 중인 item return
+    peek () {
+        return this._arr[0];
+    }
+
+    //확인
+    showQueue () {
+        console.log('Queue : ', this._arr);
+    }
+}
+
+module.exports = Queue;(파일 끝에 줄바꿈 문자 없음)
 
server/modules/web/Server.js (added)
+++ server/modules/web/Server.js
@@ -0,0 +1,105 @@
+/**
+ * @author : 하석형
+ * @since : 2023.08.24
+ * @dscription : Express 라이브러리 활용 HTTP Web Server 모듈입니다.
+ */
+const { BASE_DIR, PORT, API_SERVER_HOST } = require('../../../Global');
+const Logger = require('../log/Logger');//Logger(필수)
+
+const express = require('express');
+const webServer = express();
+const expressProxy = require('express-http-proxy');
+
+//파일 시스템 관련 라이브러리
+const FS = require('fs');
+//stream: 특정 자원을 Streaming 하기 위한 라이브러리 => Transform: Streaming 중인 자원의 Data에 Data 수정 및 추가를 지원해주는 객체
+const Transform = require('stream').Transform;
+//Streaming 중인 자원에 새로운 데이터를 stream 공간에 추가하기 위한 라이브러리
+const newLineStream = require('new-line');
+
+/**
+ * @author : 하석형
+ * @since : 2023.08.24
+ * @dscription : HTTP Server start
+ */
+webServer.listen(PORT, function () {
+    Logger.logging(`★★★ Node.js를 활용한 Web Server 구동(Port:${PORT}) ★★★`);
+})
+
+/**
+ * @author : 하석형
+ * @since : 2023.08.24
+ * @dscription : Intercepter 역할을 하는 미들웨어 기능
+ */
+webServer.use(function (request, response, next) {
+    let ip = request.headers['x-forwarded-for'] || request.socket.remoteAddress;
+    Logger.logging(`[HTTP] ${request.url} (Method: ${request.method}, IP: ${ip})`);
+    next();
+});
+
+
+
+/**
+ * @author : 하석형
+ * @since : 2023.08.24
+ * @dscription : ROOT URL -> index.html
+ */
+webServer.get('/', function (request, response) {
+    //response.sendFile을 통한 HTTP html reponse (html내용 Streaming)
+    response.sendFile(`${BASE_DIR}/client/views/index.html`);
+})
+
+/**
+ * @author : 하석형
+ * @since : 2023.08.24
+ * @dscription : 화면요청 URL 처리
+ */
+webServer.get('*.page', function (request, response, next) {
+    //index.html 내용을 직접 Streaming하여 Response, Streaming 중간에 내용 수정
+    //수정 내용 : URL 요청이 아닌, 브라우저에 표시된 URL만 변경하여, 해당하는 URL PATH의 Vue Component를 routing하기 위함
+    const StreamTransform = new Transform();
+    StreamTransform._transform = function (data, encoding, done) {
+        let fileContent = data.toString();
+        let replaceBeforeContent = `<script id="app-start-vue-page">const APP_USER_HTTP_REQUEST_URL = '/';</script>`;
+        let replaceAfterContent = `<script id="app-start-vue-page">const APP_USER_HTTP_REQUEST_URL = '${request.params['0']}.page';</script>`;
+        fileContent.replace(replaceBeforeContent, replaceAfterContent);
+        this.push(fileContent);
+        done();
+    }
+    //Streaming 진행
+    FS.createReadStream(`${BASE_DIR}/client/views/index.html`).pipe(newLineStream()).pipe(StreamTransform).pipe(response);
+})
+
+/**
+ * @author : 하석형
+ * @since : 2023.08.24
+ * @dscription : REST API 서버에 데이터 요청 보내기(Proxy)
+ */
+webServer.use('*.json', expressProxy(API_SERVER_HOST, {
+    proxyReqPathResolver: function (request) {
+        //console.log('request : ', request.url, request.params[0]);
+        return `${request.params['0']}.json`;
+    }
+}));
+
+/**
+ * @author : 하석형
+ * @since : 2023.08.24
+ * @dscription : ROOT URL, Router's, 화면요청 URL 등.. 이 외 나머지 정적 자원에 대한 처리 기능
+ */
+webServer.get('*.*', function (request, response, next) {
+    response.sendFile(`${BASE_DIR}${request.params['0']}.${request.params['1']}`);
+})
+
+/**
+ * @author : 하석형
+ * @since : 2023.08.24
+ * @dscription : Global Error Handler (*맨 마지막에 적용해야됨)
+ */
+webServer.use(function (error, request, response, next) {
+    const errorCode = !error.statusCode ? 500 : error.statusCode;
+    response.status(errorCode).send('에러가 발생하였습니다. 관리자에게 문의바랍니다.');
+    let message = `[Error:${errorCode}] ${request.url}/n ${error.stack}/n`;
+    Logger.logging(message);
+    //next();
+})(파일 끝에 줄바꿈 문자 없음)
 
server/service/test/model/TestDAO.js (added)
+++ server/service/test/model/TestDAO.js
@@ -0,0 +1,190 @@
+/**
+ * @author : 최정우
+ * @since : 2022.09.20
+ * @dscription : 테스트용 DB 접근을 담당하는 모듈 입니다.
+ */
+ const TestDAO = (function () {
+
+    //PostgreSQL DB Connection 객체 - private object(변수)
+    const PostgresqlConnection = require('../../../modules/db/postgresql/PostgresqlConnection');
+    //console.log('PostgresqlConnection : ', PostgresqlConnection);
+    const connectionPool = PostgresqlConnection.getConnectionPool();
+
+    //public object
+    return {
+
+        /**
+         * @author : 최정우
+         * @since : 2022.09.20
+         * @dscription : 테스트 데이터 목록 조회
+         */
+        testSelectList: function (param) {
+            return connectionPool.query('SELECT * FROM test_schema.test_table');
+        },
+
+        /**
+         * @author : 최정우
+         * @since : 2022.09.20
+         * @dscription : 테스트 데이터 상세 조회
+         */
+        testSelectOne: function (param) {
+            return connectionPool.query('SELECT * FROM test_schema.test_table WHERE test_seq = $1', param);
+        },
+
+        /**
+         * @author : 최정우
+         * @since : 2022.09.20
+         * @dscription : 테스트 데이터 등록
+         */
+        testInsertOne: function (param) {
+            return connectionPool.query(
+                //RETURNING <*||COLUMN NAME1,COLUMN NAME2,...> : 등록한 Data return 받는 기능
+                //ex1) RETURNING * : 모든 컬럼 다 return 함
+                //ex2) RETURNING name : 컬럼명이 'name'인 데이터만 return 함
+                `INSERT INTO test_schema.test_table (
+                    test_seq
+                    , test_title
+                    , test_content
+                    , test_create_datetime
+                    , test_create_user
+                ) VALUES (
+                    (SELECT COALESCE(MAX(test_seq), 0) + 1 FROM test_schema.test_table)
+                    , $1
+                    , $2
+                    , current_timestamp
+                    , 1
+                ) RETURNING test_seq`,
+                param
+            );
+        },
+
+        /**
+         * @author : 최정우
+         * @since : 2022.09.20
+         * @dscription : 테스트 데이터 수정
+         */
+        testUpdateOne: function (param) {
+            return connectionPool.query(
+                `UPDATE
+                    test_schema.test_table
+                SET 
+                    test_title = $2
+                    , test_content = $3
+                    , test_update_datetime = current_timestamp
+                    , test_update_user = 1
+                WHERE
+                    test_seq = $1`,
+                param
+            );
+        },
+
+        /**
+         * @author : 최정우
+         * @since : 2022.09.20
+         * @dscription : 테스트 데이터 삭제
+         */
+        testDeleteOne: function (param) {
+            return connectionPool.query(
+                `DELETE
+                FROM
+                    test_schema.test_table
+                WHERE
+                    test_seq = $1`,
+                param
+            );
+        },
+
+
+        /**
+         * @author : 최정우
+         * @since : 2022.09.20
+         * @dscription : 테스트 트랜젝션 처리
+         * 
+         * 트랜잭션 작업 진행 시나리오
+         *  1. connection pool 한 개 받아오기
+         *  2. BEGIN(트랜잭션 시작 처리)
+         *  3. [※작업내용1] 데이터 등록
+         *  4. [※작업내용2] 등록한 데이터 수정
+         *  5. *작업 완료시, 실행(dispatch)한 모든 쿼리를 COMMIT(커밋)
+         *     *에러 발생시, 실행(dispatch)한 모든 쿼리를 ROLLBACK(롤백)
+         *  6. 받아온 connection pool 반납(해제) - 필수(반납하지 않으면 해당 pool을 사용하는 query는 트랜잭션에 계속 매달려있음)
+         */
+         testTransaction: function (param) {
+            return new Promise((resolve, reject) => {
+                //1. connection pool 한 개 받아오기
+                const poolClient = PostgresqlConnection.getConnectionPoolClient();
+                poolClient.then(async(client) => {//async 처리
+                    try {
+                        //2. BEGIN(트랜잭션 시작 처리)
+                        await client.query('BEGIN');
+
+                        //처리 3초 지연
+                        //await client.query('SELECT pg_sleep(3);');
+
+                        //3. [※작업내용1] 데이터 등록
+                        let insertResultData = await client.query(
+                            `INSERT INTO test_schema.test_table (
+                                test_seq
+                                , test_title
+                                , test_content
+                                , test_create_datetime
+                                , test_create_user
+                            ) VALUES (
+                                (SELECT COALESCE(MAX(test_seq), 0) + 1 FROM test_schema.test_table)
+                                , $1
+                                , $2
+                                , current_timestamp
+                                , 1
+                            ) RETURNING test_seq`,
+                            param
+                        );
+                        //console.log('등록 결과 정보 insertResultData : ', insertResultData);
+
+                        //throw '트랜잭션 처리중 Error 강제로 발생시킴';
+
+                        //4. [※작업내용2] 등록한 데이터 수정
+                        let updateResultData = await client.query(
+                            `UPDATE
+                                test_schema.test_table
+                            SET 
+                                test_title = 'title transaction update'
+                                , test_content = 'content transaction update'
+                                , test_update_datetime = current_timestamp 1231ㄱㄹㅇㄴ
+                                , test_update_user = 1
+                            WHERE
+                                test_seq = ${insertResultData.rows[0].test_seq}`
+                        );
+                        //console.log('수정 결과 정보 updateResultData : ', updateResultData);
+
+                        throw '트랜잭션 처리중 Error 강제로 발생시킴';
+
+                        //5. *작업 완료시, 실행(dispatch)한 모든 쿼리를 COMMIT(커밋)
+                        let commitResultData = await client.query('COMMIT');
+                        //console.log('커밋 결과 정보 commitResultData : ', commitResultData);
+
+                        //Promise resolve 처리
+                        resolve(commitResultData);
+                    } catch (error) {
+                        //5. *에러 완료시, 실행(dispatch)한 모든 쿼리를 COMMIT(커밋)
+                        let rollbackResultData = await client.query('ROLLBACK');
+                        console.log('롤백 결과 정보 rollbackResultData : ', rollbackResultData);
+
+                        //Promise reject 처리
+                        reject(error);
+                    } finally {
+                        //6. 받아온 connection pool 반납(해제) - 필수(반납하지 않으면 해당 pool을 사용하는 query는 트랜잭션에 계속 매달려있음)
+                        client.release();
+                    }
+                }).catch((error) => {
+                    //Promise reject 처리
+                    reject(error);
+                })
+            });
+        },//testTransaction() end
+
+    }//return end
+ 
+ })();
+ 
+ //Module Export
+ module.exports = TestDAO;(파일 끝에 줄바꿈 문자 없음)
 
server/service/test/model/TestService.js (added)
+++ server/service/test/model/TestService.js
@@ -0,0 +1,138 @@
+/**
+ * @author : 최정우
+ * @since : 2022.09.20
+ * @dscription : 테스트용 서비스 로직을 담당하는 모듈 입니다.
+ */
+ const TestService = (function () {
+
+    //DAO
+    const TestDAO = require('./TestDAO');
+    
+    //public object
+    return {
+
+        /**
+         * @author : 최정우
+         * @since : 2022.09.20
+         * @dscription : 테스트 데이터 목록 조회
+         * @callback : parameter -> {data: Object, error: Object}
+         */
+        testSelectList: function (callback, param) {
+            //Data Access 접근
+            let dataAccessResult = TestDAO.testSelectList(param);
+            //Data Access 결과
+            dataAccessResult.then((data) => {
+                console.log('TestService testSelectList connect dataAccessResult : ', data);
+                callback({data: data, error: null});//Router에 결과 전달
+            }).catch((error) => {
+                callback({data: null, error: error});//Router에 Error 전달
+            })
+        },
+
+        /**
+         * @author : 최정우
+         * @since : 2022.09.20
+         * @dscription : 테스트 데이터 상세 조회
+         */
+        testSelectOne: function (callback, param) {
+            param = [1];
+            //Data Access 접근
+            let dataAccessResult = TestDAO.testSelectOne(param);
+            //Data Access 결과
+            dataAccessResult.then((data) => {
+                console.log('TestService testSelectOne connect dataAccessResult : ', data);
+                callback({data: data, error: null});//Router에 결과 전달
+            }).catch((error) => {
+                callback({data: null, error: error});//Router에 Error 전달
+            })
+        },
+
+        /**
+         * @author : 최정우
+         * @since : 2022.09.20
+         * @dscription : 테스트 데이터 등록
+         */
+         testInsertOne: function (callback, param) {
+            param = ['test title', 'test content'];
+            //Data Access 접근
+            let dataAccessResult = TestDAO.testInsertOne(param);
+            //Data Access 결과
+            dataAccessResult.then((data) => {
+                console.log('TestService testInsertOne connect dataAccessResult : ', data.rows[0]['test_seq']);
+                callback({data: data, error: null});//Router에 결과 전달
+            }).catch((error) => {
+                callback({data: null, error: error});//Router에 Error 전달
+            })
+        },
+
+        /**
+         * @author : 최정우
+         * @since : 2022.09.20
+         * @dscription : 테스트 데이터 수정
+         */
+        testUpdateOne: function (callback, param) {
+            param = [1, 'test title update', 'test content update'];
+            //Data Access 접근
+            let dataAccessResult = TestDAO.testUpdateOne(param);
+            //Data Access 결과
+            dataAccessResult.then((data) => {
+                console.log('TestService testUpdateOne connect dataAccessResult : ', data);
+                callback({data: data, error: null});//Router에 결과 전달
+            }).catch((error) => {
+                callback({data: null, error: error});//Router에 Error 전달
+            })
+        },
+
+        /**
+         * @author : 최정우
+         * @since : 2022.09.20
+         * @dscription : 테스트 데이터 삭제
+         */
+        testDeleteOne: function (callback, param) {
+            param = [10];
+            //Data Access 접근
+            let dataAccessResult = TestDAO.testDeleteOne(param);
+            //Data Access 결과
+            dataAccessResult.then((data) => {
+                console.log('TestService testDeleteOne connect dataAccessResult : ', data);
+                callback({data: data, error: null});//Router에 결과 전달
+            }).catch((error) => {
+                callback({data: null, error: error});//Router에 Error 전달
+            })
+        },
+
+        /**
+         * @author : 최정우
+         * @since : 2022.09.20
+         * @dscription : 테스트 트랜젝션 처리
+         * 
+         * 트랜잭션 작업 진행 시나리오
+         *  1. connection pool 한 개 받아오기
+         *  2. BEGIN(트랜잭션 시작 처리)
+         *  3. [※작업내용1] 데이터 등록
+         *  4. [※작업내용2] 등록한 데이터 수정
+         *  5. *작업 완료시, 실행(dispatch)한 모든 쿼리를 COMMIT(커밋)
+         *     *에러 발생시, 실행(dispatch)한 모든 쿼리를 ROLLBACK(롤백)
+         *  6. 받아온 connection pool 반납(해제) - 필수(반납하지 않으면 해당 pool을 사용하는 query는 트랜잭션에 계속 매달려있음)
+         */
+         testTransaction: function (callback, param) {
+            param = ['test title', 'test content'];
+            //Data Access 접근
+            let dataAccessResult = TestDAO.testTransaction(param);
+            //Data Access 결과
+            dataAccessResult.then((data) => {
+                console.log('TestService testTransaction connect dataAccessResult : ', data);
+                callback({data: data, error: null});//Router에 결과 전달
+            }).catch((error) => {
+                callback({data: null, error: error});//Router에 Error 전달
+            })
+        },
+
+
+    }
+ 
+ })();
+ 
+ //Module Export
+ module.exports = TestService;
+ (파일 끝에 줄바꿈 문자 없음)
 
server/service/test/router/TestRouter.js (added)
+++ server/service/test/router/TestRouter.js
@@ -0,0 +1,119 @@
+/**
+ * @author : 최정우
+ * @since : 2022.09.20
+ * @dscription : 테스트용 Router(Controller) 모듈 입니다.
+ */
+const express = require('express');
+const router = express.Router();
+
+//Service
+const TestService = require('../model/TestService');
+
+
+/**
+ * @author : 최정우
+ * @since : 2022.09.20
+ * @dscription : 테스트 데이터 목록 조회(POST)
+ */
+router.get('/testSelectList.json', function (request, response, next) {
+    //Callback 함수 Parameter result = {data: Object, error: Object}
+    TestService.testSelectList((result) => {
+        if (!result.error) {
+            response.send(result.data);
+        } else {
+            next(result.error);//Global Error Handler에게 예외상황 맡기기
+        }
+    });
+})
+
+/**
+ * @author : 최정우
+ * @since : 2022.09.20
+ * @dscription : 테스트 데이터 상세 조회(POST)
+ */
+router.get('/testSelectOne.json', function (request, response, next) {
+    //Callback 함수 Parameter -> result = {data: Object, error: Object}
+    TestService.testSelectOne((result) => {
+        if (!result.error) {
+            response.send(result.data);
+        } else {
+            next(result.error);//Global Error Handler에게 예외상황 맡기기
+        }
+    });
+})
+
+/**
+ * @author : 최정우
+ * @since : 2022.09.20
+ * @dscription : 테스트 데이터 등록 (POST)
+ */
+router.get('/testInsertOne.json', function (request, response, next) {
+    //Callback 함수 Parameter -> result = {data: Object, error: Object}
+    TestService.testInsertOne((result) => {
+        if (!result.error) {
+            response.send(result.data);
+        } else {
+            next(result.error);//Global Error Handler에게 예외상황 맡기기
+        }
+    })
+})
+
+/**
+ * @author : 최정우
+ * @since : 2022.09.20
+ * @dscription : 테스트 데이터 수정 (POST)
+ */
+router.get('/testUpdateOne.json', function (request, response, next) {
+    //Callback 함수 Parameter -> result = {data: Object, error: Object}
+    TestService.testUpdateOne((result) => {
+        if (!result.error) {
+            response.send(result.data);
+        } else {
+            next(result.error);//Global Error Handler에게 예외상황 맡기기
+        }
+    })
+})
+
+/**
+ * @author : 최정우
+ * @since : 2022.09.20
+ * @dscription : 테스트 데이터 삭제 (POST)
+ */
+router.get('/testDeleteOne.json', function (request, response, next) {
+    //Callback 함수 Parameter -> result = {data: Object, error: Object}
+    TestService.testDeleteOne((result) => {
+        if (!result.error) {
+            response.send(result.data);
+        } else {
+            next(result.error);//Global Error Handler에게 예외상황 맡기기
+        }
+    })
+})
+
+/**
+ * @author : 최정우
+ * @since : 2022.09.20
+ * @dscription : 테스트 트랜젝션 처리
+ * 
+ * 트랜잭션 작업 진행 시나리오
+ *  1. connection pool 한 개 받아오기
+ *  2. BEGIN(트랜잭션 시작 처리)
+ *  3. [※작업내용1] 데이터 등록
+ *  4. [※작업내용2] 등록한 데이터 수정
+ *  5. *작업 완료시, 실행(dispatch)한 모든 쿼리를 COMMIT(커밋)
+ *     *에러 발생시, 실행(dispatch)한 모든 쿼리를 ROLLBACK(롤백)
+ *  6. 받아온 connection pool 반납(해제) - 필수(반납하지 않으면 해당 pool을 사용하는 query는 트랜잭션에 계속 매달려있음)
+ */
+router.get('/testTransaction.json', function (request, response, next) {
+    //Callback 함수 Parameter -> result = {data: Object, error: Object}
+    TestService.testTransaction((result) => {
+        if (!result.error) {
+            response.send(result.data);
+        } else {
+            next(result.error);//Global Error Handler에게 예외상황 맡기기
+        }
+    })
+})
+
+//Module Export
+module.exports = router;(파일 끝에 줄바꿈 문자 없음)
 
webpack.config.js (added)
+++ webpack.config.js
@@ -0,0 +1,42 @@
+const { VueLoaderPlugin } = require("vue-loader");
+
+const {PROJECT_NAME, BASE_DIR, SERVICE_STATUS} = require('./Global');
+
+module.exports = {
+  name: PROJECT_NAME,
+  mode: SERVICE_STATUS,
+  devtool: 'eval',
+
+  entry: {
+    app: [`${BASE_DIR}/client/views/index.js`]
+  },
+
+  module: {
+    rules: [{
+      test: /\.vue?$/,
+      loader: 'vue-loader',
+    }, {
+      test: /\.(js|jsx)?$/,
+      loader: 'babel-loader',
+    }, {
+      test: /\.css$/,
+      use: ['vue-style-loader', 'css-loader']
+    }, {
+      test: /\.(jpe?g|png|gif|svg|ttf|eot|woff|woff2)$/i,
+      use: [{
+        loader:'url-loader',
+        options:{
+          limit:8192,
+          fallback:require.resolve('file-loader')
+        }
+      }]
+    }],
+  },
+
+  plugins: [new VueLoaderPlugin()],
+
+  output: {
+    path: `${BASE_DIR}/client/build`,	// __dirname: webpack.config.js 파일이 위치한 경로
+    filename: 'bundle.js'
+  },
+}(파일 끝에 줄바꿈 문자 없음)
Add a comment
List