From 9818baadae001d21b07a500e3cdd33694955db47 Mon Sep 17 00:00:00 2001 From: Sangjin Park <58503584+healtheloper@users.noreply.github.com> Date: Sun, 12 Jun 2022 22:23:03 +0900 Subject: [PATCH] =?UTF-8?q?[team-31][FE]=20Muffin=20&=20Park=203=EC=A3=BC?= =?UTF-8?q?=EC=B0=A8=20=EA=B8=88=EC=9A=94=EC=9D=BC=20=20(#300)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Muffin] 검색결과 페이지 - 왼쪽 레이아웃 작업 ( 더미데이터 사용하여 화면 출력) (#67) * feat: Search Component 분리 * refactor: 메인페이지 가까운 레이아웃 스켈레톤 UI 적용해보기 * feat: 검색결과 페이지 왼쪽 레이아웃 더미데이터 사용하여 렌더링 * refactor: location 타입 지정 * refactor: room 컴포넌트 내 함수 네이밍 수정 * [Park] create mock server (#68) * feat: create msw * feat: some data use dummy data * refactor: main page type & varriables name refactoring * feat: useFetch hooks * feat: useFetch type modify * data: roomDetailList -> roomDetail 로 수정 * [Muffin] 검색 결과페이지 숙소 모달 관련 기능 작업, moment 라이브러리 추가 * [Muffin] modal창을 열었을때 Header 밀리는 현상 * [Muffin] 차트 슬라이드 에러 수정 * refactor: slider 에러 관련 처리 및 날짜 미선택 시 차트 모달에 안내 텍스트 보여주기 * refactor: 빅서치바 인풋 체크인, 체크아웃 x 버튼클릭시 에도 차트 관련 데이터 리셋 * refactor: price 금액 초기화 하는 context SET_INIT_PRICE type으로 초기화 하도록 수정 * [Park] GitHub OAuth login * feat: github login authorization and get code * feat: post logic 백엔드에서 처리 -> CORS 문제로 이전 * feat: github login, avatar url * style: 안쓰는 변수 제거 * fix: .env github client id add * refactor: 중복 로직 제거 및 안쓰는 변수 제거 * fix: map scroll & rooms type Co-authored-by: Muffin --- package-lock.json | 1278 +++++++++++++++-- package.json | 5 + public/mockServiceWorker.js | 338 +++++ src/App.tsx | 2 + src/assets/star_img.png | Bin 0 -> 366 bytes src/assets/wish_img.png | Bin 0 -> 511 bytes src/common/util.ts | 22 +- src/components/Chart/Graph.tsx | 4 +- src/components/Chart/index.tsx | 6 +- .../Header/BigSearchBar/BigMenu.tsx | 12 +- .../Header/BigSearchBar/SearchButton.tsx | 55 + src/components/Header/BigSearchBar/index.tsx | 25 +- src/components/Header/UserInfo.tsx | 60 +- src/components/Loading.tsx | 17 + ...{AnyWhereBox.tsx => CategoryLocations.tsx} | 20 +- .../Main/{NearByBox.tsx => NearLocations.tsx} | 21 +- src/components/Main/SkeletonNearLocations.tsx | 39 + src/components/OAuthCallback.tsx | 26 + src/components/SearchResult/Room.tsx | 141 ++ src/components/SearchResult/RoomModal.tsx | 184 +++ src/components/SearchResult/Rooms.tsx | 88 ++ src/contexts/HeaderProvider.tsx | 19 +- src/contexts/PriceProvider.tsx | 8 + src/hooks/useFetch.tsx | 71 + src/hooks/useThrottle.jsx | 15 - src/index.tsx | 12 +- src/pages/MainPage.tsx | 56 +- src/pages/SearchResultPage.tsx | 47 +- src/server/browser.ts | 5 + src/server/dummyData/categoryLocations.js | 31 + .../dummyData/nearLocations.js} | 34 +- src/server/dummyData/roomDetail.js | 44 + src/server/dummyData/roomList.js | 179 +++ src/server/handlers.ts | 37 + tsconfig.json | 3 +- webpack.config.js | 5 +- 36 files changed, 2685 insertions(+), 224 deletions(-) create mode 100644 public/mockServiceWorker.js create mode 100644 src/assets/star_img.png create mode 100644 src/assets/wish_img.png create mode 100644 src/components/Header/BigSearchBar/SearchButton.tsx create mode 100644 src/components/Loading.tsx rename src/components/Main/{AnyWhereBox.tsx => CategoryLocations.tsx} (55%) rename src/components/Main/{NearByBox.tsx => NearLocations.tsx} (56%) create mode 100644 src/components/Main/SkeletonNearLocations.tsx create mode 100644 src/components/OAuthCallback.tsx create mode 100644 src/components/SearchResult/Room.tsx create mode 100644 src/components/SearchResult/RoomModal.tsx create mode 100644 src/components/SearchResult/Rooms.tsx create mode 100644 src/hooks/useFetch.tsx delete mode 100644 src/hooks/useThrottle.jsx create mode 100644 src/server/browser.ts create mode 100644 src/server/dummyData/categoryLocations.js rename src/{mocks/main.js => server/dummyData/nearLocations.js} (65%) create mode 100644 src/server/dummyData/roomDetail.js create mode 100644 src/server/dummyData/roomList.js create mode 100644 src/server/handlers.ts diff --git a/package-lock.json b/package-lock.json index 90045305a..5a5331e36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,8 @@ "core-js": "^3.22.6", "emotion-normalize": "^11.0.1", "lodash": "^4.17.21", + "msw": "^0.42.1", + "moment": "^2.29.3", "react": "^18.1.0", "react-carousel-calendar": "^0.0.3", "react-dom": "^18.1.0", @@ -2131,6 +2133,34 @@ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", "dev": true }, + "node_modules/@mswjs/cookies": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-0.2.1.tgz", + "integrity": "sha512-0tDfcPw5/s7QsNQqS3knAvAD5w5PF1nNPagRhKO/yECY+sMbJxoC2sLWnH7Lzmh52mTSVLKDhd1r92Q3kfljnQ==", + "dependencies": { + "@types/set-cookie-parser": "^2.4.0", + "set-cookie-parser": "^2.4.6" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@mswjs/interceptors": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.16.4.tgz", + "integrity": "sha512-McPKUFlZNS/wo+OAor15k0fv2skK+EdWl9CEcdxAqsN4vKajlxCxDU4B5W/pn1y0TJPSAOmxR6LYFe/8esePrg==", + "dependencies": { + "@open-draft/until": "^1.0.3", + "@xmldom/xmldom": "^0.7.5", + "debug": "^4.3.3", + "headers-polyfill": "^3.0.4", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.2.4" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/@mui/base": { "version": "5.0.0-alpha.82", "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.82.tgz", @@ -2412,6 +2442,11 @@ "node": ">= 8" } }, + "node_modules/@open-draft/until": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz", + "integrity": "sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==" + }, "node_modules/@polka/url": { "version": "1.0.0-next.21", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", @@ -2465,6 +2500,11 @@ "@types/node": "*" } }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, "node_modules/@types/eslint": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.2.tgz", @@ -2529,6 +2569,11 @@ "@types/node": "*" } }, + "node_modules/@types/js-levenshtein": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/js-levenshtein/-/js-levenshtein-1.1.1.tgz", + "integrity": "sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g==" + }, "node_modules/@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -2556,8 +2601,7 @@ "node_modules/@types/node": { "version": "17.0.35", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz", - "integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==", - "dev": true + "integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==" }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -2646,6 +2690,14 @@ "@types/node": "*" } }, + "node_modules/@types/set-cookie-parser": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@types/set-cookie-parser/-/set-cookie-parser-2.4.2.tgz", + "integrity": "sha512-fBZgytwhYAUkj/jC/FAV4RQ5EerRup1YQsXQCh8rZfiHkc4UahC192oH0smGwsXol3cL3A5oETuAHeQHmhXM4w==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/sockjs": { "version": "0.3.33", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", @@ -3060,6 +3112,14 @@ } } }, + "node_modules/@xmldom/xmldom": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz", + "integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -3189,6 +3249,31 @@ "ajv": "^6.9.1" } }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-html-community": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", @@ -3205,7 +3290,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -3214,7 +3298,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -3229,7 +3312,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -3455,6 +3537,25 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -3474,11 +3575,20 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, "engines": { "node": ">=8" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "node_modules/body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -3559,7 +3669,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -3595,6 +3704,29 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -3660,7 +3792,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -3676,7 +3807,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -3684,11 +3814,15 @@ "node": ">=8" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, "funding": [ { "type": "individual", @@ -3715,7 +3849,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -3744,6 +3877,54 @@ "node": ">= 10.0" } }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -3770,7 +3951,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -3781,8 +3961,7 @@ "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==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/colorette": { "version": "2.0.16", @@ -4078,6 +4257,14 @@ "node": ">= 10" } }, + "node_modules/defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", + "dependencies": { + "clone": "^1.0.2" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -4945,7 +5132,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, "engines": { "node": ">=0.8.x" } @@ -5036,6 +5222,19 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -5110,6 +5309,28 @@ "node": ">=0.8.0" } }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/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==", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -5147,7 +5368,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -5297,7 +5517,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -5353,6 +5572,14 @@ "node": ">=6.9.0" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", @@ -5476,6 +5703,14 @@ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, + "node_modules/graphql": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.5.0.tgz", + "integrity": "sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA==", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, "node_modules/gzip-size": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", @@ -5521,7 +5756,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -5574,6 +5808,11 @@ "he": "bin/he" } }, + "node_modules/headers-polyfill": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-3.0.7.tgz", + "integrity": "sha512-JoLCAdCEab58+2/yEmSnOlficyHFpIl0XJqwu3l+Unkm1gXpFUYsThz6Yha3D6tNhocWkCPfyW0YVIGWFqTi7w==" + }, "node_modules/history": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", @@ -5789,7 +6028,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -5797,6 +6035,25 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -5863,8 +6120,32 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } }, "node_modules/internal-slot": { "version": "1.0.3", @@ -5919,7 +6200,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -6000,16 +6280,22 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, "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==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -6017,6 +6303,14 @@ "node": ">=0.10.0" } }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -6029,11 +6323,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-node-process": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.0.1.tgz", + "integrity": "sha512-5IcdXuf++TTNt3oGl9EBdkvndXA8gmc4bz/Y+mdEpWh3Mcn/+kOw6hI7LD5CocqJWMzeb0I0ClndRVNdEPuJXQ==" + }, "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==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -6147,6 +6445,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -6206,6 +6515,14 @@ "node": ">= 10.13.0" } }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6396,6 +6713,21 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -6544,7 +6876,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -6573,6 +6904,14 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, + "node_modules/moment": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", + "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==", + "engines": { + "node": "*" + } + }, "node_modules/mrmime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz", @@ -6587,6 +6926,102 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/msw": { + "version": "0.42.1", + "resolved": "https://registry.npmjs.org/msw/-/msw-0.42.1.tgz", + "integrity": "sha512-LZZuz7VddL45gCBgfBWHyXj6a4W7OTJY0mZPoipJ3P/xwbuJwrtwB3IJrWlqBM8aink/eTKlRxwzmtIAwCj5yQ==", + "hasInstallScript": true, + "dependencies": { + "@mswjs/cookies": "^0.2.0", + "@mswjs/interceptors": "^0.16.3", + "@open-draft/until": "^1.0.3", + "@types/cookie": "^0.4.1", + "@types/js-levenshtein": "^1.1.1", + "chalk": "4.1.1", + "chokidar": "^3.4.2", + "cookie": "^0.4.2", + "graphql": "^16.3.0", + "headers-polyfill": "^3.0.4", + "inquirer": "^8.2.0", + "is-node-process": "^1.0.1", + "js-levenshtein": "^1.1.6", + "node-fetch": "^2.6.7", + "outvariant": "^1.3.0", + "path-to-regexp": "^6.2.0", + "statuses": "^2.0.0", + "strict-event-emitter": "^0.2.0", + "type-fest": "^1.2.2", + "yargs": "^17.3.1" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.2.x <= 4.7.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/msw/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "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/msw/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/msw/node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" + }, + "node_modules/msw/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==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/msw/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/multicast-dns": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", @@ -6600,6 +7035,11 @@ "multicast-dns": "cli.js" } }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6632,6 +7072,44 @@ "tslib": "^2.0.3" } }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -6650,7 +7128,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -6826,7 +7303,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -6881,6 +7357,41 @@ "node": ">= 0.8.0" } }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/outvariant": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.3.0.tgz", + "integrity": "sha512-yeWM9k6UPfG/nzxdaPlJkB2p08hCg4xP6Lx99F+vP8YF7xyZVfTmJjrrNalkmzudD4WFvNLVudQikqUmF8zhVQ==" + }, "node_modules/p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -7039,7 +7550,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -7354,7 +7864,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -7368,7 +7877,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -7515,6 +8023,14 @@ "strip-ansi": "^6.0.1" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -7575,6 +8091,18 @@ "node": ">=4" } }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -7609,6 +8137,14 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7632,11 +8168,18 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rxjs": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "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==", - "dev": true, "funding": [ { "type": "github", @@ -7655,8 +8198,7 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/scheduler": { "version": "0.22.0", @@ -7857,6 +8399,11 @@ "node": ">= 0.8.0" } }, + "node_modules/set-cookie-parser": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.5.0.tgz", + "integrity": "sha512-cHMAtSXilfyBePduZEBVPTCftTQWz6ehWJD5YNUg4mqvRosrrjKbo4WS8JkB0/RxonMoohHm7cOGH60mDkRQ9w==" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -7913,8 +8460,7 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/sirv": { "version": "1.0.19", @@ -8003,20 +8549,44 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, "engines": { "node": ">= 0.8" } }, + "node_modules/strict-event-emitter": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.2.4.tgz", + "integrity": "sha512-xIqTLS5azUH1djSUsLH9DbP6UnM/nI18vu8d43JigCQEoVsnY+mrlE+qv6kYqs6/1OkMnMIiL6ffedQSZStuoQ==", + "dependencies": { + "events": "^3.3.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "node_modules/string.prototype.matchall": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", @@ -8069,7 +8639,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -8235,12 +8804,28 @@ "dev": true, "peer": true }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -8253,7 +8838,6 @@ "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==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -8303,8 +8887,7 @@ "node_modules/tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -8370,7 +8953,7 @@ "version": "4.6.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz", "integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==", - "dev": true, + "devOptional": true, "peer": true, "bin": { "tsc": "bin/tsc", @@ -8456,8 +9039,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "node_modules/utila": { "version": "0.4.0", @@ -8521,6 +9103,14 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dependencies": { + "defaults": "^1.0.3" + } + }, "node_modules/webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", @@ -8961,6 +9551,22 @@ "node": ">=0.10.0" } }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -8988,6 +9594,14 @@ } } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -9001,6 +9615,31 @@ "engines": { "node": ">= 6" } + }, + "node_modules/yargs": { + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", + "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "engines": { + "node": ">=12" + } } }, "dependencies": { @@ -10460,6 +11099,28 @@ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", "dev": true }, + "@mswjs/cookies": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-0.2.1.tgz", + "integrity": "sha512-0tDfcPw5/s7QsNQqS3knAvAD5w5PF1nNPagRhKO/yECY+sMbJxoC2sLWnH7Lzmh52mTSVLKDhd1r92Q3kfljnQ==", + "requires": { + "@types/set-cookie-parser": "^2.4.0", + "set-cookie-parser": "^2.4.6" + } + }, + "@mswjs/interceptors": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.16.4.tgz", + "integrity": "sha512-McPKUFlZNS/wo+OAor15k0fv2skK+EdWl9CEcdxAqsN4vKajlxCxDU4B5W/pn1y0TJPSAOmxR6LYFe/8esePrg==", + "requires": { + "@open-draft/until": "^1.0.3", + "@xmldom/xmldom": "^0.7.5", + "debug": "^4.3.3", + "headers-polyfill": "^3.0.4", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.2.4" + } + }, "@mui/base": { "version": "5.0.0-alpha.82", "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.82.tgz", @@ -10602,6 +11263,11 @@ "fastq": "^1.6.0" } }, + "@open-draft/until": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz", + "integrity": "sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==" + }, "@polka/url": { "version": "1.0.0-next.21", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", @@ -10651,6 +11317,11 @@ "@types/node": "*" } }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, "@types/eslint": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.2.tgz", @@ -10715,6 +11386,11 @@ "@types/node": "*" } }, + "@types/js-levenshtein": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/js-levenshtein/-/js-levenshtein-1.1.1.tgz", + "integrity": "sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g==" + }, "@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -10742,8 +11418,7 @@ "@types/node": { "version": "17.0.35", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz", - "integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==", - "dev": true + "integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==" }, "@types/parse-json": { "version": "4.0.0", @@ -10832,6 +11507,14 @@ "@types/node": "*" } }, + "@types/set-cookie-parser": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@types/set-cookie-parser/-/set-cookie-parser-2.4.2.tgz", + "integrity": "sha512-fBZgytwhYAUkj/jC/FAV4RQ5EerRup1YQsXQCh8rZfiHkc4UahC192oH0smGwsXol3cL3A5oETuAHeQHmhXM4w==", + "requires": { + "@types/node": "*" + } + }, "@types/sockjs": { "version": "0.3.33", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", @@ -11136,6 +11819,11 @@ "dev": true, "requires": {} }, + "@xmldom/xmldom": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz", + "integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==" + }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -11233,6 +11921,21 @@ "dev": true, "requires": {} }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + } + } + }, "ansi-html-community": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", @@ -11242,14 +11945,12 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -11258,7 +11959,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -11433,6 +12133,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, "batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -11448,8 +12153,17 @@ "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } }, "body-parser": { "version": "1.20.0", @@ -11526,7 +12240,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -11543,6 +12256,15 @@ "picocolors": "^1.0.0" } }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -11589,7 +12311,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -11599,18 +12320,21 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "requires": { "has-flag": "^4.0.0" } } } }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, "chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, "requires": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -11626,7 +12350,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -11648,6 +12371,39 @@ "source-map": "~0.6.0" } }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==" + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" + }, "clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -11668,7 +12424,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -11676,8 +12431,7 @@ "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==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "colorette": { "version": "2.0.16", @@ -11918,6 +12672,14 @@ "execa": "^5.0.0" } }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", + "requires": { + "clone": "^1.0.2" + } + }, "define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -12588,8 +13350,7 @@ "events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" }, "execa": { "version": "5.1.1", @@ -12670,6 +13431,16 @@ } } }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -12737,6 +13508,21 @@ "websocket-driver": ">=0.5.1" } }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "requires": { + "escape-string-regexp": "^1.0.5" + }, + "dependencies": { + "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==" + } + } + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -12761,7 +13547,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -12875,7 +13660,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "optional": true }, "function-bind": { @@ -12912,6 +13696,11 @@ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, "get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", @@ -12999,6 +13788,11 @@ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, + "graphql": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.5.0.tgz", + "integrity": "sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA==" + }, "gzip-size": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", @@ -13031,8 +13825,7 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "has-property-descriptors": { "version": "1.0.0", @@ -13064,6 +13857,11 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "headers-polyfill": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-3.0.7.tgz", + "integrity": "sha512-JoLCAdCEab58+2/yEmSnOlficyHFpIl0XJqwu3l+Unkm1gXpFUYsThz6Yha3D6tNhocWkCPfyW0YVIGWFqTi7w==" + }, "history": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", @@ -13237,11 +14035,15 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, "ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -13287,8 +14089,29 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + } }, "internal-slot": { "version": "1.0.3", @@ -13331,7 +14154,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "requires": { "binary-extensions": "^2.0.0" } @@ -13378,29 +14200,41 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" + }, "is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "dev": true }, + "is-node-process": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.0.1.tgz", + "integrity": "sha512-5IcdXuf++TTNt3oGl9EBdkvndXA8gmc4bz/Y+mdEpWh3Mcn/+kOw6hI7LD5CocqJWMzeb0I0ClndRVNdEPuJXQ==" + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "is-number-object": { "version": "1.0.7", @@ -13469,6 +14303,11 @@ "has-symbols": "^1.0.2" } }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" + }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -13516,6 +14355,11 @@ "supports-color": "^8.0.0" } }, + "js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -13672,6 +14516,15 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -13780,8 +14633,7 @@ "mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" }, "minimalistic-assert": { "version": "1.0.1", @@ -13804,6 +14656,11 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, + "moment": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", + "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==" + }, "mrmime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz", @@ -13815,6 +14672,67 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "msw": { + "version": "0.42.1", + "resolved": "https://registry.npmjs.org/msw/-/msw-0.42.1.tgz", + "integrity": "sha512-LZZuz7VddL45gCBgfBWHyXj6a4W7OTJY0mZPoipJ3P/xwbuJwrtwB3IJrWlqBM8aink/eTKlRxwzmtIAwCj5yQ==", + "requires": { + "@mswjs/cookies": "^0.2.0", + "@mswjs/interceptors": "^0.16.3", + "@open-draft/until": "^1.0.3", + "@types/cookie": "^0.4.1", + "@types/js-levenshtein": "^1.1.1", + "chalk": "4.1.1", + "chokidar": "^3.4.2", + "cookie": "^0.4.2", + "graphql": "^16.3.0", + "headers-polyfill": "^3.0.4", + "inquirer": "^8.2.0", + "is-node-process": "^1.0.1", + "js-levenshtein": "^1.1.6", + "node-fetch": "^2.6.7", + "outvariant": "^1.3.0", + "path-to-regexp": "^6.2.0", + "statuses": "^2.0.0", + "strict-event-emitter": "^0.2.0", + "type-fest": "^1.2.2", + "yargs": "^17.3.1" + }, + "dependencies": { + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + }, + "path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" + }, + "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==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==" + } + } + }, "multicast-dns": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", @@ -13825,6 +14743,11 @@ "thunky": "^1.0.2" } }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -13854,6 +14777,35 @@ "tslib": "^2.0.3" } }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, "node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -13868,8 +14820,7 @@ "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "npm-run-path": { "version": "4.0.1", @@ -13997,7 +14948,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "requires": { "mimic-fn": "^2.1.0" } @@ -14034,6 +14984,32 @@ "word-wrap": "^1.2.3" } }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==" + }, + "outvariant": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.3.0.tgz", + "integrity": "sha512-yeWM9k6UPfG/nzxdaPlJkB2p08hCg4xP6Lx99F+vP8YF7xyZVfTmJjrrNalkmzudD4WFvNLVudQikqUmF8zhVQ==" + }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -14155,8 +15131,7 @@ "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "pkg-dir": { "version": "4.2.0", @@ -14389,7 +15364,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -14400,7 +15374,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "requires": { "picomatch": "^2.2.1" } @@ -14516,6 +15489,11 @@ "strip-ansi": "^6.0.1" } }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, "require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -14560,6 +15538,15 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, "retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -14581,6 +15568,11 @@ "glob": "^7.1.3" } }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" + }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -14590,17 +15582,23 @@ "queue-microtask": "^1.2.2" } }, + "rxjs": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "requires": { + "tslib": "^2.1.0" + } + }, "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==", - "dev": true + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "scheduler": { "version": "0.22.0", @@ -14776,6 +15774,11 @@ "send": "0.18.0" } }, + "set-cookie-parser": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.5.0.tgz", + "integrity": "sha512-cHMAtSXilfyBePduZEBVPTCftTQWz6ehWJD5YNUg4mqvRosrrjKbo4WS8JkB0/RxonMoohHm7cOGH60mDkRQ9w==" + }, "setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -14820,8 +15823,7 @@ "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "sirv": { "version": "1.0.19", @@ -14897,18 +15899,41 @@ "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "strict-event-emitter": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.2.4.tgz", + "integrity": "sha512-xIqTLS5azUH1djSUsLH9DbP6UnM/nI18vu8d43JigCQEoVsnY+mrlE+qv6kYqs6/1OkMnMIiL6ffedQSZStuoQ==", + "requires": { + "events": "^3.3.0" + } }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "requires": { "safe-buffer": "~5.2.0" } }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + } + } + }, "string.prototype.matchall": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", @@ -14952,7 +15977,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -15051,12 +16075,25 @@ "dev": true, "peer": true }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, "thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -15066,7 +16103,6 @@ "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==", - "dev": true, "requires": { "is-number": "^7.0.0" } @@ -15107,8 +16143,7 @@ "tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "tsutils": { "version": "3.21.0", @@ -15158,7 +16193,7 @@ "version": "4.6.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz", "integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==", - "dev": true, + "devOptional": true, "peer": true }, "unbox-primitive": { @@ -15219,8 +16254,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utila": { "version": "0.4.0", @@ -15272,6 +16306,14 @@ "minimalistic-assert": "^1.0.0" } }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "requires": { + "defaults": "^1.0.3" + } + }, "webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", @@ -15580,6 +16622,16 @@ "dev": true, "peer": true }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -15593,6 +16645,11 @@ "dev": true, "requires": {} }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -15603,6 +16660,25 @@ "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" + }, + "yargs": { + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", + "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + } + }, + "yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==" } } } diff --git a/package.json b/package.json index 65b981c04..de4933284 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,8 @@ "core-js": "^3.22.6", "emotion-normalize": "^11.0.1", "lodash": "^4.17.21", + "msw": "^0.42.1", + "moment": "^2.29.3", "react": "^18.1.0", "react-carousel-calendar": "^0.0.3", "react-dom": "^18.1.0", @@ -54,5 +56,8 @@ "webpack-bundle-analyzer": "^4.5.0", "webpack-cli": "^4.9.2", "webpack-dev-server": "^4.9.0" + }, + "msw": { + "workerDirectory": "public" } } diff --git a/public/mockServiceWorker.js b/public/mockServiceWorker.js new file mode 100644 index 000000000..f6d8c7a4c --- /dev/null +++ b/public/mockServiceWorker.js @@ -0,0 +1,338 @@ +/* eslint-disable */ +/* tslint:disable */ + +/** + * Mock Service Worker (0.42.1). + * @see https://github.com/mswjs/msw + * - Please do NOT modify this file. + * - Please do NOT serve this file on production. + */ + +const INTEGRITY_CHECKSUM = '02f4ad4a2797f85668baf196e553d929' +const bypassHeaderName = 'x-msw-bypass' +const activeClientIds = new Set() + +self.addEventListener('install', function () { + return self.skipWaiting() +}) + +self.addEventListener('activate', async function (event) { + return self.clients.claim() +}) + +self.addEventListener('message', async function (event) { + const clientId = event.source.id + + if (!clientId || !self.clients) { + return + } + + const client = await self.clients.get(clientId) + + if (!client) { + return + } + + const allClients = await self.clients.matchAll() + + switch (event.data) { + case 'KEEPALIVE_REQUEST': { + sendToClient(client, { + type: 'KEEPALIVE_RESPONSE', + }) + break + } + + case 'INTEGRITY_CHECK_REQUEST': { + sendToClient(client, { + type: 'INTEGRITY_CHECK_RESPONSE', + payload: INTEGRITY_CHECKSUM, + }) + break + } + + case 'MOCK_ACTIVATE': { + activeClientIds.add(clientId) + + sendToClient(client, { + type: 'MOCKING_ENABLED', + payload: true, + }) + break + } + + case 'MOCK_DEACTIVATE': { + activeClientIds.delete(clientId) + break + } + + case 'CLIENT_CLOSED': { + activeClientIds.delete(clientId) + + const remainingClients = allClients.filter((client) => { + return client.id !== clientId + }) + + // Unregister itself when there are no more clients + if (remainingClients.length === 0) { + self.registration.unregister() + } + + break + } + } +}) + +// Resolve the "main" client for the given event. +// Client that issues a request doesn't necessarily equal the client +// that registered the worker. It's with the latter the worker should +// communicate with during the response resolving phase. +async function resolveMainClient(event) { + const client = await self.clients.get(event.clientId) + + if (client.frameType === 'top-level') { + return client + } + + const allClients = await self.clients.matchAll() + + return allClients + .filter((client) => { + // Get only those clients that are currently visible. + return client.visibilityState === 'visible' + }) + .find((client) => { + // Find the client ID that's recorded in the + // set of clients that have registered the worker. + return activeClientIds.has(client.id) + }) +} + +async function handleRequest(event, requestId) { + const client = await resolveMainClient(event) + const response = await getResponse(event, client, requestId) + + // Send back the response clone for the "response:*" life-cycle events. + // Ensure MSW is active and ready to handle the message, otherwise + // this message will pend indefinitely. + if (client && activeClientIds.has(client.id)) { + ;(async function () { + const clonedResponse = response.clone() + sendToClient(client, { + type: 'RESPONSE', + payload: { + requestId, + type: clonedResponse.type, + ok: clonedResponse.ok, + status: clonedResponse.status, + statusText: clonedResponse.statusText, + body: + clonedResponse.body === null ? null : await clonedResponse.text(), + headers: serializeHeaders(clonedResponse.headers), + redirected: clonedResponse.redirected, + }, + }) + })() + } + + return response +} + +async function getResponse(event, client, requestId) { + const { request } = event + const requestClone = request.clone() + const getOriginalResponse = () => fetch(requestClone) + + // Bypass mocking when the request client is not active. + if (!client) { + return getOriginalResponse() + } + + // Bypass initial page load requests (i.e. static assets). + // The absence of the immediate/parent client in the map of the active clients + // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet + // and is not ready to handle requests. + if (!activeClientIds.has(client.id)) { + return await getOriginalResponse() + } + + // Bypass requests with the explicit bypass header + if (requestClone.headers.get(bypassHeaderName) === 'true') { + const cleanRequestHeaders = serializeHeaders(requestClone.headers) + + // Remove the bypass header to comply with the CORS preflight check. + delete cleanRequestHeaders[bypassHeaderName] + + const originalRequest = new Request(requestClone, { + headers: new Headers(cleanRequestHeaders), + }) + + return fetch(originalRequest) + } + + // Send the request to the client-side MSW. + const reqHeaders = serializeHeaders(request.headers) + const body = await request.text() + + const clientMessage = await sendToClient(client, { + type: 'REQUEST', + payload: { + id: requestId, + url: request.url, + method: request.method, + headers: reqHeaders, + cache: request.cache, + mode: request.mode, + credentials: request.credentials, + destination: request.destination, + integrity: request.integrity, + redirect: request.redirect, + referrer: request.referrer, + referrerPolicy: request.referrerPolicy, + body, + bodyUsed: request.bodyUsed, + keepalive: request.keepalive, + }, + }) + + switch (clientMessage.type) { + case 'MOCK_SUCCESS': { + return delayPromise( + () => respondWithMock(clientMessage), + clientMessage.payload.delay, + ) + } + + case 'MOCK_NOT_FOUND': { + return getOriginalResponse() + } + + case 'NETWORK_ERROR': { + const { name, message } = clientMessage.payload + const networkError = new Error(message) + networkError.name = name + + // Rejecting a request Promise emulates a network error. + throw networkError + } + + case 'INTERNAL_ERROR': { + const parsedBody = JSON.parse(clientMessage.payload.body) + + console.error( + `\ +[MSW] Uncaught exception in the request handler for "%s %s": + +${parsedBody.location} + +This exception has been gracefully handled as a 500 response, however, it's strongly recommended to resolve this error, as it indicates a mistake in your code. If you wish to mock an error response, please see this guide: https://mswjs.io/docs/recipes/mocking-error-responses\ +`, + request.method, + request.url, + ) + + return respondWithMock(clientMessage) + } + } + + return getOriginalResponse() +} + +self.addEventListener('fetch', function (event) { + const { request } = event + const accept = request.headers.get('accept') || '' + + // Bypass server-sent events. + if (accept.includes('text/event-stream')) { + return + } + + // Bypass navigation requests. + if (request.mode === 'navigate') { + return + } + + // Opening the DevTools triggers the "only-if-cached" request + // that cannot be handled by the worker. Bypass such requests. + if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { + return + } + + // Bypass all requests when there are no active clients. + // Prevents the self-unregistered worked from handling requests + // after it's been deleted (still remains active until the next reload). + if (activeClientIds.size === 0) { + return + } + + const requestId = uuidv4() + + return event.respondWith( + handleRequest(event, requestId).catch((error) => { + if (error.name === 'NetworkError') { + console.warn( + '[MSW] Successfully emulated a network error for the "%s %s" request.', + request.method, + request.url, + ) + return + } + + // At this point, any exception indicates an issue with the original request/response. + console.error( + `\ +[MSW] Caught an exception from the "%s %s" request (%s). This is probably not a problem with Mock Service Worker. There is likely an additional logging output above.`, + request.method, + request.url, + `${error.name}: ${error.message}`, + ) + }), + ) +}) + +function serializeHeaders(headers) { + const reqHeaders = {} + headers.forEach((value, name) => { + reqHeaders[name] = reqHeaders[name] + ? [].concat(reqHeaders[name]).concat(value) + : value + }) + return reqHeaders +} + +function sendToClient(client, message) { + return new Promise((resolve, reject) => { + const channel = new MessageChannel() + + channel.port1.onmessage = (event) => { + if (event.data && event.data.error) { + return reject(event.data.error) + } + + resolve(event.data) + } + + client.postMessage(JSON.stringify(message), [channel.port2]) + }) +} + +function delayPromise(cb, duration) { + return new Promise((resolve) => { + setTimeout(() => resolve(cb()), duration) + }) +} + +function respondWithMock(clientMessage) { + return new Response(clientMessage.payload.body, { + ...clientMessage.payload, + headers: clientMessage.payload.headers, + }) +} + +function uuidv4() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + const r = (Math.random() * 16) | 0 + const v = c == 'x' ? r : (r & 0x3) | 0x8 + return v.toString(16) + }) +} diff --git a/src/App.tsx b/src/App.tsx index 22dd60f60..69449c917 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,6 +5,7 @@ import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import { theme } from '@common/theme'; import Layout from '@components/Layout'; +import OAuthCallback from '@components/OAuthCallback'; import color from '@constants/color'; import { HeaderProvider, useHeaderState } from '@contexts/HeaderProvider'; import MainPage from '@pages/MainPage'; @@ -50,6 +51,7 @@ export default function App() { }> } /> + } /> } /> diff --git a/src/assets/star_img.png b/src/assets/star_img.png new file mode 100644 index 0000000000000000000000000000000000000000..852f8df8a1a26ef68a100aad5c22f463c6b7b42a GIT binary patch literal 366 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa&H|6fVg?3oVGw3ym^DWND9BhG zPqMVPMeSI+gAI;Dy~+V&GJAdD(ui%fW`%Sk9hMXbMZy+S7i;D%mCZ1LKu5K1VL> zzhi$~rDfuU(nSq%3|x%%Ss@&{&Kwyf;)hkPH79-34JdvmZ+Y9t;6l2{8sQ(GOqOcg zt6KAyrE$*bC+lZQhH9{H-ozhf5v{J`E+hNWGydIavD(ydJD+IARi&1o;9>A|^>bP0 Hl+XkKRr!cJ literal 0 HcmV?d00001 diff --git a/src/assets/wish_img.png b/src/assets/wish_img.png new file mode 100644 index 0000000000000000000000000000000000000000..4381e097cc4329cf88c51e6c445568f4c728f34a GIT binary patch literal 511 zcmVzQSZfqb*n~#h+GTBgoayOgJB-`l!f`l5#@&B#=N;_3dq=r0mJkn~7_RJ`D~?nO@luSeE{!C=Qf*l3#1`4d+L z*A!mQY#)!uAH_xGisPM&^C7Mbc)W|#8ClW0I0pbsQ5{fx?3B(BJ(e4Vhb=CEe2}CM z3L!xkh#nJ&({`Vj?Owf$ywWwW!hWB2Fy}RK-jT8@ZVPELw*uNgE}7Q?Tp%vyjesVI ztNBHM4WhdP7jq|o1tMI{odFeya5Zloyl2|pSAUvTFeV*@Ak6>(002ovPDHLkV1k*G B({um; literal 0 HcmV?d00001 diff --git a/src/common/util.ts b/src/common/util.ts index 561c0d647..e5fe0aa84 100644 --- a/src/common/util.ts +++ b/src/common/util.ts @@ -1,4 +1,4 @@ -export const getGeoLocation = () => +export const getGeoLocation = (): Promise => new Promise((resolve, reject) => { navigator.geolocation.getCurrentPosition( position => { @@ -9,3 +9,23 @@ export const getGeoLocation = () => }, ); }); + +export const delay = (ms: number) => + new Promise(resolve => { + setTimeout(() => { + resolve(true); + }, ms); + }); + +export const differenceDate = (checkIn: string, checkOut: string) => + new Date(checkOut).getDate() - new Date(checkIn).getDate(); + +export const getParamsFormat = (config: object) => { + const params = Object.entries(config) + .map(param => { + const [key, value] = param; + return `${key}=${value}`; + }) + .join('&'); + return `?${params}`; +}; diff --git a/src/components/Chart/Graph.tsx b/src/components/Chart/Graph.tsx index df1df4f54..c92ceafcd 100644 --- a/src/components/Chart/Graph.tsx +++ b/src/components/Chart/Graph.tsx @@ -164,7 +164,9 @@ export default function Graph({ priceState, accommodationData }: GraphProps) { } const minPrice = Math.floor(percentage * sliderNewValue[0]); - const maxPrice = Math.floor(percentage * sliderNewValue[1]); + let maxPrice = Math.floor(percentage * sliderNewValue[1]); + + if (minPrice === maxPrice) maxPrice += percentage * sliderInterval; if (activeThumb === 0) { setSliderValue([ diff --git a/src/components/Chart/index.tsx b/src/components/Chart/index.tsx index fb191331d..266450327 100644 --- a/src/components/Chart/index.tsx +++ b/src/components/Chart/index.tsx @@ -74,11 +74,15 @@ export default function Chart() { 가격 범위 - {isCheckDate() && ( + {isCheckDate() ? ( <Graph priceState={priceState} accommodationData={accommodationData} /> + ) : ( + <Typography variant="input2" sx={{ textAlign: 'center' }}> + 체크인, 체크아웃 날짜를 먼저 선택해주세요. + </Typography> )} </FlexBox> </FlexBox> diff --git a/src/components/Header/BigSearchBar/BigMenu.tsx b/src/components/Header/BigSearchBar/BigMenu.tsx index 937bc1a4a..6aa41d33e 100644 --- a/src/components/Header/BigSearchBar/BigMenu.tsx +++ b/src/components/Header/BigSearchBar/BigMenu.tsx @@ -73,17 +73,19 @@ export default function BigMenu({ const handleClickCloseBtn = () => { if (menuType === 'checkin') { calendarDispatch({ type: 'CHECK_IN_DELETE' }); + priceDispatch({ + type: 'SET_INIT_PRICE', + }); } else if (menuType === 'checkout') { calendarDispatch({ type: 'CHECK_OUT_DELETE' }); + priceDispatch({ + type: 'SET_INIT_PRICE', + }); } else if (menuType === 'price') { calendarDispatch({ type: 'CHECK_IN_DELETE' }); calendarDispatch({ type: 'CHECK_OUT_DELETE' }); priceDispatch({ - type: 'SET_PRICE', - initMinPrice: 0, - initMaxPrice: 0, - minPrice: 0, - maxPrice: 0, + type: 'SET_INIT_PRICE', }); } else if (menuType === 'persons') { personDispatch({ type: 'SET_ZERO_PERSONS' }); diff --git a/src/components/Header/BigSearchBar/SearchButton.tsx b/src/components/Header/BigSearchBar/SearchButton.tsx new file mode 100644 index 000000000..1b845ce4e --- /dev/null +++ b/src/components/Header/BigSearchBar/SearchButton.tsx @@ -0,0 +1,55 @@ +import SearchIcon from '@mui/icons-material/Search'; +import { Fab } from '@mui/material'; +import { useCalendarState } from 'react-carousel-calendar'; +import { useNavigate } from 'react-router-dom'; + +import color from '@constants/color'; +import fontSize from '@constants/fontSize'; +import { useHeaderDispatch } from '@contexts/HeaderProvider'; +import { usePersonState } from '@contexts/PersonProvider'; +import { usePriceState } from '@contexts/PriceProvider'; + +export default function SearchButton() { + const navigate = useNavigate(); + const priceState = usePriceState(); + const calendarState = useCalendarState(); + const personState = usePersonState(); + const headerDispatch = useHeaderDispatch(); + + const handleOnclick = () => { + // 서버에 넘길 필요한 데이터? => 여기서 api 요청? + // check_in, check_out, price_min, price_max, adult, child, baby, page, limit, cached_count + headerDispatch({ type: 'BODY_CLICK' }); + navigate('/rooms', { + state: { + check_in: calendarState.checkin, + check_out: calendarState.checkout, + price_min: priceState.minPrice, + price_max: priceState.maxPrice, + adult: personState.adult, + child: personState.child, + baby: personState.baby, + page: 1, + limit: 1, + cached_count: 1000, + }, + }); + }; + + return ( + <Fab + variant="extended" + color="primary" + sx={{ width: '6rem', mr: '1rem', position: 'absolute', right: 0 }} + onClick={handleOnclick} + > + <SearchIcon + sx={{ + color: color.white, + fontSize: fontSize.fontDefault, + }} + /> + <span>검색</span> + </Fab> + ); +} diff --git a/src/components/Header/BigSearchBar/index.tsx b/src/components/Header/BigSearchBar/index.tsx index 1f82ae08d..78cd3fcc0 100644 --- a/src/components/Header/BigSearchBar/index.tsx +++ b/src/components/Header/BigSearchBar/index.tsx @@ -1,23 +1,19 @@ -import SearchIcon from '@mui/icons-material/Search'; -import { Fab } from '@mui/material'; import { Calendar, CalendarProvider } from 'react-carousel-calendar'; -import { useNavigate } from 'react-router-dom'; import Chart from '@components/Chart'; import FlexBox from '@components/FlexBox'; import BigMenus from '@components/Header/BigSearchBar/BigMenus'; import Modal from '@components/Header/BigSearchBar/Modal'; +import SearchButton from '@components/Header/BigSearchBar/SearchButton'; import { MenuType } from '@components/Header/MiniSearchBar/Menu'; import Persons from '@components/Persons'; import color from '@constants/color'; -import fontSize from '@constants/fontSize'; import widths from '@constants/widths'; import { useHeaderDispatch, useHeaderState } from '@contexts/HeaderProvider'; import { PersonProvider } from '@contexts/PersonProvider'; import { PriceProvider } from '@contexts/PriceProvider'; export default function BigSearchBar() { - const navigate = useNavigate(); const headerDispatch = useHeaderDispatch(); const headerState = useHeaderState(); @@ -44,6 +40,7 @@ export default function BigSearchBar() { throw Error('Menu Type not found'); } }; + return ( <CalendarProvider> <PriceProvider> @@ -77,23 +74,7 @@ export default function BigSearchBar() { isSelectedType={isSelectedType} changeMenuType={changeMenuType} /> - <Fab - variant="extended" - color="primary" - sx={{ width: '6rem', mr: '1rem', position: 'absolute', right: 0 }} - onClick={() => { - headerDispatch({ type: 'BODY_CLICK' }); - navigate('/rooms'); - }} - > - <SearchIcon - sx={{ - color: color.white, - fontSize: fontSize.fontDefault, - }} - /> - <span>검색</span> - </Fab> + <SearchButton /> <Modal>{getModalItem()}</Modal> </FlexBox> </PersonProvider> diff --git a/src/components/Header/UserInfo.tsx b/src/components/Header/UserInfo.tsx index 0292cf7df..49b8b1455 100644 --- a/src/components/Header/UserInfo.tsx +++ b/src/components/Header/UserInfo.tsx @@ -1,24 +1,68 @@ import MenuIcon from '@mui/icons-material/Menu'; import PersonIcon from '@mui/icons-material/Person'; -import { Fab, Menu, Fade, MenuItem } from '@mui/material'; -import React, { useState } from 'react'; +import { Fab, Menu, Fade, MenuItem, Avatar } from '@mui/material'; +import React, { useEffect, useState } from 'react'; + +import { getParamsFormat } from '@common/util'; +import { useHeaderState, useHeaderDispatch } from '@contexts/HeaderProvider'; export default function UserInfo() { const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); + const [avatarUrl, setAvatarUrl] = useState(localStorage.getItem('avatarUrl')); + const { isLogin } = useHeaderState(); + const headerDispatch = useHeaderDispatch(); + const open = Boolean(anchorEl); - const handleClick = (event: React.MouseEvent<HTMLElement>) => { + const handleUserInfoClick = (event: React.MouseEvent<HTMLElement>) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; + const handleLoginClick = () => { + const loginBaseUrl = 'https://github.com/login/oauth/authorize'; + const clientId = process.env.GITHUB_CLIENT_ID; + const redirectUri = + process.env.NODE_ENV === 'development' + ? 'http://localhost:3000/callback' + : 'https://puffinbnb.netlify.app/callback'; + if (!clientId) throw Error('Github login client id not found'); + + const githubLoginConfig = { + client_id: clientId, + redirect_uri: redirectUri, + }; + const params = getParamsFormat(githubLoginConfig); + window.location.href = `${loginBaseUrl}${params}`; + }; + + const handleLogoutClick = () => { + headerDispatch({ type: 'LOGOUT' }); + window.location.reload(); + }; + + useEffect(() => { + if (isLogin) { + setAvatarUrl(localStorage.getItem('avatarUrl')); + } else { + setAvatarUrl(null); + localStorage.removeItem('avatarUrl'); + } + }, [isLogin]); + return ( <div> - <Fab variant="extended" color="info" onClick={handleClick}> + <Fab variant="extended" color="info" onClick={handleUserInfoClick}> <MenuIcon /> - <PersonIcon /> + {avatarUrl ? ( + <Avatar src={avatarUrl} sx={{ width: 30, height: 30 }} /> + ) : ( + <Avatar sx={{ width: 30, height: 30 }}> + <PersonIcon /> + </Avatar> + )} </Fab> <Menu id="fade-menu" @@ -42,7 +86,11 @@ export default function UserInfo() { }, }} > - <MenuItem onClick={handleClose}>로그인</MenuItem> + {isLogin ? ( + <MenuItem onClick={handleLogoutClick}>로그아웃</MenuItem> + ) : ( + <MenuItem onClick={handleLoginClick}>로그인</MenuItem> + )} </Menu> </div> ); diff --git a/src/components/Loading.tsx b/src/components/Loading.tsx new file mode 100644 index 000000000..40b2b417a --- /dev/null +++ b/src/components/Loading.tsx @@ -0,0 +1,17 @@ +import { CircularProgress, Box } from '@mui/material'; + +export default function Loading() { + return ( + <Box + sx={{ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + width: '100vw', + height: '100vh', + }} + > + <CircularProgress /> + </Box> + ); +} diff --git a/src/components/Main/AnyWhereBox.tsx b/src/components/Main/CategoryLocations.tsx similarity index 55% rename from src/components/Main/AnyWhereBox.tsx rename to src/components/Main/CategoryLocations.tsx index ef84977ad..643334d91 100644 --- a/src/components/Main/AnyWhereBox.tsx +++ b/src/components/Main/CategoryLocations.tsx @@ -1,18 +1,24 @@ import { Box, Grid, Typography } from '@mui/material'; import FlexBox from '@components/FlexBox'; -import { anywhereData } from '@mocks/main'; +import { IMainPageDatas, ICategoryLocationsInfo } from '@pages/MainPage'; -export default function AnyWhereBox() { +interface CategoryLocationsProps { + categoryLocations: IMainPageDatas<ICategoryLocationsInfo>; +} + +export default function CategoryLocations({ + categoryLocations, +}: CategoryLocationsProps) { return ( <> <Typography variant="h4" sx={{ marginBottom: '2rem' }}> - {anywhereData.title} + {categoryLocations.title} </Typography> <Grid container rowSpacing={4} columnSpacing={4}> - {anywhereData.infos.map(data => ( - <Grid item xs={12} sm={6} md={6} lg={3} xl={3} key={data.uuid}> + {categoryLocations.infos.map((info: ICategoryLocationsInfo) => ( + <Grid item xs={12} sm={6} md={6} lg={3} xl={3} key={info.uuid}> <FlexBox fd="column"> <Box sx={{ @@ -20,10 +26,10 @@ export default function AnyWhereBox() { }} component="img" alt="image" - src={data.image} + src={info.image} /> <Typography sx={{ marginTop: '1rem' }}> - {data.description} + {info.description} </Typography> </FlexBox> </Grid> diff --git a/src/components/Main/NearByBox.tsx b/src/components/Main/NearLocations.tsx similarity index 56% rename from src/components/Main/NearByBox.tsx rename to src/components/Main/NearLocations.tsx index affbc692b..78fad3100 100644 --- a/src/components/Main/NearByBox.tsx +++ b/src/components/Main/NearLocations.tsx @@ -1,18 +1,21 @@ import { Box, Grid, Typography } from '@mui/material'; import FlexBox from '@components/FlexBox'; -import { nearByData } from '@mocks/main'; +import { IMainPageDatas, INearLocationsInfo } from '@pages/MainPage'; -export default function NearByBox() { +interface NearLocationsProps { + nearLocations: IMainPageDatas<INearLocationsInfo>; +} + +export default function NearLocations({ nearLocations }: NearLocationsProps) { return ( <> <Typography variant="h4" sx={{ marginBottom: '2rem' }}> - {nearByData.title} + {nearLocations.title} </Typography> - <Grid container rowSpacing={3} columnSpacing={3}> - {nearByData.infos.map(data => ( - <Grid item xs={12} sm={6} md={6} lg={3} xl={3} key={data.uuid}> + {nearLocations.infos.map((info: INearLocationsInfo) => ( + <Grid item xs={12} sm={6} md={6} lg={3} xl={3} key={info.uuid}> <FlexBox> <Box sx={{ @@ -22,11 +25,11 @@ export default function NearByBox() { }} component="img" alt="image" - src={data.image} + src={info.image} /> <FlexBox fd="column" jc="center" sx={{ marginLeft: '1rem' }}> - <Typography>{data.city}</Typography> - <Typography>{data.description}</Typography> + <Typography>{info.city}</Typography> + <Typography>{info.description}</Typography> </FlexBox> </FlexBox> </Grid> diff --git a/src/components/Main/SkeletonNearLocations.tsx b/src/components/Main/SkeletonNearLocations.tsx new file mode 100644 index 000000000..61d2da92e --- /dev/null +++ b/src/components/Main/SkeletonNearLocations.tsx @@ -0,0 +1,39 @@ +import { Skeleton, Grid } from '@mui/material'; + +import FlexBox from '@components/FlexBox'; + +export default function SkeletonNearLocations() { + return ( + <> + <Skeleton variant="text" height={40} sx={{ borderRadius: '1rem' }} /> + <Grid container rowSpacing={3} columnSpacing={3}> + {new Array(8).fill(0).map((_, idx) => ( + <Grid + item + xs={12} + sm={6} + md={6} + lg={3} + xl={3} + key={`skeleton-nearby-${idx + 1}`} + > + <FlexBox> + <Skeleton + sx={{ + borderRadius: '0.625rem', + }} + width="5rem" + height="5rem" + variant="rectangular" + /> + <FlexBox fd="column" jc="center" sx={{ marginLeft: '1rem' }}> + <Skeleton variant="text" width={100} height={24} /> + <Skeleton variant="text" width={100} height={24} /> + </FlexBox> + </FlexBox> + </Grid> + ))} + </Grid> + </> + ); +} diff --git a/src/components/OAuthCallback.tsx b/src/components/OAuthCallback.tsx new file mode 100644 index 000000000..4259ab62d --- /dev/null +++ b/src/components/OAuthCallback.tsx @@ -0,0 +1,26 @@ +import { useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; + +import Loading from '@components/Loading'; +import { useHeaderDispatch } from '@contexts/HeaderProvider'; +import useFetch, { ResponseState } from '@hooks/useFetch'; + +export default function OAuthCallback() { + const navigate = useNavigate(); + const headerDispatch = useHeaderDispatch(); + const searchParams = new URLSearchParams(window.location.search); + const code = searchParams.get('code'); + const fetchUrl = `https://github-oauth-park.herokuapp.com/api/githubLogin?code=${code}`; + const { isLoading, data }: ResponseState<{ avatarUrl: string }> = + useFetch(fetchUrl); + + useEffect(() => { + if (!isLoading && data) { + headerDispatch({ type: 'LOGIN' }); + localStorage.setItem('avatarUrl', data.avatarUrl); + navigate('/'); + } + }, [data]); + + return <Loading />; +} diff --git a/src/components/SearchResult/Room.tsx b/src/components/SearchResult/Room.tsx new file mode 100644 index 000000000..043dc1cfa --- /dev/null +++ b/src/components/SearchResult/Room.tsx @@ -0,0 +1,141 @@ +import { Grid, Typography, Box, Divider } from '@mui/material'; +import React, { useState } from 'react'; + +import starImage from '@assets/star_img.png'; +import wishImage from '@assets/wish_img.png'; +import { differenceDate } from '@common/util'; +import FlexBox from '@components/FlexBox'; +import RoomModal from '@components/SearchResult/RoomModal'; + +export default function Room({ room, checkIn, checkOut, guest }: any) { + const [open, setOpen] = useState(false); + const [roomDetailData, setRoomDetailData] = useState({ + id: 0, + dailyPrice: 0, + reviewCount: 0, + ratingStarScore: 0, + }); + + const { + title, + imageUrl, + dailyPrice, + reviewCount, + ratingStarScore, + maximumNum, + bathroomCount, + bedCount, + bedroomCount, + } = room; + + const getRoomDetailOptions = () => + `최대 인원 ${maximumNum}명 침대 ${bedCount}개 욕실 ${bathroomCount}개 주방 무선 인터넷 에어컨 헤어드라이어`; + + const handleOnClick = async (e: React.MouseEvent<HTMLDivElement>) => { + if (e.target.id === 'wish') return; + setOpen(true); + // /api/rooms/id 비동기 요청 후 state Setting + fetch('http://localhost:3000/room.json') + .then(res => res.json()) + .then(res => { + if (res.data) { + setRoomDetailData(res.data); + } + }); + }; + + const priceSum = () => dailyPrice * differenceDate(checkIn, checkOut); + + return ( + <> + <Grid + container + sx={{ + cursor: 'pointer', + padding: '1rem', + '&:hover': { + boxShadow: '0 2px 4px rgba(0,0,0,0.18)', + }, + }} + onClick={handleOnClick} + > + <Grid item> + <Box + sx={{ + width: '20.625rem', + height: '12.5rem', + borderRadius: '0.6rem', + marginRight: '1.5rem', + }} + component="img" + alt="roomImage" + src={imageUrl} + /> + </Grid> + <Grid item xs={12} sm container> + <Grid item xs container direction="column" spacing={2}> + <Grid item xs> + <FlexBox jc="space-between"> + <Typography + variant="body2" + color="text.secondary" + sx={{ marginBottom: '0.5rem' }} + > + 지도 위치 + </Typography> + <Box + id="wish" + sx={{ width: '20px', height: '18px', cursor: 'pointer' }} + component="img" + src={wishImage} + /> + </FlexBox> + <Typography variant="body2" sx={{ marginBottom: '0.5rem' }}> + {title} + </Typography> + <Typography variant="body2" color="text.secondary"> + {getRoomDetailOptions()} + </Typography> + </Grid> + <Grid item> + <FlexBox sx={{ fontSize: '0.875rem' }} jc="flex-end" ai="center"> + <Typography sx={{ fontWeight: '700' }}> + ₩{dailyPrice.toLocaleString()} + </Typography> +  / 박 + </FlexBox> + </Grid> + <Grid + item + sx={{ display: 'flex', justifyContent: 'space-between' }} + > + <FlexBox ai="center" sx={{ gap: '5px' }}> + <Box + sx={{ width: '0.8125rem', height: '0.75rem' }} + component="img" + src={starImage} + /> + <Typography>{ratingStarScore}</Typography> + <Typography variant="input2">(후기{reviewCount}개)</Typography> + </FlexBox> + <Typography variant="input2" sx={{ textDecoration: 'underline' }}> + 총액 ₩{priceSum().toLocaleString()} + </Typography> + </Grid> + </Grid> + </Grid> + </Grid> + <Divider orientation="horizontal" /> + + {/* Modal을 여기 아래에서 호출해주는게 맞는걸까... */} + <RoomModal + open={open} + setOpen={setOpen} + checkIn={checkIn} + checkOut={checkOut} + guest={guest} + roomDetailData={roomDetailData} + /> + </> + ); +} diff --git a/src/components/SearchResult/RoomModal.tsx b/src/components/SearchResult/RoomModal.tsx new file mode 100644 index 000000000..f7b0b2592 --- /dev/null +++ b/src/components/SearchResult/RoomModal.tsx @@ -0,0 +1,184 @@ +import { Typography, Box, Divider, Button, Modal } from '@mui/material'; +import moment from 'moment'; + +import { differenceDate } from '@common/util'; +import FlexBox from '@components/FlexBox'; +import color from '@constants/color'; + +interface RoomModalProps { + open: boolean; + setOpen: React.Dispatch<React.SetStateAction<boolean>>; + roomDetailData: any; + checkIn: string; + checkOut: string; + guest: number; +} + +const modalStyle = { + width: '25rem', + height: '33.875rem', + position: 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + bgcolor: 'background.paper', + borderRadius: '0.625rem', + padding: '1.5rem', +}; + +export default function RoomModal({ + open, + setOpen, + checkIn, + checkOut, + guest, + roomDetailData, +}: RoomModalProps) { + return ( + <Modal open={open} onClose={() => setOpen(false)} disableScrollLock> + <FlexBox sx={modalStyle} fd="column"> + <Box sx={{ marginBottom: '1.5rem' }}> + <FlexBox jc="space-between"> + <FlexBox> + <Typography sx={{ fontWeight: '700' }}> + ₩{roomDetailData.dailyPrice.toLocaleString()} + </Typography> +  / 박 + </FlexBox> + <Typography + variant="input2" + sx={{ textDecoration: 'underline', fontWeight: '700' }} + > + 후기 {roomDetailData.reviewCount}개 + </Typography> + </FlexBox> + </Box> + <FlexBox + sx={{ + width: '22rem', + height: '6.68rem', + marginBottom: '1rem', + border: 1, + borderColor: color.grey4, + borderRadius: '0.625rem', + }} + fd="column" + > + <FlexBox + sx={{ + height: '50%', + borderBottom: 1, + borderColor: color.grey4, + }} + ai="center" + > + <FlexBox + sx={{ + width: '50%', + height: '100%', + padding: '0 1rem', + borderRight: 1, + borderColor: color.grey4, + }} + fd="column" + jc="center" + > + <Typography sx={{ fontSize: '0.75rem', fontWeight: 700 }}> + 체크인 + </Typography> + <Typography variant="input2"> + {moment(checkIn).format('YYYY. M. D.')} + </Typography> + </FlexBox> + <FlexBox + sx={{ width: '50%', height: '100%', padding: '0 1rem' }} + fd="column" + jc="center" + > + <Typography sx={{ fontSize: '0.75rem', fontWeight: 700 }}> + 체크아웃 + </Typography> + <Typography variant="input2"> + {moment(checkOut).format('YYYY. M. D.')} + </Typography> + </FlexBox> + </FlexBox> + <FlexBox + sx={{ height: '50%', padding: '0 1rem' }} + fd="column" + jc="center" + > + <Typography sx={{ fontSize: '0.75rem', fontWeight: 700 }}> + 인원 + </Typography> + <Typography variant="input2">게스트 {guest}명</Typography> + </FlexBox> + </FlexBox> + <Button + sx={{ + width: '22rem', + height: '3.43rem', + borderRadius: '0.625rem', + marginBottom: '1rem', + color: color.white, + backgroundColor: color.black, + '&:hover': { + backgroundColor: color.grey3, + }, + }} + > + 예약하기 + </Button> + <Typography + variant="input2" + sx={{ textAlign: 'center', marginBottom: '1.68rem' }} + > + 예약 확정 전에는 요금이 청구되지 않습니다. + </Typography> + <Box sx={{ marginBottom: '1rem' }}> + <FlexBox jc="space-between" sx={{ marginBottom: '0.5rem' }}> + <Typography sx={{ textDecoration: 'underline' }}> + ₩{roomDetailData.dailyPrice.toLocaleString()} x{' '} + {differenceDate(checkIn, checkOut)}박 + </Typography> + <Typography> + ₩ + {( + roomDetailData.dailyPrice * differenceDate(checkIn, checkOut) + ).toLocaleString()} + </Typography> + </FlexBox> + <FlexBox jc="space-between" sx={{ marginBottom: '0.5rem' }}> + <Typography sx={{ textDecoration: 'underline' }}> + 주 단위 요금 할인 + </Typography> + <Typography>₩0</Typography> + </FlexBox> + <FlexBox jc="space-between" sx={{ marginBottom: '0.5rem' }}> + <Typography sx={{ textDecoration: 'underline' }}>청소비</Typography> + <Typography>₩0</Typography> + </FlexBox> + <FlexBox jc="space-between" sx={{ marginBottom: '0.5rem' }}> + <Typography sx={{ textDecoration: 'underline' }}> + 서비스 수수료 + </Typography> + <Typography>₩0</Typography> + </FlexBox> + <FlexBox jc="space-between" sx={{ marginBottom: '0.5rem' }}> + <Typography sx={{ textDecoration: 'underline' }}> + 숙박세와 수수료 + </Typography> + <Typography>₩0</Typography> + </FlexBox> + </Box> + <Divider orientation="horizontal" sx={{ marginBottom: '1rem' }} /> + <FlexBox jc="space-between"> + <Typography sx={{ textDecoration: 'underline', fontWeight: 700 }}> + 총 합계 + </Typography> + <Typography>가격</Typography> + </FlexBox> + </FlexBox> + </Modal> + ); +} diff --git a/src/components/SearchResult/Rooms.tsx b/src/components/SearchResult/Rooms.tsx new file mode 100644 index 000000000..610dbf358 --- /dev/null +++ b/src/components/SearchResult/Rooms.tsx @@ -0,0 +1,88 @@ +import { Box, Stack, Typography } from '@mui/material'; +import moment from 'moment'; + +import Room from '@components/SearchResult/Room'; + +interface RoomProps { + title: string; + imageUrl: string; + dailyPrice: number; + reviewCount: number; + ratingStarScore: number; + maximumNum: number; + bathroomCount: number; + bedCount: number; + bedroomCount: number; +} + +export interface SearchDataListProps { + check_in: string; + check_out: string; + price_min: number; + price_max: number; + adult: number; + child: number; + baby: number; + page: number; + limit: number; + cached_count: number; +} + +interface RoomListType { + totalElements: number; + content: RoomProps[]; +} + +interface RoomsProps { + roomList: RoomListType; + searchDataList: SearchDataListProps; +} + +export default function Rooms({ roomList, searchDataList }: RoomsProps) { + const { + check_in: checkIn, + check_out: checkOut, + price_min: minPrice, + price_max: maxPrice, + adult, + child, + baby, + } = searchDataList; + + const getGuestNum = () => adult + child + baby; + + const getTitle = () => { + const roomCount = Math.floor(roomList.totalElements / 100) * 100; + + const guest = getGuestNum(); + + return `${roomCount}개 이상의 숙소 ${moment(checkIn).format( + 'M월 D일', + )} ~ ${moment(checkOut).format( + 'M월 D일', + )} ₩${minPrice.toLocaleString()} ~ ₩${maxPrice.toLocaleString()} 게스트${guest}명`; + }; + + return ( + <Stack spacing={2} sx={{ padding: '1rem', overflow: 'auto' }}> + <Box sx={{ padding: '1rem' }}> + <Typography variant="input1">{getTitle()}</Typography> + <Typography + variant="h2" + sx={{ margin: '1rem 0', fontSize: '2rem', fontWeight: 900 }} + > + 지도에서 선택한 지역의 숙소 + </Typography> + </Box> + {roomList?.content?.map((room: RoomProps, idx: number) => ( + <Room + key={`room-${idx + 1}`} + room={room} + checkIn={checkIn} + checkOut={checkOut} + guest={getGuestNum()} + /> + ))} + </Stack> + ); +} diff --git a/src/contexts/HeaderProvider.tsx b/src/contexts/HeaderProvider.tsx index cfae70fd4..31354d5e3 100644 --- a/src/contexts/HeaderProvider.tsx +++ b/src/contexts/HeaderProvider.tsx @@ -5,18 +5,22 @@ import { MenuType } from '@components/Header/MiniSearchBar/Menu'; export interface HeaderState { menuType: MenuType; isFocus: boolean; + isLogin: boolean; } type Action = | { type: 'TOGGLE_FOCUS'; menuType: MenuType } | { type: 'CHANGE_MENU_TYPE'; menuType: MenuType } - | { type: 'BODY_CLICK' }; + | { type: 'BODY_CLICK' } + | { type: 'LOGIN' } + | { type: 'LOGOUT' }; type HeaderDispatch = Dispatch<Action>; const initHeaderState: HeaderState = { menuType: 'none', isFocus: false, + isLogin: !!localStorage.getItem('avatarUrl'), }; const HeaderStateContext = createContext<HeaderState | null>(null); @@ -24,13 +28,24 @@ const HeaderDispatchContext = createContext<HeaderDispatch | null>(null); function reducer(state: HeaderState, action: Action): HeaderState { switch (action.type) { + case 'LOGIN': + return { + ...state, + isLogin: true, + }; + case 'LOGOUT': + return { + ...state, + isLogin: false, + }; case 'TOGGLE_FOCUS': return { + ...state, menuType: action.menuType, isFocus: !state.isFocus, }; case 'BODY_CLICK': - return { ...initHeaderState }; + return { ...initHeaderState, isLogin: state.isLogin }; case 'CHANGE_MENU_TYPE': return { ...state, diff --git a/src/contexts/PriceProvider.tsx b/src/contexts/PriceProvider.tsx index d521c864d..8df8ab267 100644 --- a/src/contexts/PriceProvider.tsx +++ b/src/contexts/PriceProvider.tsx @@ -8,6 +8,7 @@ export interface PriceState { } type Action = + | { type: 'SET_INIT_PRICE' } | { type: 'MIN_PRICE'; minPrice: number; maxPrice: number } | { type: 'MAX_PRICE'; minPrice: number; maxPrice: number } | { @@ -32,6 +33,13 @@ const PriceDispatchContext = createContext<PriceDispatch | null>(null); function reducer(state: PriceState, action: Action): PriceState { switch (action.type) { + case 'SET_INIT_PRICE': + return { + initMinPrice: 0, + initMaxPrice: 0, + minPrice: 0, + maxPrice: 0, + }; case 'SET_PRICE': return { ...state, diff --git a/src/hooks/useFetch.tsx b/src/hooks/useFetch.tsx new file mode 100644 index 000000000..5bffd2b79 --- /dev/null +++ b/src/hooks/useFetch.tsx @@ -0,0 +1,71 @@ +import { useEffect, useReducer } from 'react'; + +export interface ResponseState<T> { + data?: T; + error?: Error; + isLoading: boolean; +} + +type Action<T> = + | { type: 'LOADING' } + | { type: 'FETCHED'; payload: T } + | { type: 'ERROR'; payload: Error }; + +export default function useFetch<T>( + url: string, + options?: RequestInit, +): ResponseState<T> { + const initState: ResponseState<T> = { + data: undefined, + error: undefined, + isLoading: false, + }; + + function reducer( + state: ResponseState<T>, + action: Action<T>, + ): ResponseState<T> { + switch (action.type) { + case 'LOADING': + return { ...state, isLoading: true }; + case 'FETCHED': + return { + ...state, + isLoading: false, + data: action.payload, + }; + case 'ERROR': + return { + ...state, + isLoading: false, + error: action.payload, + }; + default: + throw Error('Unexpected action on useFetch'); + } + } + + const [state, dispatch] = useReducer(reducer, initState); + + useEffect(() => { + if (!url) return; + + const fetchData = async () => { + dispatch({ type: 'LOADING' }); + try { + const response = await fetch(url, options); + if (!response.ok) { + throw new Error(response.statusText); + } + const payload = await response.json(); + dispatch({ type: 'FETCHED', payload }); + } catch (error) { + dispatch({ type: 'ERROR', payload: error as Error }); + } + }; + + fetchData(); + }, []); + + return state; +} diff --git a/src/hooks/useThrottle.jsx b/src/hooks/useThrottle.jsx deleted file mode 100644 index 55f549d94..000000000 --- a/src/hooks/useThrottle.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import { useRef } from 'react'; - -const useThrottle = (callback, delay) => { - const timer = useRef(null); - return (...args) => { - if (!timer.current) { - callback(...args); - timer.current = setTimeout(() => { - timer.current = null; - }, delay); - } - }; -}; - -export default useThrottle; diff --git a/src/index.tsx b/src/index.tsx index a39768a42..778ffb307 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,12 +1,14 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; +// if (process.env.NODE_ENV === 'development') +// 원래는 개발환경에서만 쓰지만 백엔드 없이 작업하므로 그대로 진행 +import { serviceWorker } from '@server/browser'; + import App from './App'; +serviceWorker.start(); + const root = ReactDOM.createRoot(document.getElementById('root')!); -root.render( - <React.StrictMode> - <App /> - </React.StrictMode>, -); +root.render(<App />); diff --git a/src/pages/MainPage.tsx b/src/pages/MainPage.tsx index 718418eab..bf8e5fbe7 100644 --- a/src/pages/MainPage.tsx +++ b/src/pages/MainPage.tsx @@ -2,20 +2,68 @@ import { Box, Container } from '@mui/material'; import Background from '@components/Background'; import Footer from '@components/Footer'; -import AnyWhereBox from '@components/Main/AnyWhereBox'; -import NearByBox from '@components/Main/NearByBox'; +import CategoryLocations from '@components/Main/CategoryLocations'; +import NearLocations from '@components/Main/NearLocations'; +import SkeletonNearLocations from '@components/Main/SkeletonNearLocations'; +import useFetch, { ResponseState } from '@hooks/useFetch'; + +export interface INearLocationsInfo { + uuid: number; + city: string; + description: string; + image: string; +} + +export interface ICategoryLocationsInfo { + uuid: number; + image: string; + description: string; +} + +export interface IMainPageDatas<T> { + title: string; + infos: T[]; +} + +type NearLocationsResponse = ResponseState<IMainPageDatas<INearLocationsInfo>>; + +type CategoryLocationsResponse = ResponseState< + IMainPageDatas<ICategoryLocationsInfo> +>; export default function MainPage() { + const { + isLoading: categoryLoading, + data: categoryLocations, + }: CategoryLocationsResponse = useFetch('/api/categoryLocations'); + + const { isLoading: nearLoading, data: nearLocations }: NearLocationsResponse = + useFetch('/api/nearLocations'); + + /** + * TODO: Type Guard 관련 + * !nearLocations -> Error 페이지를 보여줘야 하는게 좋아보임 + * 임시로 !nearLocations 이면 Skeleton 을 보여주는 것으로 대체 + */ + return ( <> <Container maxWidth="lg"> <Box sx={{ margin: '0 auto' }}> <Background /> <Box sx={{ marginBottom: '5rem' }}> - <NearByBox /> + {nearLoading || !nearLocations ? ( + <SkeletonNearLocations /> + ) : ( + <NearLocations nearLocations={nearLocations} /> + )} </Box> <Box sx={{ marginBottom: '5rem' }}> - <AnyWhereBox /> + {categoryLoading || !categoryLocations ? ( + <SkeletonNearLocations /> + ) : ( + <CategoryLocations categoryLocations={categoryLocations} /> + )} </Box> </Box> </Container> diff --git a/src/pages/SearchResultPage.tsx b/src/pages/SearchResultPage.tsx index 1deade19f..3326dc178 100644 --- a/src/pages/SearchResultPage.tsx +++ b/src/pages/SearchResultPage.tsx @@ -1,7 +1,9 @@ import { Box, Skeleton } from '@mui/material'; import { useEffect, useRef, useState } from 'react'; +import { useLocation } from 'react-router-dom'; -import { getGeoLocation } from '@common/util'; +import { getGeoLocation, delay } from '@common/util'; +import Rooms, { SearchDataListProps } from '@components/SearchResult/Rooms'; import SkeletonRooms from '@components/SearchResult/SkeletonRooms'; const { kakao } = window; @@ -13,17 +15,24 @@ const wrapperStyle = { marginTop: '5.875rem', }; -const delay = (ms: number) => - new Promise(resolve => { - setTimeout(() => { - resolve(true); - }, ms); - }); - export default function SearchResultPage() { const mapRef = useRef(); + const location = useLocation(); + const [roomList, setRoomList] = useState([]); + const [searchDataList, setSearchDataList] = useState<SearchDataListProps>({ + check_in: '', + check_out: '', + price_min: 0, + price_max: 0, + adult: 0, + child: 0, + baby: 0, + page: 0, + limit: 0, + cached_count: 0, + }); const [isLoading, setIsLoading] = useState(false); - const [userGeolocation, setUserGeoLocation] = useState([]); + const [userGeolocation, setUserGeoLocation] = useState<number[]>([]); useEffect(() => { const getUserGeoLocation = async () => { @@ -56,10 +65,26 @@ export default function SearchResultPage() { } }, [userGeolocation]); + useEffect(() => { + // location.state의 값으로 서버에 파라미터 담아서 비동기 요청 + setSearchDataList(location.state); + fetch('/api/rooms') + .then(res => res.json()) + .then(res => { + if (res.data) { + setRoomList(res.data); + } + }); + }, []); + return ( <Box sx={wrapperStyle}> - <SkeletonRooms /> - <Box ref={mapRef}> + {roomList ? ( + <Rooms roomList={roomList} searchDataList={searchDataList} /> + ) : ( + <SkeletonRooms /> + )} + <Box ref={mapRef} sx={{ height: '100vh' }}> {isLoading && <Skeleton variant="rectangular" height="100%" />} </Box> </Box> diff --git a/src/server/browser.ts b/src/server/browser.ts new file mode 100644 index 000000000..9ca3f3216 --- /dev/null +++ b/src/server/browser.ts @@ -0,0 +1,5 @@ +import { setupWorker } from 'msw'; + +import { handlers } from '@server/handlers'; + +export const serviceWorker = setupWorker(...handlers()); diff --git a/src/server/dummyData/categoryLocations.js b/src/server/dummyData/categoryLocations.js new file mode 100644 index 000000000..63c9c14d8 --- /dev/null +++ b/src/server/dummyData/categoryLocations.js @@ -0,0 +1,31 @@ +const categoryLocations = { + title: '어디서나, 여행은 살아보는 거야!', + infos: [ + { + uuid: 10, + image: + 'https://images.unsplash.com/photo-1512917774080-9991f1c4c750?auto=format&w=350&dpr=2', + description: '자연생활을 만끽할 수 있는 숙소', + }, + { + uuid: 11, + image: + 'https://images.unsplash.com/photo-1512917774080-9991f1c4c750?auto=format&w=350&dpr=2', + description: '독특한 공간', + }, + { + uuid: 12, + image: + 'https://images.unsplash.com/photo-1512917774080-9991f1c4c750?auto=format&w=350&dpr=2', + description: '집 전체', + }, + { + uuid: 13, + image: + 'https://images.unsplash.com/photo-1512917774080-9991f1c4c750?auto=format&w=350&dpr=2', + description: '반려동물 동반 기능', + }, + ], +}; + +export default categoryLocations; diff --git a/src/mocks/main.js b/src/server/dummyData/nearLocations.js similarity index 65% rename from src/mocks/main.js rename to src/server/dummyData/nearLocations.js index 0fb9eb417..831593d41 100644 --- a/src/mocks/main.js +++ b/src/server/dummyData/nearLocations.js @@ -1,4 +1,4 @@ -const nearByData = { +const nearLocations = { title: '가까운 여행지 둘러보기', infos: [ { @@ -60,34 +60,4 @@ const nearByData = { ], }; -const anywhereData = { - title: '어디서나, 여행은 살아보는 거야!', - infos: [ - { - uuid: 10, - image: - 'https://images.unsplash.com/photo-1512917774080-9991f1c4c750?auto=format&w=350&dpr=2', - description: '자연생활을 만끽할 수 있는 숙소', - }, - { - uuid: 11, - image: - 'https://images.unsplash.com/photo-1512917774080-9991f1c4c750?auto=format&w=350&dpr=2', - description: '독특한 공간', - }, - { - uuid: 12, - image: - 'https://images.unsplash.com/photo-1512917774080-9991f1c4c750?auto=format&w=350&dpr=2', - description: '집 전체', - }, - { - uuid: 13, - image: - 'https://images.unsplash.com/photo-1512917774080-9991f1c4c750?auto=format&w=350&dpr=2', - description: '반려동물 동반 기능', - }, - ], -}; - -export { nearByData, anywhereData }; +export default nearLocations; diff --git a/src/server/dummyData/roomDetail.js b/src/server/dummyData/roomDetail.js new file mode 100644 index 000000000..2a1a4e1a8 --- /dev/null +++ b/src/server/dummyData/roomDetail.js @@ -0,0 +1,44 @@ +const roomDetailList = [ + { + data: { + id: 61, + title: '유한회사 송이이 민박', + imageUrls: [ + 'http://tong.visitkorea.or.kr/cms/resource/83/1843083_image2_1.jpg', + ], + address: 'Hongseong충청남도 성남시 강남대거리', + hostName: '최정자', + hostImageUrl: + 'https://i.picsum.photos/id/440/50/50.jpg?hmac=w_6InceAcZY4Z3EmHus0JpoazjTEcfbeben7UHGcqBI', + headCountCapacity: 7, + bedCount: 3, + bedroomCount: 1, + bathroomCount: 1, + description: + 'Velit cum aliquid impedit voluptatibus voluptate. Temporibus ut veritatis.', + dailyPrice: 237800, + reviewCount: 119, + ratingStarScore: 1.47, + checkWish: false, + hasAllInfoPrice: false, + detailPrice: { + checkIn: null, + checkOut: null, + dayCount: null, + headCount: null, + totalOriginalPrice: null, + dailyOriginalPrice: null, + saleRatio: null, + savedPrice: null, + cleanigFee: null, + serviceFee: null, + lodgingTaxRatio: null, + lodgingTax: null, + fixedDailyPrice: null, + fixedTotalPrice: null, + }, + }, + }, +]; + +export default roomDetailList; diff --git a/src/server/dummyData/roomList.js b/src/server/dummyData/roomList.js new file mode 100644 index 000000000..ef8cc4c0b --- /dev/null +++ b/src/server/dummyData/roomList.js @@ -0,0 +1,179 @@ +const roomList = { + data: { + content: [ + { + id: 61, + title: '유한회사 송이이 민박', + imageUrl: + 'http://tong.visitkorea.or.kr/cms/resource/83/1843083_image2_1.jpg', + lat: 36.6009, + lng: 126.665, + dailyPrice: 237800, + reviewCount: 119, + ratingStarScore: 1.47, + maximumNum: 4, + bathroomCount: 2, + bedCount: 4, + bedroomCount: 2, + }, + { + id: 73, + title: '주식회사 이황이 멘션', + imageUrl: + 'http://tong.visitkorea.or.kr/cms/resource/39/1981439_image2_1.jpg', + lat: 37.65639, + lng: 126.835, + dailyPrice: 119400, + reviewCount: 449, + ratingStarScore: 1.19, + maximumNum: 4, + bathroomCount: 2, + bedCount: 4, + bedroomCount: 2, + }, + { + id: 78, + title: '김박 아파트', + imageUrl: + 'http://tong.visitkorea.or.kr/cms/resource/73/2436173_image2_1.jpg', + lat: 37.65639, + lng: 126.835, + dailyPrice: 227800, + reviewCount: 144, + ratingStarScore: 3.65, + maximumNum: 4, + bathroomCount: 2, + bedCount: 4, + bedroomCount: 2, + }, + { + id: 80, + title: '이김안 민박', + imageUrl: + 'http://tong.visitkorea.or.kr/cms/resource/78/1609978_image2_1.jpg', + lat: 37.65639, + lng: 126.835, + dailyPrice: 130600, + reviewCount: 255, + ratingStarScore: 2.86, + maximumNum: 4, + bathroomCount: 2, + bedCount: 4, + bedroomCount: 2, + }, + { + id: 82, + title: '이윤 도미토리', + imageUrl: + 'http://tong.visitkorea.or.kr/cms/resource/99/1593599_image2_1.jpg', + lat: 37.65639, + lng: 126.835, + dailyPrice: 508600, + reviewCount: 447, + ratingStarScore: 2.21, + maximumNum: 4, + bathroomCount: 2, + bedCount: 4, + bedroomCount: 2, + }, + { + id: 90, + title: '장김 호텔', + imageUrl: + 'http://tong.visitkorea.or.kr/cms/resource/12/2652012_image2_1.jpg', + lat: 36.6009, + lng: 126.665, + dailyPrice: 441500, + reviewCount: 435, + ratingStarScore: 1.73, + maximumNum: 4, + bathroomCount: 2, + bedCount: 4, + bedroomCount: 2, + }, + { + id: 94, + title: '한김 게스트하우스', + imageUrl: null, + lat: 36.6009, + lng: 126.665, + dailyPrice: 527400, + reviewCount: 221, + ratingStarScore: 2.88, + maximumNum: 4, + bathroomCount: 2, + bedCount: 4, + bedroomCount: 2, + }, + { + id: 99, + title: '이고강 멘션', + imageUrl: null, + lat: 37.65639, + lng: 126.835, + dailyPrice: 597800, + reviewCount: 139, + ratingStarScore: 2.22, + maximumNum: 4, + bathroomCount: 2, + bedCount: 4, + bedroomCount: 2, + }, + { + id: 106, + title: '김박오 모텔', + imageUrl: null, + lat: 37.65639, + lng: 126.835, + dailyPrice: 540900, + reviewCount: 310, + ratingStarScore: 2.38, + maximumNum: 4, + bathroomCount: 2, + bedCount: 4, + bedroomCount: 2, + }, + { + id: 109, + title: '김이 도미토리', + imageUrl: null, + lat: 36.6009, + lng: 126.665, + dailyPrice: 574000, + reviewCount: 34, + ratingStarScore: 2.18, + maximumNum: 4, + bathroomCount: 2, + bedCount: 4, + bedroomCount: 2, + }, + ], + pageable: { + sort: { + empty: true, + sorted: false, + unsorted: true, + }, + offset: 10, + pageNumber: 1, + pageSize: 10, + paged: true, + unpaged: false, + }, + totalPages: 277, + totalElements: 2766, + last: false, + number: 1, + sort: { + empty: true, + sorted: false, + unsorted: true, + }, + size: 10, + numberOfElements: 10, + first: false, + empty: false, + }, +}; + +export default roomList; diff --git a/src/server/handlers.ts b/src/server/handlers.ts new file mode 100644 index 000000000..f4bba256d --- /dev/null +++ b/src/server/handlers.ts @@ -0,0 +1,37 @@ +import { rest } from 'msw'; + +import { delay } from '@common/util'; +import categoryLocations from '@server/dummyData/categoryLocations'; +import nearLocations from '@server/dummyData/nearLocations'; +import roomList from '@server/dummyData/roomList'; + +const getRooms: Parameters<typeof rest.get>[1] = async (_, res, ctx) => { + await delay(1000); + return res(ctx.status(200), ctx.json(roomList)); +}; + +const getNearLocations: Parameters<typeof rest.get>[1] = async ( + _, + res, + ctx, +) => { + await delay(1000); + return res(ctx.status(200), ctx.json(nearLocations)); +}; + +const getCategoryLocations: Parameters<typeof rest.get>[1] = async ( + _, + res, + ctx, +) => { + await delay(1000); + return res(ctx.status(200), ctx.json(categoryLocations)); +}; + +export function handlers() { + return [ + rest.get('/api/nearLocations', getNearLocations), + rest.get('/api/categoryLocations', getCategoryLocations), + rest.get('/api/rooms', getRooms), + ]; +} diff --git a/tsconfig.json b/tsconfig.json index 082bf1009..ca5c073c5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,7 +22,8 @@ "@assets/*": ["src/assets/*"], "@mocks/*": ["src/mocks/*"], "@contexts/*": ["src/contexts/*"], - "@hooks/*": ["src/hooks/*"] + "@hooks/*": ["src/hooks/*"], + "@server/*": ["src/server/*"] } }, "include": ["src"], diff --git a/webpack.config.js b/webpack.config.js index ed61c9435..975cac04d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -8,7 +8,7 @@ const webpack = require('webpack'); dotenv.config(); const mode = process.env.NODE_ENV || 'development'; -const { KAKAO_MAP_KEY } = process.env; +const { KAKAO_MAP_KEY, NODE_ENV, GITHUB_CLIENT_ID } = process.env; const PORT = 3000; @@ -29,6 +29,7 @@ module.exports = { '@mocks': path.resolve(__dirname, 'src/mocks'), '@contexts': path.resolve(__dirname, 'src/contexts'), '@hooks': path.resolve(__dirname, 'src/hooks'), + '@server': path.resolve(__dirname, 'src/server'), }, }, module: { @@ -59,6 +60,8 @@ module.exports = { }), new webpack.EnvironmentPlugin({ KAKAO_MAP_KEY, + NODE_ENV, + GITHUB_CLIENT_ID, }), ], stats: 'errors-only',