diff --git a/javascript-vendingmachine-precourse/.gitignore b/javascript-vendingmachine-precourse/.gitignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/javascript-vendingmachine-precourse/.gitignore
@@ -0,0 +1 @@
+node_modules
diff --git a/javascript-vendingmachine-precourse/.npmrc b/javascript-vendingmachine-precourse/.npmrc
new file mode 100644
index 0000000..c42da84
--- /dev/null
+++ b/javascript-vendingmachine-precourse/.npmrc
@@ -0,0 +1 @@
+engine-strict = true
diff --git a/javascript-vendingmachine-precourse/LICENSE b/javascript-vendingmachine-precourse/LICENSE
new file mode 100644
index 0000000..2a91af0
--- /dev/null
+++ b/javascript-vendingmachine-precourse/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 woowacourse
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/javascript-vendingmachine-precourse/README.md b/javascript-vendingmachine-precourse/README.md
new file mode 100644
index 0000000..aebfcb9
--- /dev/null
+++ b/javascript-vendingmachine-precourse/README.md
@@ -0,0 +1,206 @@
+
+
+
+μνκΈ°
+
+## π μ§νλ°©μ
+
+- λ―Έμ
μ **κΈ°λ₯ μꡬμ¬ν, νλ‘κ·Έλλ° μꡬμ¬ν, κ³Όμ μ§ν μꡬμ¬ν** μΈ κ°μ§λ‘ ꡬμ±λμ΄ μλ€.
+- μΈ κ°μ μꡬμ¬νμ λ§μ‘±νκΈ° μν΄ λ
Έλ ₯νλ€. νΉν κΈ°λ₯μ ꡬννκΈ° μ μ κΈ°λ₯ λͺ©λ‘μ λ§λ€κ³ , κΈ°λ₯ λ¨μλ‘ μ»€λ° νλ λ°©μμΌλ‘ μ§ννλ€.
+- κΈ°λ₯ μꡬμ¬νμ κΈ°μ¬λμ§ μμ λ΄μ©μ μ€μ€λ‘ νλ¨νμ¬ κ΅¬ννλ€.
+
+
+## π― κΈ°λ₯ μꡬ μ¬ν
+λ°νλλ λμ μ΄ μ΅μνμ΄ λλ μνκΈ°λ₯Ό ꡬννλ€.
+### 1) 곡ν΅
+
+μλ¨μΒ `ν`λ©λ΄κ° μ‘΄μ¬νλ©° κ° νμ λ°λΌ μ μ ν κΈ°λ₯μ μννλ€.
+
+- `μν κ΄λ¦¬`νμ μνκΈ°κ° λ³΄μ νκ³ μλΒ **μνμ μΆκ°**νλ κΈ°λ₯μ μννλ€.
+- `μλ μΆ©μ `νμΒ **μνκΈ°κ° λ³΄μ ν κΈμ‘μ μΆ©μ **νλ κΈ°λ₯μ μννλ€.
+- `μν ꡬ맀`νμ μ¬μ©μκ°Β **κΈμ‘μ ν¬μ
**ν μ μμΌλ©°, ν¬μ
ν κΈμ‘μ λ§μΆ°Β **μνμ ꡬ맀**νκ³ , λ¨μ κΈμ‘μ λν΄μλΒ **μλμ λ°ν**νλ κΈ°λ₯μ μννλ€.
+- λ€λ₯Έ νμΌλ‘ μ΄λνλ€ λμμλ κΈ°μ‘΄ νμ μνκ° μ μ§λμ΄μΌ νλ€.
+- localStorageλ₯Ό μ΄μ©νμ¬, μλ‘κ³ μΉ¨νλλΌλ κ°μ₯ μ΅κ·Όμ μμ
ν μ 보λ€μ λΆλ¬μ¬ μ μλλ‘ νλ€.
+
+### 2) μν κ΄λ¦¬ ν
+
+`μν κ΄λ¦¬`νμμ, λ€μκ³Ό κ°μ κ·μΉμ λ°νμΌλ‘ μνμ μΆκ°νλ€.
+
+- μ΅μ΄ μν λͺ©λ‘μ λΉμμ§ μνμ΄λ€.
+- μνλͺ
, κ°κ²©, μλμ μ
λ ₯ν΄ μνμ μΆκ°ν μ μλ€.
+ - μν κ°κ²©μ 100μλΆν° μμνλ©°, 10μμΌλ‘ λλμ΄ λ¨μ΄μ ΈμΌ νλ€.
+- μ¬μ©μλ μΆκ°ν μνμ νμΈν μ μλ€.
+
+### 3) μλ μΆ©μ ν (μνκΈ° 보μ λμ )
+
+`μλ μΆ©μ `Β νμμ, λ€μκ³Ό κ°μ κ·μΉμΌλ‘ μνκΈ° 보μ κΈμ‘μ μΆ©μ νλ€.
+
+- `μλ μΆ©μ `Β νμμ μ΅μ΄ μνκΈ°κ° λ³΄μ ν κΈμ‘μ 0μμ΄λ©°, κ° λμ μ κ°μλ 0κ°μ΄λ€.
+- μλ μΆ©μ μ
λ ₯ μμμ μΆ©μ ν κΈμ‘μ μ
λ ₯ν ν, `μΆ©μ νκΈ°` λ²νΌμ λλ¬ μνκΈ° 보μ κΈμ‘μ μΆ©μ ν μ μλ€.
+ - μνκΈ° 보μ κΈμ‘μΒ `{κΈμ‘}μ`Β νμμΌλ‘ λνλΈλ€.
+- μνκΈ° 보μ κΈμ‘λ§νΌμ λμ μ΄ λ¬΄μμλ‘ μμ±λλ€.
+ - λμ μ κ°μλΒ `{κ°μ}κ°`Β νμμΌλ‘ λνλΈλ€.
+- μνκΈ° 보μ κΈμ‘μ λμ νμ¬ μΆ©μ ν μ μλ€. μΆκ° μΆ©μ κΈμ‘λ§νΌμ λμ μ΄ λ¬΄μμλ‘ μμ±λμ΄ κΈ°μ‘΄ λμ λ€μ λν΄μ§λ€.
+- μν ꡬ맀 νμμ ν¬μ
ν κΈμ‘μ μνκΈ° 보μ κΈμ‘μ λνμ§ μλλ€.
+
+### 4) μν ꡬ맀 ν
+
+`μν ꡬ맀`νμμ, λ€μκ³Ό κ°μ κ·μΉμ λ°νμΌλ‘ κΈμ‘μ μΆ©μ νκ³ , μνμ ꡬ맀νλ©°, μλμ λ°ννλ€.
+
+- `μν ꡬ맀`Β νμ΄μ§μμ μ΅μ΄ μΆ©μ κΈμ‘μ 0μμ΄λ©°, λ°νλ κ° λμ μ κ°μλ 0κ°μ΄λ€.
+- μ¬μ©μλ ν¬μ
ν κΈμ‘ μ
λ ₯ μμμ ν¬μ
κΈμ‘μ μ
λ ₯ν ν, `ν¬μ
νκΈ°`λ²νΌμ μ΄μ©νμ¬ κΈμ‘μ ν¬μ
νλ€.
+ - κΈμ‘μ 10μμΌλ‘ λλμ΄ λ¨μ΄μ§λ κΈμ‘λ§ ν¬μ
ν μ μλ€.
+ - μνκΈ°κ° λ³΄μ ν κΈμ‘μΒ `{κΈμ‘}μ`Β νμμΌλ‘ λνλΈλ€.
+- κΈμ‘μ λμ μΌλ‘ ν¬μ
ν μ μλ€.
+- νμ λ μνμ `ꡬ맀νκΈ°` λ²νΌμ disabled λμ΄μΌ νλ€.
+- μ¬μ©μλΒ `λ°ννκΈ°`Β λ²νΌμ ν΅ν΄ μλμ λ°ν λ°μ μ μλ€.
+
+**μν ꡬ맀 > μλ κ³μ° λͺ¨λ**
+
+`μν ꡬ맀`Β νμμ μλ λ°ν μ λ€μκ³Ό κ°μ κ·μΉμ ν΅ν΄ μλμ λ°ννλ€.
+
+- μλμ λλ €μ€ λλ νμ¬ λ³΄μ ν μ΅μ κ°μμ λμ μΌλ‘ μλμ λλ €μ€λ€.
+- μ§νλ₯Ό μλμΌλ‘ λ°ννλ κ²½μ°λ μλ€κ³ κ°μ νλ€.
+- μλμ λ°νν μ μλ κ²½μ° μλμΌλ‘ λ°νν μ μλ κΈμ‘λ§ λ°ννλ€.
+- λμ μ κ°μλ₯Ό λνλ΄λ μ 보λΒ `{κ°μ}κ°`Β νμμΌλ‘ λνλΈλ€.
+
+---
+
+### π» μ€ν κ²°κ³Ό μμ
+
+#### μν κ΄λ¦¬
+
+
+#### μλ μΆ©μ
+
+
+#### μν ꡬ맀 λ° μλ λ°ν
+
+
+---
+
+## β
νλ‘κ·Έλλ° μꡬ μ¬ν
+
+### DOM μ νμ
+κ° μμμ μλμ κ°μ μ νμλ₯Ό λ°λμ μ§μ νλ€.
+
+**ν λ©λ΄ λ²νΌ**
+
+- `μν ꡬ맀` νμΌλ‘ μ΄λνλ λ©λ΄ λ²νΌ idλΒ `product-purchase-menu`μ΄λ€.
+- `μλ μΆ©μ `νμΌλ‘ μ΄λνλ λ©λ΄ λ²νΌ idλΒ `vending-machine-manage-menu`μ΄λ€.
+- `μν κ΄λ¦¬`νμΌλ‘ μ΄λνλ λ©λ΄ λ²νΌ idλΒ `product-add-menu`μ΄λ€.
+
+**μν κ΄λ¦¬(μΆκ°) λ©λ΄**
+
+- μν μΆκ° μ
λ ₯ νΌμ μνλͺ
μ
λ ₯ μμμ idλΒ `product-name-input`μ΄λ€.
+- μν μΆκ° μ
λ ₯ νΌμ μν κ°κ²© μ
λ ₯ μμμ idλΒ `product-price-input`μ΄λ€.
+- μν μΆκ° μ
λ ₯ νΌμ μλ μ
λ ₯ μμμ idλΒ `product-quantity-input`μ΄λ€.
+- μν `μΆκ°νκΈ°` λ²νΌ μμμ idλΒ `product-add-button`μ΄λ€.
+- μΆκ°ν κ° μν μμμ classλͺ
μ `product-manage-item`μ΄λ©°, νμμ μλ μμλ€μ κ°λλ€.
+ - μνλͺ
μ ν΄λΉνλ μμμ classλͺ
μΒ `product-manage-name`μ΄λ€.
+ - κ°κ²©μ ν΄λΉνλ μμμ classλͺ
μΒ `product-manage-price`μ΄λ€.
+ - μλμ ν΄λΉνλ μμμ classλͺ
μΒ `product-manage-quantity`μ΄λ€.
+
+**μλ μΆ©μ (μνκΈ° 보μ λμ ) λ©λ΄**
+
+- μνκΈ°κ° λ³΄μ ν κΈμ‘μ μΆ©μ ν μμμ idλΒ `vending-machine-charge-input`μ΄λ€.
+- `μΆ©μ νκΈ°`Β λ²νΌμ ν΄λΉνλ μμμ idλΒ `vending-machine-charge-button`μ΄λ€.
+- μΆ©μ λ κΈμ‘μ νμΈνλ μμμ idλΒ `vending-machine-charge-amount`Β μ΄λ€.
+- 보μ ν κ° λμ μ κ°μμ ν΄λΉνλ μμμ idλ λ€μκ³Ό κ°λ€.
+ - 500μ:Β `vending-machine-coin-500-quantity`
+ - 100μ:Β `vending-machine-coin-100-quantity`
+ - 50μ:Β `vending-machine-coin-50-quantity`
+ - 10μ:Β `vending-machine-coin-10-quantity`
+
+**μν ꡬ맀 λ©λ΄**
+
+- ν¬μ
κΈμ‘ μ
λ ₯ μμμ idλΒ `charge-input`μ΄λ€.
+- ν¬μ
νκΈ° λ²νΌ μμμ idλΒ `charge-button`μ΄λ€.
+- ν¬μ
ν κΈμ‘μ νμΈνλ μμμ idλΒ `charge-amount`μ΄λ€.
+- λ°ννκΈ° λ²νΌ μμμ idλΒ `coin-return-button`μ΄λ€.
+- λ°νλ κ° λμ μ κ°μμ ν΄λΉνλ μμμ idλ λ€μκ³Ό κ°λ€.
+ - 500μ:Β `coin-500-quantity`
+ - 100μ:Β `coin-100-quantity`
+ - 50μ:Β `coin-50-quantity`
+ - 10μ:Β `coin-10-quantity`
+- κ° μν μμμ classλͺ
μ `product-purchase-item`μ΄κ³ , νμμ μλ μμλ€μ κ°λλ€.
+ - ꡬ맀 λ²νΌμ ν΄λΉνλ μμμ classλͺ
μΒ `purchase-button`μ΄λ€.
+ - μνλͺ
μ ν΄λΉνλ μμμ classλͺ
μΒ `product-purchase-name`μ΄λ€.
+ - κ°κ²©μ ν΄λΉνλ μμμ classλͺ
μΒ `product-purchase-price`μ΄λ€.
+ - μλμ ν΄λΉνλ μμμ classλͺ
μΒ `product-purchase-quantity`μ΄λ€.
+ - μνλͺ
μ `dataset`Β μμ±μ μ¬μ©νκ³ Β `data-product-name`Β νμμΌλ‘ μ μ₯νλ€.
+ - κ°κ²©μΒ `dataset`Β μμ±μ μ¬μ©νκ³ Β `data-product-price`Β νμμΌλ‘ μ μ₯νλ€.
+ - μλμΒ `dataset`Β μμ±μ μ¬μ©νκ³ Β `data-product-quantity`Β νμμΌλ‘ μ μ₯νλ€.
+
+
+---
+
+### λΌμ΄λΈλ¬λ¦¬
+- μλμ 무μμλ‘ μμ±νλ κΈ°λ₯μ [`MissionUtils` λΌμ΄λΈλ¬λ¦¬](https://github.com/woowacourse-projects/javascript-mission-utils#mission-utils)μ `Random.pickNumberInList`λ₯Ό μ¬μ©ν΄ ꡬνλ€.
+ - `MissionUtils` λΌμ΄λΈλ¬λ¦¬ μ€ν¬λ¦½νΈλ `index.html`μ μ΄λ―Έ ν¬ν¨λμ΄ μ μ κ°μ²΄μ μΆκ°λμ΄ μμΌλ―λ‘, λ°λ‘ `import` νμ§ μμλ ꡬν μ½λ μ΄λμμλ μ¬μ©ν μ μλ€.
+
+ ```javascript
+ // ex)
+ const randomNumber = Random.pickNumberInList([10, 50, 100, 500]);
+ ```
+
+---
+
+### κ³΅ν΅ μꡬμ¬ν
+
+- μ€ν¬λ¦½νΈ μΆκ° μΈμ μ£Όμ΄μ§Β `index.html`νμΌμ μμ ν μ μλ€.
+ - μ€νμΌ(css)μ μ±μ μμκ° μλλ€.
+- λͺ¨λ μμΈ λ°μ μν©μ `alert`λ©μλλ₯Ό μ΄μ©νμ¬ μ²λ¦¬νλ€.
+- μΈλΆ λΌμ΄λΈλ¬λ¦¬(jQuery, Lodash λ±)λ₯Ό μ¬μ©νμ§ μκ³ , μμ Vanilla JSλ‘λ§ κ΅¬ννλ€.
+- **[μλ°μ€ν¬λ¦½νΈ μ½λ 컨벀μ
](https://github.com/woowacourse/woowacourse-docs/tree/feature/styleguide/styleguide/javascript)μ μ§ν€λ©΄μ νλ‘κ·Έλλ°** νλ€.
+- **indent(μΈλ΄νΈ, λ€μ¬μ°κΈ°) depthλ₯Ό 3μ΄ λμ§ μλλ‘ κ΅¬ννλ€. 2κΉμ§λ§ νμ©**νλ€.
+ - μλ₯Ό λ€μ΄ whileλ¬Έ μμ ifλ¬Έμ΄ μμΌλ©΄ λ€μ¬μ°κΈ°λ 2μ΄λ€.
+ - ννΈ: indent(μΈλ΄νΈ, λ€μ¬μ°κΈ°) depthλ₯Ό μ€μ΄λ μ’μ λ°©λ²μ ν¨μ(λλ λ©μλ)λ₯Ό λΆλ¦¬νλ©΄ λλ€.
+- **ν¨μ(λλ λ©μλ)κ° ν κ°μ§ μΌλ§ νλλ‘ μ΅λν μκ²** λ§λ€μ΄λΌ.
+- λ³μ μ μΈμ `var` λ₯Ό μ¬μ©νμ§ μλλ€. `const` μ `let` μ μ¬μ©νλ€.
+ - [const](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/const)
+ - [let](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/let)
+- `import` λ¬Έμ μ΄μ©ν΄ μ€ν¬λ¦½νΈλ₯Ό λͺ¨λννκ³ λΆλ¬μ¬ μ μκ² λ§λ λ€.
+ - [https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/import](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/import)
+- **ν¨μ(λλ λ©μλ)μ κΈΈμ΄κ° 15λΌμΈμ λμ΄κ°μ§ μλλ‘ κ΅¬ννλ€.**
+ - ν¨μ(λλ λ©μλ)κ° ν κ°μ§ μΌλ§ μ νλλ‘ κ΅¬ννλ€.
+
+---
+
+## π κ³Όμ μ§ν μꡬμ¬ν
+- λ―Έμ
μ [javascript-vendingmachine-precourse](https://github.com/woowacourse/javascript-vendingmachine-precourse/) μ μ₯μλ₯Ό Fork/Cloneν΄ μμνλ€.
+- **κΈ°λ₯μ ꡬννκΈ° μ μ javascript-vendingmachine-precourse/docs/README.md νμΌμ ꡬνν κΈ°λ₯ λͺ©λ‘μ μ 리**ν΄ μΆκ°νλ€.
+- **Gitμ μ»€λ° λ¨μλ μ λ¨κ³μμ README.md νμΌμ μ 리ν κΈ°λ₯ λͺ©λ‘ λ¨μ**λ‘ μΆκ°νλ€.
+ - [AngularJS Commit Message Conventions](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) μ°Έκ³ ν΄ commit logλ₯Ό λ¨κΈ΄λ€.
+- κ³Όμ μ§ν λ° μ μΆ λ°©λ²μ [ν리μ½μ€ κ³Όμ μ μΆ λ¬Έμ](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) λ₯Ό μ°Έκ³ νλ€.
+
+## βοΈ λ―Έμ
μ μΆ λ°©λ²
+
+- λ―Έμ
ꡬνμ μλ£ν ν GitHubμ ν΅ν΄ μ μΆν΄μΌ νλ€.
+ - GitHubμ νμ©ν μ μΆ λ°©λ²μ [ν리μ½μ€ κ³Όμ μ μΆ λ¬Έμ](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) λ₯Ό μ°Έκ³ ν΄ μ μΆνλ€.
+- GitHubμ λ―Έμ
μ μ μΆν ν [μ°μνν
ν¬μ½μ€ μ§μ νλ«νΌ](https://apply.techcourse.co.kr) μ μ μνμ¬ ν리μ½μ€ κ³Όμ λ₯Ό μ μΆνλ€.
+ - μμΈν λ°©λ²μ [λ§ν¬](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse#μ μΆ-κ°μ΄λ) λ₯Ό μ°Έκ³ νλ€.
+ - **Pull Requestλ§ λ³΄λ΄κ³ , μ§μ νλ«νΌμμ κ³Όμ λ₯Ό μ μΆνμ§ μμΌλ©΄ μ΅μ’
μ μΆνμ§ μμ κ²μΌλ‘ μ²λ¦¬λλ μ£Όμνλ€.**
+
+
+### π¨ κ³Όμ μ μΆ μ 체ν¬λ¦¬μ€νΈ - 0μ λ°©μ§λ₯Ό μν μ£Όμμ¬ν
+- μꡬμ¬νμ λͺ
μλ μΆλ ₯κ° νμμ μ§ν€μ§ μμ κ²½μ° κΈ°λ₯ ꡬνμ λͺ¨λ μ μμ μΌλ‘ νλλΌλ 0μ μΌλ‘ μ²λ¦¬λλ€.
+- κΈ°λ₯ ꡬνμ μλ£ν λ€ μλ κ°μ΄λμ λ°λΌ ν
μ€νΈλ₯Ό μ€ννμ λ λͺ¨λ ν
μ€νΈκ° μ±κ³΅νλ μ§ νμΈνλ€. **ν
μ€νΈκ° μ€ν¨ν κ²½μ° 0μ μΌλ‘ μ²λ¦¬λλ―λ‘, λ°λμ νμΈ ν μ μΆνλ€.**
+
+### βοΈ ν
μ€νΈ μ€ν κ°μ΄λ
+- ν
μ€νΈ μ€νμ νμν ν¨ν€μ§ μ€μΉλ₯Ό μν΄ `Node.js` λ²μ `14` μ΄μμ΄ νμνλ€.
+- λ€μ λͺ
λ Ήμ΄λ₯Ό μ
λ ₯ν΄ ν¨ν€μ§λ₯Ό μ€μΉνλ€.
+```bash
+// {ν΄λ κ²½λ‘}/javascript-vendingmachine-precourse/ μμ
+npm install
+```
+
+- μ€μΉκ° μλ£λμλ€λ©΄, λ€μ λͺ
λ Ήμ΄λ₯Ό μ
λ ₯ν΄ ν
μ€νΈλ₯Ό μ€ννλ€.
+```bash
+// {ν΄λ κ²½λ‘}/javascript-vendingmachine-precourse/ μμ
+npm run test
+```
+
+- μλμ κ°μ νλ©΄μ΄ λμ€λ©° λͺ¨λ ν
μ€νΈκ° passνλ€λ©΄ μ±κ³΅!
+
+
diff --git a/javascript-vendingmachine-precourse/cypress.json b/javascript-vendingmachine-precourse/cypress.json
new file mode 100644
index 0000000..a78fa83
--- /dev/null
+++ b/javascript-vendingmachine-precourse/cypress.json
@@ -0,0 +1,9 @@
+{
+ "integrationFolder": "test",
+ "testFiles": "*.spec.js",
+ "screenshotOnRunFailure": false,
+ "video": false,
+ "pluginsFile": false,
+ "supportFile": false,
+ "blockHosts": ["cdn.jsdelivr.net"]
+}
diff --git a/javascript-vendingmachine-precourse/images/beverage_icon.png b/javascript-vendingmachine-precourse/images/beverage_icon.png
new file mode 100644
index 0000000..cfed9e2
Binary files /dev/null and b/javascript-vendingmachine-precourse/images/beverage_icon.png differ
diff --git a/javascript-vendingmachine-precourse/images/demo_coin.gif b/javascript-vendingmachine-precourse/images/demo_coin.gif
new file mode 100644
index 0000000..05457a2
Binary files /dev/null and b/javascript-vendingmachine-precourse/images/demo_coin.gif differ
diff --git a/javascript-vendingmachine-precourse/images/demo_product.gif b/javascript-vendingmachine-precourse/images/demo_product.gif
new file mode 100644
index 0000000..ce631e2
Binary files /dev/null and b/javascript-vendingmachine-precourse/images/demo_product.gif differ
diff --git a/javascript-vendingmachine-precourse/images/demo_purchase.gif b/javascript-vendingmachine-precourse/images/demo_purchase.gif
new file mode 100644
index 0000000..12e4470
Binary files /dev/null and b/javascript-vendingmachine-precourse/images/demo_purchase.gif differ
diff --git a/javascript-vendingmachine-precourse/images/test_result.png b/javascript-vendingmachine-precourse/images/test_result.png
new file mode 100644
index 0000000..c987571
Binary files /dev/null and b/javascript-vendingmachine-precourse/images/test_result.png differ
diff --git a/javascript-vendingmachine-precourse/index.html b/javascript-vendingmachine-precourse/index.html
new file mode 100644
index 0000000..47d57c5
--- /dev/null
+++ b/javascript-vendingmachine-precourse/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+ μνκΈ°
+
+
+
+
+
+
+
+
diff --git a/javascript-vendingmachine-precourse/package-lock.json b/javascript-vendingmachine-precourse/package-lock.json
new file mode 100644
index 0000000..6a972b5
--- /dev/null
+++ b/javascript-vendingmachine-precourse/package-lock.json
@@ -0,0 +1,3111 @@
+{
+ "name": "javascript-vendingmachine-precourse",
+ "version": "1.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "javascript-vendingmachine-precourse",
+ "version": "1.0.0",
+ "license": "MIT",
+ "devDependencies": {
+ "cypress": "8.7.0"
+ },
+ "engines": {
+ "node": ">=14.0.0",
+ "npm": ">=6.0.0"
+ }
+ },
+ "node_modules/@colors/colors": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
+ "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
+ "node_modules/@cypress/request": {
+ "version": "2.88.10",
+ "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.10.tgz",
+ "integrity": "sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==",
+ "dev": true,
+ "dependencies": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "http-signature": "~1.3.6",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.5.0",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^8.3.2"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@cypress/xvfb": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz",
+ "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.1.0",
+ "lodash.once": "^4.1.1"
+ }
+ },
+ "node_modules/@cypress/xvfb/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "14.18.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.0.tgz",
+ "integrity": "sha512-0GeIl2kmVMXEnx8tg1SlG6Gg8vkqirrW752KqolYo1PHevhhZN3bhJ67qHj+bQaINhX0Ra3TlWwRvMCd9iEfNQ==",
+ "dev": true
+ },
+ "node_modules/@types/sinonjs__fake-timers": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.4.tgz",
+ "integrity": "sha512-IFQTJARgMUBF+xVd2b+hIgXWrZEjND3vJtRCvIelcFB5SIXfjV4bOHbHJ0eXKh+0COrBRc8MqteKAz/j88rE0A==",
+ "dev": true
+ },
+ "node_modules/@types/sizzle": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
+ "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
+ "dev": true
+ },
+ "node_modules/@types/yauzl": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz",
+ "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dev": true,
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/arch": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz",
+ "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==",
+ "dev": true,
+ "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/asn1": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
+ "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
+ "dev": true,
+ "dependencies": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "node_modules/assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/async": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz",
+ "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==",
+ "dev": true
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
+ "node_modules/at-least-node": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/aws4": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
+ "dev": true
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "dev": true,
+ "dependencies": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "node_modules/blob-util": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz",
+ "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==",
+ "dev": true
+ },
+ "node_modules/bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+ "dev": true
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/cachedir": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz",
+ "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+ "dev": true
+ },
+ "node_modules/chalk": {
+ "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"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chalk/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==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/check-more-types": {
+ "version": "2.24.0",
+ "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz",
+ "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz",
+ "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==",
+ "dev": true
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "restore-cursor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-table3": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz",
+ "integrity": "sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0"
+ },
+ "engines": {
+ "node": "10.* || >= 12.*"
+ },
+ "optionalDependencies": {
+ "@colors/colors": "1.5.0"
+ }
+ },
+ "node_modules/cli-truncate": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
+ "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
+ "dev": true,
+ "dependencies": {
+ "slice-ansi": "^3.0.0",
+ "string-width": "^4.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "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
+ },
+ "node_modules/colorette": {
+ "version": "2.0.16",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz",
+ "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==",
+ "dev": true
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/commander": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/common-tags": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz",
+ "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/cypress": {
+ "version": "8.7.0",
+ "resolved": "https://registry.npmjs.org/cypress/-/cypress-8.7.0.tgz",
+ "integrity": "sha512-b1bMC3VQydC6sXzBMFnSqcvwc9dTZMgcaOzT0vpSD+Gq1yFc+72JDWi55sfUK5eIeNLAtWOGy1NNb6UlhMvB+Q==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "@cypress/request": "^2.88.6",
+ "@cypress/xvfb": "^1.2.4",
+ "@types/node": "^14.14.31",
+ "@types/sinonjs__fake-timers": "^6.0.2",
+ "@types/sizzle": "^2.3.2",
+ "arch": "^2.2.0",
+ "blob-util": "^2.0.2",
+ "bluebird": "^3.7.2",
+ "cachedir": "^2.3.0",
+ "chalk": "^4.1.0",
+ "check-more-types": "^2.24.0",
+ "cli-cursor": "^3.1.0",
+ "cli-table3": "~0.6.0",
+ "commander": "^5.1.0",
+ "common-tags": "^1.8.0",
+ "dayjs": "^1.10.4",
+ "debug": "^4.3.2",
+ "enquirer": "^2.3.6",
+ "eventemitter2": "^6.4.3",
+ "execa": "4.1.0",
+ "executable": "^4.1.1",
+ "extract-zip": "2.0.1",
+ "figures": "^3.2.0",
+ "fs-extra": "^9.1.0",
+ "getos": "^3.2.1",
+ "is-ci": "^3.0.0",
+ "is-installed-globally": "~0.4.0",
+ "lazy-ass": "^1.6.0",
+ "listr2": "^3.8.3",
+ "lodash": "^4.17.21",
+ "log-symbols": "^4.0.0",
+ "minimist": "^1.2.5",
+ "ospath": "^1.2.2",
+ "pretty-bytes": "^5.6.0",
+ "proxy-from-env": "1.0.0",
+ "ramda": "~0.27.1",
+ "request-progress": "^3.0.0",
+ "supports-color": "^8.1.1",
+ "tmp": "~0.2.1",
+ "untildify": "^4.0.0",
+ "url": "^0.11.0",
+ "yauzl": "^2.10.0"
+ },
+ "bin": {
+ "cypress": "bin/cypress"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "dev": true,
+ "dependencies": {
+ "assert-plus": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/dayjs": {
+ "version": "1.10.7",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz",
+ "integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==",
+ "dev": true
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/debug/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "dev": true,
+ "dependencies": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/enquirer": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-colors": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "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": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/eventemitter2": {
+ "version": "6.4.5",
+ "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.5.tgz",
+ "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==",
+ "dev": true
+ },
+ "node_modules/execa": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz",
+ "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "get-stream": "^5.0.0",
+ "human-signals": "^1.1.1",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.0",
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/executable": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz",
+ "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==",
+ "dev": true,
+ "dependencies": {
+ "pify": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "node_modules/extract-zip": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
+ "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.1",
+ "get-stream": "^5.1.0",
+ "yauzl": "^2.10.0"
+ },
+ "bin": {
+ "extract-zip": "cli.js"
+ },
+ "engines": {
+ "node": ">= 10.17.0"
+ },
+ "optionalDependencies": {
+ "@types/yauzl": "^2.9.1"
+ }
+ },
+ "node_modules/extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+ "dev": true,
+ "engines": [
+ "node >=0.6.0"
+ ]
+ },
+ "node_modules/fd-slicer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+ "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
+ "dev": true,
+ "dependencies": {
+ "pend": "~1.2.0"
+ }
+ },
+ "node_modules/figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "dev": true,
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 0.12"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "dependencies": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "node_modules/get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "dev": true,
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/getos": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz",
+ "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==",
+ "dev": true,
+ "dependencies": {
+ "async": "^3.2.0"
+ }
+ },
+ "node_modules/getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "dev": true,
+ "dependencies": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/global-dirs": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz",
+ "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==",
+ "dev": true,
+ "dependencies": {
+ "ini": "2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/http-signature": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz",
+ "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==",
+ "dev": true,
+ "dependencies": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^2.0.2",
+ "sshpk": "^1.14.1"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/human-signals": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
+ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.12.0"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/ini": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz",
+ "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/is-ci": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz",
+ "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==",
+ "dev": true,
+ "dependencies": {
+ "ci-info": "^3.2.0"
+ },
+ "bin": {
+ "is-ci": "bin.js"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-installed-globally": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz",
+ "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==",
+ "dev": true,
+ "dependencies": {
+ "global-dirs": "^3.0.0",
+ "is-path-inside": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "node_modules/isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+ "dev": true
+ },
+ "node_modules/jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+ "dev": true
+ },
+ "node_modules/json-schema": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
+ "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
+ "dev": true
+ },
+ "node_modules/json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+ "dev": true
+ },
+ "node_modules/jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jsprim": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz",
+ "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==",
+ "dev": true,
+ "engines": [
+ "node >=0.6.0"
+ ],
+ "dependencies": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.4.0",
+ "verror": "1.10.0"
+ }
+ },
+ "node_modules/lazy-ass": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz",
+ "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=",
+ "dev": true,
+ "engines": {
+ "node": "> 0.8"
+ }
+ },
+ "node_modules/listr2": {
+ "version": "3.13.5",
+ "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.13.5.tgz",
+ "integrity": "sha512-3n8heFQDSk+NcwBn3CgxEibZGaRzx+pC64n3YjpMD1qguV4nWus3Al+Oo3KooqFKTQEJ1v7MmnbnyyNspgx3NA==",
+ "dev": true,
+ "dependencies": {
+ "cli-truncate": "^2.1.0",
+ "colorette": "^2.0.16",
+ "log-update": "^4.0.0",
+ "p-map": "^4.0.0",
+ "rfdc": "^1.3.0",
+ "rxjs": "^7.4.0",
+ "through": "^2.3.8",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "enquirer": ">= 2.3.0 < 3"
+ },
+ "peerDependenciesMeta": {
+ "enquirer": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "node_modules/lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=",
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-update": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz",
+ "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-escapes": "^4.3.0",
+ "cli-cursor": "^3.1.0",
+ "slice-ansi": "^4.0.0",
+ "wrap-ansi": "^6.2.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-update/node_modules/slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/log-update/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "node_modules/mime-db": {
+ "version": "1.51.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
+ "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.34",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
+ "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
+ "dev": true,
+ "dependencies": {
+ "mime-db": "1.51.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/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,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
+ "dev": true
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ospath": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz",
+ "integrity": "sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs=",
+ "dev": true
+ },
+ "node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
+ "dev": true
+ },
+ "node_modules/performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+ "dev": true
+ },
+ "node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pretty-bytes": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
+ "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
+ "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=",
+ "dev": true
+ },
+ "node_modules/psl": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
+ "dev": true
+ },
+ "node_modules/pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==",
+ "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
+ "node_modules/ramda": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.2.tgz",
+ "integrity": "sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==",
+ "dev": true
+ },
+ "node_modules/request-progress": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz",
+ "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=",
+ "dev": true,
+ "dependencies": {
+ "throttleit": "^1.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/rfdc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
+ "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
+ "dev": true
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rxjs": {
+ "version": "7.4.0",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz",
+ "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==",
+ "dev": true,
+ "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",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "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
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz",
+ "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==",
+ "dev": true
+ },
+ "node_modules/slice-ansi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
+ "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/sshpk": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+ "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+ "dev": true,
+ "dependencies": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ },
+ "bin": {
+ "sshpk-conv": "bin/sshpk-conv",
+ "sshpk-sign": "bin/sshpk-sign",
+ "sshpk-verify": "bin/sshpk-verify"
+ },
+ "engines": {
+ "node": ">=0.10.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==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "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"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/throttleit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz",
+ "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=",
+ "dev": true
+ },
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+ "dev": true
+ },
+ "node_modules/tmp": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
+ "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
+ "dev": true,
+ "dependencies": {
+ "rimraf": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8.17.0"
+ }
+ },
+ "node_modules/tough-cookie": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+ "dev": true,
+ "dependencies": {
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
+ "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==",
+ "dev": true
+ },
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/untildify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
+ "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ }
+ },
+ "node_modules/url/node_modules/punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==",
+ "dev": true
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "dev": true,
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "dev": true,
+ "engines": [
+ "node >=0.6.0"
+ ],
+ "dependencies": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "node_modules/yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
+ "dev": true,
+ "dependencies": {
+ "buffer-crc32": "~0.2.3",
+ "fd-slicer": "~1.1.0"
+ }
+ }
+ },
+ "dependencies": {
+ "@colors/colors": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
+ "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@cypress/request": {
+ "version": "2.88.10",
+ "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.10.tgz",
+ "integrity": "sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==",
+ "dev": true,
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "http-signature": "~1.3.6",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.5.0",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^8.3.2"
+ }
+ },
+ "@cypress/xvfb": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz",
+ "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.1.0",
+ "lodash.once": "^4.1.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "@types/node": {
+ "version": "14.18.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.0.tgz",
+ "integrity": "sha512-0GeIl2kmVMXEnx8tg1SlG6Gg8vkqirrW752KqolYo1PHevhhZN3bhJ67qHj+bQaINhX0Ra3TlWwRvMCd9iEfNQ==",
+ "dev": true
+ },
+ "@types/sinonjs__fake-timers": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.4.tgz",
+ "integrity": "sha512-IFQTJARgMUBF+xVd2b+hIgXWrZEjND3vJtRCvIelcFB5SIXfjV4bOHbHJ0eXKh+0COrBRc8MqteKAz/j88rE0A==",
+ "dev": true
+ },
+ "@types/sizzle": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
+ "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
+ "dev": true
+ },
+ "@types/yauzl": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz",
+ "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dev": true,
+ "requires": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ }
+ },
+ "ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.21.3"
+ }
+ },
+ "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
+ },
+ "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"
+ }
+ },
+ "arch": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz",
+ "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==",
+ "dev": true
+ },
+ "asn1": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
+ "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true
+ },
+ "astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true
+ },
+ "async": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz",
+ "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==",
+ "dev": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
+ "at-least-node": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
+ "dev": true
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+ "dev": true
+ },
+ "aws4": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "dev": true,
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "blob-util": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz",
+ "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==",
+ "dev": true
+ },
+ "bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
+ "dev": true
+ },
+ "cachedir": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz",
+ "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==",
+ "dev": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+ "dev": true
+ },
+ "chalk": {
+ "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"
+ },
+ "dependencies": {
+ "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==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "check-more-types": {
+ "version": "2.24.0",
+ "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz",
+ "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=",
+ "dev": true
+ },
+ "ci-info": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz",
+ "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==",
+ "dev": true
+ },
+ "clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true
+ },
+ "cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "^3.1.0"
+ }
+ },
+ "cli-table3": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz",
+ "integrity": "sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==",
+ "dev": true,
+ "requires": {
+ "@colors/colors": "1.5.0",
+ "string-width": "^4.2.0"
+ }
+ },
+ "cli-truncate": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
+ "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
+ "dev": true,
+ "requires": {
+ "slice-ansi": "^3.0.0",
+ "string-width": "^4.2.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "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
+ },
+ "colorette": {
+ "version": "2.0.16",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz",
+ "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==",
+ "dev": true
+ },
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "commander": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+ "dev": true
+ },
+ "common-tags": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz",
+ "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "cypress": {
+ "version": "8.7.0",
+ "resolved": "https://registry.npmjs.org/cypress/-/cypress-8.7.0.tgz",
+ "integrity": "sha512-b1bMC3VQydC6sXzBMFnSqcvwc9dTZMgcaOzT0vpSD+Gq1yFc+72JDWi55sfUK5eIeNLAtWOGy1NNb6UlhMvB+Q==",
+ "dev": true,
+ "requires": {
+ "@cypress/request": "^2.88.6",
+ "@cypress/xvfb": "^1.2.4",
+ "@types/node": "^14.14.31",
+ "@types/sinonjs__fake-timers": "^6.0.2",
+ "@types/sizzle": "^2.3.2",
+ "arch": "^2.2.0",
+ "blob-util": "^2.0.2",
+ "bluebird": "^3.7.2",
+ "cachedir": "^2.3.0",
+ "chalk": "^4.1.0",
+ "check-more-types": "^2.24.0",
+ "cli-cursor": "^3.1.0",
+ "cli-table3": "~0.6.0",
+ "commander": "^5.1.0",
+ "common-tags": "^1.8.0",
+ "dayjs": "^1.10.4",
+ "debug": "^4.3.2",
+ "enquirer": "^2.3.6",
+ "eventemitter2": "^6.4.3",
+ "execa": "4.1.0",
+ "executable": "^4.1.1",
+ "extract-zip": "2.0.1",
+ "figures": "^3.2.0",
+ "fs-extra": "^9.1.0",
+ "getos": "^3.2.1",
+ "is-ci": "^3.0.0",
+ "is-installed-globally": "~0.4.0",
+ "lazy-ass": "^1.6.0",
+ "listr2": "^3.8.3",
+ "lodash": "^4.17.21",
+ "log-symbols": "^4.0.0",
+ "minimist": "^1.2.5",
+ "ospath": "^1.2.2",
+ "pretty-bytes": "^5.6.0",
+ "proxy-from-env": "1.0.0",
+ "ramda": "~0.27.1",
+ "request-progress": "^3.0.0",
+ "supports-color": "^8.1.1",
+ "tmp": "~0.2.1",
+ "untildify": "^4.0.0",
+ "url": "^0.11.0",
+ "yauzl": "^2.10.0"
+ }
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "dayjs": {
+ "version": "1.10.7",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz",
+ "integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true
+ },
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "dev": true,
+ "requires": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dev": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "enquirer": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^4.1.1"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "eventemitter2": {
+ "version": "6.4.5",
+ "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.5.tgz",
+ "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==",
+ "dev": true
+ },
+ "execa": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz",
+ "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.0",
+ "get-stream": "^5.0.0",
+ "human-signals": "^1.1.1",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.0",
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2",
+ "strip-final-newline": "^2.0.0"
+ }
+ },
+ "executable": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz",
+ "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==",
+ "dev": true,
+ "requires": {
+ "pify": "^2.2.0"
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "extract-zip": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
+ "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
+ "dev": true,
+ "requires": {
+ "@types/yauzl": "^2.9.1",
+ "debug": "^4.1.1",
+ "get-stream": "^5.1.0",
+ "yauzl": "^2.10.0"
+ }
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+ "dev": true
+ },
+ "fd-slicer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+ "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
+ "dev": true,
+ "requires": {
+ "pend": "~1.2.0"
+ }
+ },
+ "figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+ "dev": true
+ },
+ "form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "getos": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz",
+ "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==",
+ "dev": true,
+ "requires": {
+ "async": "^3.2.0"
+ }
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "global-dirs": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz",
+ "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==",
+ "dev": true,
+ "requires": {
+ "ini": "2.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "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
+ },
+ "http-signature": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz",
+ "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^2.0.2",
+ "sshpk": "^1.14.1"
+ }
+ },
+ "human-signals": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
+ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
+ "dev": true
+ },
+ "indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "ini": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz",
+ "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==",
+ "dev": true
+ },
+ "is-ci": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz",
+ "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==",
+ "dev": true,
+ "requires": {
+ "ci-info": "^3.2.0"
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "is-installed-globally": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz",
+ "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==",
+ "dev": true,
+ "requires": {
+ "global-dirs": "^3.0.0",
+ "is-path-inside": "^3.0.2"
+ }
+ },
+ "is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true
+ },
+ "is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
+ "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==",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+ "dev": true
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+ "dev": true
+ },
+ "json-schema": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
+ "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
+ "dev": true
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+ "dev": true
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ }
+ },
+ "jsprim": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz",
+ "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==",
+ "dev": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.4.0",
+ "verror": "1.10.0"
+ }
+ },
+ "lazy-ass": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz",
+ "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=",
+ "dev": true
+ },
+ "listr2": {
+ "version": "3.13.5",
+ "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.13.5.tgz",
+ "integrity": "sha512-3n8heFQDSk+NcwBn3CgxEibZGaRzx+pC64n3YjpMD1qguV4nWus3Al+Oo3KooqFKTQEJ1v7MmnbnyyNspgx3NA==",
+ "dev": true,
+ "requires": {
+ "cli-truncate": "^2.1.0",
+ "colorette": "^2.0.16",
+ "log-update": "^4.0.0",
+ "p-map": "^4.0.0",
+ "rfdc": "^1.3.0",
+ "rxjs": "^7.4.0",
+ "through": "^2.3.8",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=",
+ "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==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ }
+ },
+ "log-update": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz",
+ "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^4.3.0",
+ "cli-cursor": "^3.1.0",
+ "slice-ansi": "^4.0.0",
+ "wrap-ansi": "^6.2.0"
+ },
+ "dependencies": {
+ "slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ }
+ }
+ },
+ "merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "mime-db": {
+ "version": "1.51.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
+ "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.34",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
+ "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.51.0"
+ }
+ },
+ "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
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.0.0"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "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"
+ }
+ },
+ "ospath": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz",
+ "integrity": "sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs=",
+ "dev": true
+ },
+ "p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "requires": {
+ "aggregate-error": "^3.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
+ "dev": true
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+ "dev": true
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "pretty-bytes": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
+ "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
+ "dev": true
+ },
+ "proxy-from-env": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
+ "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=",
+ "dev": true
+ },
+ "psl": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
+ "dev": true
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+ "dev": true
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==",
+ "dev": true
+ },
+ "ramda": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.2.tgz",
+ "integrity": "sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==",
+ "dev": true
+ },
+ "request-progress": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz",
+ "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=",
+ "dev": true,
+ "requires": {
+ "throttleit": "^1.0.0"
+ }
+ },
+ "restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "requires": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "rfdc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
+ "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "rxjs": {
+ "version": "7.4.0",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz",
+ "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==",
+ "dev": true,
+ "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
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz",
+ "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
+ "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ }
+ },
+ "sshpk": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+ "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+ "dev": true,
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.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==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "strip-ansi": {
+ "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"
+ }
+ },
+ "strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "throttleit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz",
+ "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=",
+ "dev": true
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+ "dev": true
+ },
+ "tmp": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
+ "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
+ "dev": true,
+ "requires": {
+ "rimraf": "^3.0.0"
+ }
+ },
+ "tough-cookie": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+ "dev": true,
+ "requires": {
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ }
+ },
+ "tslib": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
+ "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==",
+ "dev": true
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "dev": true
+ },
+ "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==",
+ "dev": true
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true
+ },
+ "untildify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
+ "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
+ "dev": true
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==",
+ "dev": true,
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==",
+ "dev": true
+ }
+ }
+ },
+ "uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "dev": true
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
+ "dev": true,
+ "requires": {
+ "buffer-crc32": "~0.2.3",
+ "fd-slicer": "~1.1.0"
+ }
+ }
+ }
+}
diff --git a/javascript-vendingmachine-precourse/package.json b/javascript-vendingmachine-precourse/package.json
new file mode 100644
index 0000000..5790c81
--- /dev/null
+++ b/javascript-vendingmachine-precourse/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "javascript-vendingmachine-precourse",
+ "version": "1.0.0",
+ "description": "μ°μνν
ν¬μ½μ€ ν리μ½μ€ μνκΈ° λ―Έμ
",
+ "dependencies": {},
+ "devDependencies": {
+ "cypress": "8.7.0"
+ },
+ "scripts": {
+ "test": "cypress run --browser chrome"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/woowacourse/javascript-vendingmachine-precourse.git"
+ },
+ "keywords": [],
+ "author": "woowacourse",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/woowacourse/javascript-vendingmachine-precourse/issues"
+ },
+ "homepage": "https://github.com/woowacourse/javascript-vendingmachine-precourse#readme",
+ "engineStrict": true,
+ "engines": {
+ "npm": ">=6.0.0",
+ "node": ">=14.0.0"
+ }
+}
diff --git a/javascript-vendingmachine-precourse/src/App.js b/javascript-vendingmachine-precourse/src/App.js
new file mode 100644
index 0000000..e1ebae9
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/App.js
@@ -0,0 +1,71 @@
+import { $ } from './utils/dom.js';
+import ProductManageController from './ProductManage/ProductManageController.js';
+import ChangeManageController from './ChangeManage/ChangeManageController.js';
+import ProductPurchaseController from './ProductPurchase/ProductPurchaseController.js';
+import { validateProdList, validateChanges } from './utils/validation.js';
+import Dialog from './utils/dialog.js';
+
+export default class App {
+ template = `
+
+ πλ©λ΄ ν΄λ¦ μ, ν΄λΉ νμ΄μ§λ‘ μ΄λλ©λλ€.π
+
+ `;
+
+ $target; // app
+ ProductManageController; // μν κ΄λ¦¬ controller
+ ChangeManageController; // μλ μΆ©μ controller
+ ProductManageController; // μν ꡬ맀 controller
+
+ constructor($target) {
+ this.$target = $target;
+ this.$target.innerHTML = this.template;
+
+ this.productManageController = new ProductManageController();
+ this.ChangeManageController = new ChangeManageController();
+ this.ProductPurchaseController = new ProductPurchaseController();
+ $('#vending-machine-menu').addEventListener('click', e => this.onClickMenu(e));
+ this.renderProductManageMenu(); //μ΄κΈ°μ μν κ΄λ¦¬ νμ΄μ§λ‘ λ‘λλλλ‘
+ }
+
+ // κ° λ©λ΄ ν΄λ¦ μ ν μ΄λ
+ onClickMenu({ target }) {
+ switch (target.id) {
+ case 'product-add-menu':
+ this.renderProductManageMenu();
+ break;
+ case 'vending-machine-manage-menu':
+ this.renderChangeManageMenu();
+ break;
+ case 'product-purchase-menu':
+ this.renderProductPurchaseMenu();
+ break;
+ }
+ }
+
+ // μν κ΄λ¦¬ ν λ λλ§
+ renderProductManageMenu() {
+ this.productManageController.renderProductAddMenu();
+ }
+
+ // μλ μΆ©μ ν λ λλ§
+ renderChangeManageMenu() {
+ this.ChangeManageController.renderChangeManageMenu();
+ }
+
+ // μν ꡬ맀 ν λ λλ§
+ renderProductPurchaseMenu() {
+ try {
+ validateProdList(); //μν λͺ©λ‘ κ²μ¬
+ validateChanges(); //μλ νν© κ²μ¬
+ } catch (error) {
+ Dialog.error(error);
+ return;
+ }
+ this.ProductPurchaseController.renderProductPurchaseMenu();
+ }
+}
diff --git a/javascript-vendingmachine-precourse/src/ChangeManage/ChangeManageController.js b/javascript-vendingmachine-precourse/src/ChangeManage/ChangeManageController.js
new file mode 100644
index 0000000..f5b42e5
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/ChangeManage/ChangeManageController.js
@@ -0,0 +1,28 @@
+import { $ } from '../utils/dom.js';
+import ChangeManageModel from './ChangeManageModel.js';
+import ChangeManageView from './ChangeManageView.js';
+
+// μλ μΆ©μ service (view, model μ¬μ΄μμ κ΄λ¦¬)
+export default class ChangeManageController {
+ model;
+ view;
+
+ constructor() {
+ this.model = new ChangeManageModel();
+ this.view = new ChangeManageView();
+ }
+
+ renderChangeManageMenu() {
+ this.model.updateChangeInfo();
+ this.view.render(this.model.changeInfo);
+ $('#vending-machine-charge-form').addEventListener('submitChange', ({ detail }) =>
+ this.onSubmitChange(detail)
+ );
+ }
+
+ // μλ μ
λ ₯ μ, λͺ¨λΈκ³Ό λ·° μ
λ°μ΄νΈ
+ onSubmitChange(changeInput) {
+ this.model.setChangeInfo(changeInput);
+ this.view.updateChangeInfo(this.model.changeInfo);
+ }
+}
diff --git a/javascript-vendingmachine-precourse/src/ChangeManage/ChangeManageModel.js b/javascript-vendingmachine-precourse/src/ChangeManage/ChangeManageModel.js
new file mode 100644
index 0000000..8cead6e
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/ChangeManage/ChangeManageModel.js
@@ -0,0 +1,47 @@
+import { getData, setData } from '../utils/storage.js';
+
+export default class ChangeManageController {
+ changeInfo;
+
+ get changeInfo() {
+ return this.changeInfo;
+ }
+
+ setChangeInfo(changeInput) {
+ this.changeInfo.total += changeInput;
+ this.changeInfo.coins = this.convertChangeToCoins(changeInput);
+ setData('changeInfo', this.changeInfo);
+ }
+
+ constructor() {
+ this.updateChangeInfo();
+ }
+
+ updateChangeInfo() {
+ const initCoins = {
+ coin500: 0,
+ coin100: 0,
+ coin50: 0,
+ coin10: 0,
+ };
+
+ this.changeInfo = getData('changeInfo') ?? {
+ total: 0,
+ coins: initCoins,
+ };
+ }
+
+ // μλ 무μμλ‘ κ΅ν
+ convertChangeToCoins(changeInput) {
+ const { coins } = this.changeInfo;
+ while (changeInput !== 0) {
+ const convertedCoins = MissionUtils.Random.pickNumberInList([10, 50, 100, 500]);
+ // λ¨μ μλμ΄ 10μ, λ³νλ λμ μ΄ 500μμΌ λλ κ΅ν λΆκ°
+ if (changeInput >= convertedCoins) {
+ changeInput -= convertedCoins;
+ coins[`coin${convertedCoins}`] += 1;
+ }
+ }
+ return coins;
+ }
+}
diff --git a/javascript-vendingmachine-precourse/src/ChangeManage/ChangeManageView.js b/javascript-vendingmachine-precourse/src/ChangeManage/ChangeManageView.js
new file mode 100644
index 0000000..3958361
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/ChangeManage/ChangeManageView.js
@@ -0,0 +1,88 @@
+import { $ } from '../utils/dom.js';
+import Dialog from '../utils/dialog.js';
+import { validateChange } from '../utils/validation.js';
+
+export default class ChangeManageView {
+ $vendingMachineChargeForm;
+ template = `
+
+ `;
+
+ // μ΄κΈ° λ λλ§ (μλ μΆ©μ λ©λ΄ + νμ¬ μλ)
+ render(changeInfo) {
+ $('#current-menu').innerHTML = this.template;
+ this.updateChangeInfo(changeInfo);
+ this.$vendingMachineChargeForm = $('#vending-machine-charge-form');
+ this.$vendingMachineChargeForm.addEventListener('submit', e => this.onChangeInput(e));
+ }
+
+ updateChangeInfo(changeInfo) {
+ const { total, coins } = changeInfo;
+ $('#vending-machine-charge-amount').textContent = `νμ¬ μ΄μ‘: ${total}μ`;
+ $('#current-charge-table').innerHTML = '';
+ $('#current-charge-table').innerHTML = this.createChangeInfo(coins);
+ }
+
+ createChangeInfo(coins) {
+ const { coin500, coin100, coin50, coin10 } = coins;
+
+ return `
+
+
+ λμ
+ κ°μ
+
+
+
+
+ 500μ
+ ${coin500}κ°
+
+
+ 100μ
+ ${coin100}κ°
+
+
+ 50μ
+ ${coin50}κ°
+
+
+ 10μ
+ ${coin10}κ°
+
+
+ `;
+ }
+
+ onChangeInput(e) {
+ e.preventDefault();
+ const [_, changeInput] = e.target;
+
+ try {
+ validateChange(+changeInput.value);
+ Dialog.show('μλμ΄ μ±κ³΅μ μΌλ‘ μΆ©μ λμμ΅λλ€!');
+ } catch (error) {
+ Dialog.error(error);
+ return;
+ }
+
+ // μλ μΆ©μ μ΄λ²€νΈ λ°μ
+ const newEvent = new CustomEvent('submitChange', {
+ detail: +changeInput.value,
+ });
+ this.$vendingMachineChargeForm.dispatchEvent(newEvent);
+ }
+}
diff --git a/javascript-vendingmachine-precourse/src/ProductManage/ProductManageController.js b/javascript-vendingmachine-precourse/src/ProductManage/ProductManageController.js
new file mode 100644
index 0000000..3e2464a
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/ProductManage/ProductManageController.js
@@ -0,0 +1,30 @@
+import { $ } from '../utils/dom.js';
+import ProductManageModel from './ProductManageModel.js';
+import ProductManageView from './ProductManageView.js';
+
+// μν κ΄λ¦¬ Service
+export default class ProductManageController {
+ model;
+ view;
+
+ constructor() {
+ this.model = new ProductManageModel();
+ this.view = new ProductManageView();
+ }
+
+ // μν μΆκ° λ©λ΄
+ renderProductAddMenu() {
+ this.model.updateProdList();
+ this.view.render(this.model.productList);
+ // μν μΆκ° μ΄λ²€νΈ νΈλ€λ¬ λ°μΈλ©
+ $('#product-add-form').addEventListener('addNewProd', ({ detail }) =>
+ this.onAddNewProduct(detail)
+ );
+ }
+
+ // μν μΆκ° μ΄λ²€νΈ νΈλ€λ¬ (λ°μ΄ν°(λͺ¨λΈ) μ
λ°μ΄νΈ, λ·° μ
λ°μ΄νΈ)
+ onAddNewProduct(newProduct) {
+ this.model.setProdList(newProduct);
+ this.view.updateProdTable(this.model.productList);
+ }
+}
diff --git a/javascript-vendingmachine-precourse/src/ProductManage/ProductManageModel.js b/javascript-vendingmachine-precourse/src/ProductManage/ProductManageModel.js
new file mode 100644
index 0000000..3074722
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/ProductManage/ProductManageModel.js
@@ -0,0 +1,30 @@
+import { makeProductId } from '../utils/validation.js';
+import { getData, setData } from '../utils/storage.js';
+
+// μν λ°μ΄ν° κ΄λ¦¬
+export default class ProductManageModel {
+ productList;
+
+ get productList() {
+ return this.productList;
+ }
+
+ setProdList({ prodName, prodPrice, prodQuantity }) {
+ const newProduct = {
+ id: makeProductId(),
+ name: prodName,
+ price: prodPrice,
+ quantity: prodQuantity,
+ };
+ this.productList = [...this.productList, newProduct];
+ setData('productList', this.productList);
+ }
+
+ constructor() {
+ this.updateProdList();
+ }
+
+ updateProdList() {
+ this.productList = getData('productList') ?? [];
+ }
+}
diff --git a/javascript-vendingmachine-precourse/src/ProductManage/ProductManageView.js b/javascript-vendingmachine-precourse/src/ProductManage/ProductManageView.js
new file mode 100644
index 0000000..fbbfebe
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/ProductManage/ProductManageView.js
@@ -0,0 +1,88 @@
+import { $ } from '../utils/dom.js';
+import { validateProdInfo } from '../utils/validation.js';
+import Dialog from '../utils/dialog.js';
+
+// μν λ·° κ΄λ¦¬
+export default class ProductManageView {
+ $addProductForm;
+ template = `
+
+ `;
+
+ // μ΄κΈ° λ λλ§
+ render(productList) {
+ $('#current-menu').innerHTML = this.template;
+ this.updateProdTable(productList);
+ this.$addProductForm = $('#product-add-form');
+ this.$addProductForm.addEventListener('submit', e => this.onSubmitNewProd(e));
+ }
+
+ // μν λͺ©λ‘ λ λλ§
+ updateProdTable(productList) {
+ $('#current-product-table').innerHTML = '';
+ $('#current-product-table').innerHTML = this.createProductList(productList);
+ }
+
+ createProductList(productList) {
+ return `
+
+
+ μνλͺ
+ κ°κ²©
+ μλ
+
+
+
+ ${productList
+ .map(
+ prod => `
+
+ ${prod.name}
+ ${prod.price}
+ ${prod.quantity}
+
+ `
+ )
+ .join('')}
+
+ `;
+ }
+
+ // μν μΆκ° λ²νΌ ν΄λ¦ μ΄λ²€νΈ νΈλ€λ¬
+ onSubmitNewProd(e) {
+ e.preventDefault();
+ const [_, prodNameInput, prodPriceInput, prodQuantityInput] = e.target;
+ const prodName = prodNameInput.value;
+ const prodPrice = +prodPriceInput.value;
+ const prodQuantity = +prodQuantityInput.value;
+ const newProd = { prodName, prodPrice, prodQuantity };
+
+ try {
+ validateProdInfo(newProd);
+ Dialog.show('μνμ΄ μ±κ³΅μ μΌλ‘ μΆκ°λμμ΅λλ€!');
+ } catch (error) {
+ Dialog.error(error);
+ return;
+ }
+
+ // μν μΆκ° μ΄λ²€νΈ λ°μ
+ const newEvent = new CustomEvent('addNewProd', {
+ detail: newProd,
+ });
+ this.$addProductForm.dispatchEvent(newEvent);
+ }
+}
diff --git a/javascript-vendingmachine-precourse/src/ProductPurchase/ProductPurchaseController.js b/javascript-vendingmachine-precourse/src/ProductPurchase/ProductPurchaseController.js
new file mode 100644
index 0000000..85e2b18
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/ProductPurchase/ProductPurchaseController.js
@@ -0,0 +1,71 @@
+import { $ } from '../utils/dom.js';
+import ProductPurchaseModel from './ProductPurchaseModel.js';
+import ProductPurchaseView from './ProductPurchaseView.js';
+import Dialog from '../utils/dialog.js';
+
+export default class ProductPurchaseController {
+ model;
+ view;
+
+ constructor() {
+ this.model = new ProductPurchaseModel();
+ this.view = new ProductPurchaseView();
+ }
+
+ // μν ꡬ맀 λ©λ΄ λ λλ§
+ renderProductPurchaseMenu() {
+ this.model.updateData();
+ this.view.render({
+ inserted: this.model.inserted,
+ productList: this.model.productList,
+ coinsForChange: this.model.coinsForChange,
+ });
+
+ // μ΄λ²€νΈ νΈλ€λ¬ λ°μΈλ©
+ // κΈμ‘ ν¬μ
+ $('#charge-input-form').addEventListener('insertCoin', ({ detail }) =>
+ this.onInsertCoins(detail)
+ );
+
+ // μν ꡬ맀
+ $('#available-product-table').addEventListener('purchaseProduct', ({ detail }) =>
+ this.onPurchaseProduct(detail)
+ );
+
+ // μλ λ°ν
+ $('#coin-return-button').addEventListener('returnChange', () => this.onReturnChange());
+ }
+
+ // κΈμ‘ ν¬μ
μ΄λ²€νΈ νΈλ€λ¬
+ onInsertCoins(inserted) {
+ this.model.setInsertedCoin(inserted);
+ this.view.updateInsertCoins(this.model.inserted);
+ }
+
+ // μν ꡬ맀 μ΄λ²€νΈ νΈλ€λ¬
+ onPurchaseProduct(prodId) {
+ try {
+ this.model.purchaseProduct(prodId);
+ Dialog.show('μνμ΄ μ μμ μΌλ‘ ꡬ맀λμμ΅λλ€!');
+ } catch (error) {
+ Dialog.error(error);
+ return;
+ }
+
+ this.view.updateInsertCoins(this.model.inserted);
+ this.view.updateProductList(this.model.productList);
+ }
+
+ // μλ λ°ν μ΄λ²€νΈ νΈλ€λ¬
+ onReturnChange() {
+ try {
+ this.model.returnChange();
+ } catch (error) {
+ Dialog.error(error);
+ return;
+ }
+
+ this.view.updateInsertCoins(this.model.inserted);
+ this.view.updateReturnChange(this.model.coinsForChange);
+ }
+}
diff --git a/javascript-vendingmachine-precourse/src/ProductPurchase/ProductPurchaseModel.js b/javascript-vendingmachine-precourse/src/ProductPurchase/ProductPurchaseModel.js
new file mode 100644
index 0000000..eb5dab1
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/ProductPurchase/ProductPurchaseModel.js
@@ -0,0 +1,107 @@
+import { getData, setData } from '../utils/storage.js';
+import { ERRORS } from '../utils/constants.js';
+
+export default class ProductPurchaseModel {
+ inserted; // ν¬μ
κΈμ‘
+ productList; // μν λͺ©λ‘
+ coinsForChange; // μλ νν©
+ initialChangInfo = {
+ total: 0,
+ coins: {
+ coin500: 0,
+ coin100: 0,
+ coin50: 0,
+ coin10: 0,
+ },
+ };
+
+ // getter
+ get inserted() {
+ return this.inserted;
+ }
+
+ get productList() {
+ return this.productList;
+ }
+
+ get coinsForChange() {
+ return this.coinsForChange;
+ }
+
+ // setter
+ setInsertedCoin(inserted) {
+ this.inserted += inserted;
+ setData('inserted', this.inserted);
+ }
+
+ // μ΄κΈ° λ°μ΄ν° μ
λ°μ΄νΈ
+ constructor() {
+ this.updateData();
+ }
+
+ updateData() {
+ this.inserted = getData('inserted') ?? 0;
+ this.productList = getData('productList') ?? [];
+ this.coinsForChange = getData('coinsForChange') ?? {
+ coin500: 0,
+ coin100: 0,
+ coin50: 0,
+ coin10: 0,
+ };
+ }
+
+ // μν ꡬ맀
+ purchaseProduct(prodId) {
+ const target = this.productList.find(product => product.id === +prodId);
+ if (this.inserted < target.price) throw new Error(ERRORS.PURCHASE.LACK_INSERTED);
+
+ if (target.quantity > 0) {
+ this.inserted -= target.price; // ν¬μ
κΈμ‘ μ
λ°μ΄νΈ
+ target.quantity--;
+ }
+
+ setData('inserted', this.inserted);
+ setData('productList', this.productList); // μν λͺ©λ‘ μ
λ°μ΄νΈ
+ }
+
+ // μλ λ°ν
+ returnChange() {
+ // κΈμ‘μ ν¬μ
νμ§ μκ³ μλμ λ°ννλ €κ³ ν λ
+ if (this.inserted === 0) throw new Error(ERRORS.PURCHASE.EMPTY_INSERTED);
+
+ const { total, coins } = getData('changeInfo');
+ // νμ¬ ν¬μ
κΈμ‘μ΄ μλλ³΄λ€ λ§μ λ
+ if (this.inserted >= total) {
+ this.coinsForChange = coins;
+ setData('changeInfo', this.initialChangInfo);
+ this.inserted -= total;
+ } else {
+ this.coinsForChange = this.convertChangeToCoins(this.inserted, this.coinsForChange);
+ setData('changeInfo', {
+ total: total - this.inserted,
+ coins: {
+ coin500: coins.coin500 - this.coinsForChange.coin500,
+ coin100: coins.coin100 - this.coinsForChange.coin100,
+ coin50: coins.coin50 - this.coinsForChange.coin50,
+ coin10: coins.coin10 - this.coinsForChange.coin10,
+ },
+ });
+ this.inserted = 0;
+ }
+
+ setData('inserted', this.inserted);
+ setData('coinsForChange', this.coinsForChange);
+ }
+
+ convertChangeToCoins(changeInput, coins) {
+ while (changeInput !== 0) {
+ const convertedCoins = MissionUtils.Random.pickNumberInList([10, 50, 100, 500]);
+ // λ¨μ μλμ΄ 10μ, λ³νλ λμ μ΄ 500μμΌ λλ κ΅ν λΆκ°
+ if (changeInput >= convertedCoins) {
+ changeInput -= convertedCoins;
+ coins[`coin${convertedCoins}`] += 1;
+ }
+ }
+ return coins;
+ }
+}
diff --git a/javascript-vendingmachine-precourse/src/ProductPurchase/ProductPurchaseView.js b/javascript-vendingmachine-precourse/src/ProductPurchase/ProductPurchaseView.js
new file mode 100644
index 0000000..77302a3
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/ProductPurchase/ProductPurchaseView.js
@@ -0,0 +1,162 @@
+import { $ } from '../utils/dom.js';
+import Dialog from '../utils/dialog.js';
+import { validateChange } from '../utils/validation.js';
+
+export default class ProductPurchaseView {
+ template = `
+
+
+
+ ꡬ맀ν μ μλ μν νν©
+
+
+
+ λ°νλ μλ
+ λ°ννκΈ°
+
+
+
+ `;
+
+ // μ΄κΈ° λ λλ§
+ render({ inserted, productList, coinsForChange }) {
+ $('#current-menu').innerHTML = this.template;
+ this.updateInsertCoins(inserted); // ν¬μ
κΈμ‘
+ this.updateProductList(productList); // μν 리μ€νΈ
+ this.updateReturnChange(coinsForChange); // μλ νν©
+ $('#charge-input-form').addEventListener('submit', e => this.onInsertCoin(e));
+ $('#available-product-table').addEventListener('click', e => this.onClickPurchaseProduct(e));
+ $('#coin-return-button').addEventListener('click', () => this.onClickReturnChange());
+ }
+ x;
+
+ // ν¬μ
κΈμ‘ λ·° μ
λ°μ΄νΈ
+ updateInsertCoins(inserted) {
+ $('#charge-amount').textContent = `${inserted}`;
+ }
+
+ // μν λͺ©λ‘ λ·° μ
λ°μ΄νΈ
+ updateProductList(productList) {
+ $('#available-product-table').innerHTML = '';
+ $('#available-product-table').innerHTML = this.createProductList(productList);
+ }
+
+ // μλ λ°ν λ·° μ
λ°μ΄νΈ
+ updateReturnChange(coinsForChange) {
+ $('#coin-return-table').innerHTML = '';
+ $('#coin-return-table').innerHTML = this.createReturnChange(coinsForChange);
+ }
+
+ // κΈμ‘ ν¬μ
μ΄λ²€νΈ emit
+ onInsertCoin(e) {
+ e.preventDefault();
+ const [_, chargeInput] = e.target;
+ try {
+ validateChange(+chargeInput.value);
+ Dialog.show('κΈμ‘μ΄ μ μμ μΌλ‘ ν¬μ
λμμ΅λλ€!');
+ } catch (error) {
+ Dialog.error(error);
+ return;
+ }
+
+ const newEvent = new CustomEvent('insertCoin', {
+ detail: +chargeInput.value,
+ });
+ $('#charge-input-form').dispatchEvent(newEvent);
+ }
+
+ // μν ꡬ맀 μ΄λ²€νΈ emit
+ onClickPurchaseProduct({ target }) {
+ if (target.className === 'purchase-button') {
+ const { productId } = target.closest('.product-purchase-item').dataset;
+ const newEvent = new CustomEvent('purchaseProduct', {
+ detail: productId,
+ });
+ $('#available-product-table').dispatchEvent(newEvent);
+ }
+ }
+
+ // μλ λ°ν μ΄λ²€νΈ emit
+ onClickReturnChange() {
+ const newEvent = new CustomEvent('returnChange');
+ $('#coin-return-button').dispatchEvent(newEvent);
+ }
+
+ // ν
νλ¦Ώ μ
λ°μ΄νΈ
+ createProductList(productList) {
+ return `
+
+
+ μνλͺ
+ κ°κ²©
+ μλ
+ ꡬ맀
+
+
+
+ ${productList
+ .map(
+ prod => `
+
+ ${prod.name}
+ ${
+ prod.price
+ }
+ ${
+ prod.quantity
+ }
+
+ ${
+ prod.quantity === 0
+ ? `ꡬ맀 `
+ : `ꡬ맀 `
+ }
+
+
+ `
+ )
+ .join('')}
+
+ `;
+ }
+
+ createReturnChange(coinsForChange) {
+ const { coin500, coin100, coin50, coin10 } = coinsForChange;
+
+ return `
+
+
+ λμ
+ κ°μ
+
+
+
+
+ 500μ
+ ${coin500}κ°
+
+
+ 100μ
+ ${coin100}κ°
+
+
+ 50μ
+ ${coin50}κ°
+
+
+ 10μ
+ ${coin10}κ°
+
+
+`;
+ }
+}
diff --git a/javascript-vendingmachine-precourse/src/index.js b/javascript-vendingmachine-precourse/src/index.js
new file mode 100644
index 0000000..794d4fc
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/index.js
@@ -0,0 +1,4 @@
+import App from './App.js';
+import { $ } from './utils/dom.js';
+
+new App($('#app'));
diff --git a/javascript-vendingmachine-precourse/src/utils/constants.js b/javascript-vendingmachine-precourse/src/utils/constants.js
new file mode 100644
index 0000000..e9317ee
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/utils/constants.js
@@ -0,0 +1,25 @@
+export const ERRORS = {
+ PROD_ADD: {
+ EMPTY_PROD_NAME: 'μνλͺ
μ μ
λ ₯ν΄μ£ΌμΈμ.',
+ WRONG_PROD_PRICE: 'μνμ κ°κ²©μ 0μλ³΄λ€ ν° κ°μΌλ‘ μ
λ ₯ν΄μ£ΌμΈμ.',
+ WRONG_PRICE_UNIT: 'μν κ°κ²©μ 10μ λ°°μλ‘ μ
λ ₯ν΄μ£ΌμΈμ.',
+ WRONG_QUANTITY: 'μν μλμ 0λ³΄λ€ ν° κ°μΌλ‘ μ
λ ₯ν΄μ£ΌμΈμ.',
+ DUPLICATE_PROD_NAME: 'μ΄λ―Έ λ±λ‘λ μνμ
λλ€.',
+ },
+ CHANGE: {
+ EMPTY_CHANGE_AMOUNT: 'μΆ©μ κΈμ‘μ 0μλ³΄λ€ ν° κ°μ μ
λ ₯ν΄μ£ΌμΈμ.',
+ WRONG_CHANGE_UNIT: 'μΆ©μ κΈμ‘μ 10μ λ°°μλ‘ μ
λ ₯ν΄μ£ΌμΈμ.',
+ },
+ PURCHASE: {
+ EMPTY_PRODUCT_LIST: 'λ±λ‘λ μνμ΄ μμ΅λλ€. μνμ λ±λ‘ν΄μ£ΌμΈμ.',
+ EMPTY_CHANGE: 'μλμ΄ λΆμ‘±ν΄ μνμ ꡬ맀ν μ μμ΅λλ€. μλμ μΆ©μ ν΄μ£ΌμΈμ.',
+ LACK_INSERTED: 'νμ¬ ν¬μ
λ κΈμ‘μΌλ‘ ν΄λΉ μνμ ꡬ맀ν μ μμ΅λλ€.',
+ EMPTY_INSERTED: 'ν¬μ
λ κΈμ‘μ΄ μμ΅λλ€.',
+ },
+};
+
+export const ERROR_BOUNDARIES = {
+ PRODUCT_ADD: {
+ MINIMUM_PRICE: 0,
+ },
+};
diff --git a/javascript-vendingmachine-precourse/src/utils/dialog.js b/javascript-vendingmachine-precourse/src/utils/dialog.js
new file mode 100644
index 0000000..13389d4
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/utils/dialog.js
@@ -0,0 +1,8 @@
+export default class Dialog {
+ static show(message) {
+ window.alert(message);
+ }
+ static error({ message }) {
+ window.alert(message);
+ }
+}
diff --git a/javascript-vendingmachine-precourse/src/utils/dom.js b/javascript-vendingmachine-precourse/src/utils/dom.js
new file mode 100644
index 0000000..8f16fcc
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/utils/dom.js
@@ -0,0 +1 @@
+export const $ = selector => document.querySelector(selector);
diff --git a/javascript-vendingmachine-precourse/src/utils/storage.js b/javascript-vendingmachine-precourse/src/utils/storage.js
new file mode 100644
index 0000000..eb117ab
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/utils/storage.js
@@ -0,0 +1,3 @@
+// λ‘컬 μ€ν λ¦¬μ§ get, set
+export const getData = key => JSON.parse(window.localStorage.getItem(key));
+export const setData = (key, data) => window.localStorage.setItem(key, JSON.stringify(data));
diff --git a/javascript-vendingmachine-precourse/src/utils/validation.js b/javascript-vendingmachine-precourse/src/utils/validation.js
new file mode 100644
index 0000000..2cf5e52
--- /dev/null
+++ b/javascript-vendingmachine-precourse/src/utils/validation.js
@@ -0,0 +1,48 @@
+import { ERRORS, ERROR_BOUNDARIES } from './constants.js';
+import { getData } from './storage.js';
+
+// μν μΆκ° - μν μμ΄λ μμ±
+export const makeProductId = () =>
+ Math.max(...(getData('productList') ?? []).map(prod => prod.id), 0) + 1;
+
+// μν μΆκ° - μ ν¨μ± κ²μ¬
+export const validateProdInfo = ({ prodName, prodPrice, prodQuantity }) => {
+ // μνλͺ
λ―Έμ
λ ₯
+ if (!prodName.trim().length) throw new Error(ERRORS.PROD_ADD.EMPTY_PROD_NAME);
+
+ // μν μ΅μ κΈμ‘ λ―Έλ§
+ if (prodPrice <= ERROR_BOUNDARIES.PRODUCT_ADD.MINIMUM_PRICE)
+ throw new Error(ERRORS.PROD_ADD.WRONG_PROD_PRICE);
+
+ // μν κ°κ²© μ΄μ
+ if (prodPrice % 10 !== 0) throw new Error(ERRORS.PROD_ADD.WRONG_PRICE_UNIT);
+
+ // μν μλ μ΄μ
+ if (prodQuantity <= 0) throw new Error(ERRORS.PROD_ADD.WRONG_QUANTITY);
+
+ // μν μ€λ³΅
+ if ((getData('productList') ?? []).map(prod => prod.name).includes(prodName))
+ throw new Error(ERRORS.PROD_ADD.DUPLICATE_PROD_NAME);
+};
+
+// μλ κ΅ν - μ ν¨μ± κ²μ¬
+export const validateChange = changeInput => {
+ // μλμ΄ 0μ μ΄νλ‘ μ
λ ₯λ κ²½μ°
+ if (changeInput <= 0) throw new Error(ERRORS.CHANGE.EMPTY_CHANGE_AMOUNT);
+
+ // μλ λ¨μ μ΄μ
+ if (changeInput % 10 !== 0) throw new Error(ERRORS.CHANGE.WRONG_CHANGE_UNIT);
+};
+
+// μν ꡬ맀 - λ±λ‘λ μν μ¬λΆ νμΈ
+export const validateProdList = () => {
+ const productList = getData('productList') ?? null;
+ if (!productList) throw new Error(ERRORS.PURCHASE.EMPTY_PRODUCT_LIST);
+};
+
+// μν ꡬ맀 - μλ νμΈ
+export const validateChanges = () => {
+ const changeInfo = getData('changeInfo') ?? 0;
+ if (!changeInfo) throw new Error(ERRORS.PURCHASE.EMPTY_CHANGE);
+ changeInfo;
+};
diff --git a/javascript-vendingmachine-precourse/style.css b/javascript-vendingmachine-precourse/style.css
new file mode 100644
index 0000000..2e882bc
--- /dev/null
+++ b/javascript-vendingmachine-precourse/style.css
@@ -0,0 +1,25 @@
+section {
+ margin: 20px;
+}
+
+button {
+ border: 1px solid black;
+ border-radius: 3px;
+ background-color: white;
+ font-size: medium;
+ margin: 10px;
+}
+
+table,
+tr,
+th,
+td {
+ border: 1px solid #282828;
+ padding: 10px;
+ border-collapse: collapse;
+ text-align: center;
+}
+
+fieldset {
+ margin-bottom: 20px;
+}
diff --git a/javascript-vendingmachine-precourse/test/app.spec.js b/javascript-vendingmachine-precourse/test/app.spec.js
new file mode 100644
index 0000000..0a09605
--- /dev/null
+++ b/javascript-vendingmachine-precourse/test/app.spec.js
@@ -0,0 +1,116 @@
+describe("ꡬν κ²°κ³Όκ° μꡬμ¬νκ³Ό μΌμΉν΄μΌ νλ€.", () => {
+ const baseUrl = "../index.html";
+ const SELECTOR = {
+ COIN_MENU: "#vending-machine-manage-menu",
+ COIN_CHARGE_INPUT: "#vending-machine-charge-input",
+ COIN_CHARGE_BUTTON: "#vending-machine-charge-button",
+ COIN_500: "#vending-machine-coin-500-quantity",
+ COIN_100: "#vending-machine-coin-100-quantity",
+ COIN_50: "#vending-machine-coin-50-quantity",
+ COIN_10: "#vending-machine-coin-10-quantity",
+ PRODUCT_MENU: "#product-add-menu",
+ PRODUCT_NAME_INPUT: "#product-name-input",
+ PRODUCT_PRICE_INPUT: "#product-price-input",
+ PRODUCT_QUANTITY_INPUT: "#product-quantity-input",
+ PRODUCT_ADD_BUTTON: "#product-add-button",
+ PURCHASE_MENU: "#product-purchase-menu",
+ PURCHASE_CHARGE_INPUT: "#charge-input",
+ PURCHASE_CHARGE_AMOUNT: "#charge-amount",
+ PURCHASE_CHARGE_BUTTON: "#charge-button",
+ PURCHASE_ITEM_BUTTON: ".purchase-button",
+ PURCHASE_ITEM_QUANTITY: ".product-purchase-quantity",
+ };
+
+ before(() => {
+ Cypress.Commands.add("stubRandomReturns", (returnValues = []) => {
+ const randomStub = cy.stub();
+
+ returnValues.forEach((value, index) => {
+ randomStub.onCall(index).returns(value);
+ });
+
+ cy.visit(baseUrl, {
+ onBeforeLoad: (window) => {
+ window.MissionUtils = {
+ Random: {
+ pickNumberInList: randomStub,
+ },
+ };
+ },
+ });
+ });
+
+ Cypress.Commands.add("addProduct", (name, price, quantity) => {
+ cy.get(SELECTOR.PRODUCT_NAME_INPUT).type(name);
+ cy.get(SELECTOR.PRODUCT_PRICE_INPUT).type(price);
+ cy.get(SELECTOR.PRODUCT_QUANTITY_INPUT).type(quantity);
+ cy.get(SELECTOR.PRODUCT_ADD_BUTTON).click();
+ });
+ });
+
+ beforeEach(() => {
+ cy.stubRandomReturns([100, 100, 100, 100, 50]);
+ });
+
+ it("μν 1κ°λ₯Ό ꡬ맀ν μ μμ΄μΌ νλ€.", () => {
+ // given
+ const name = "μ½λΌ";
+ const price = 1500;
+ const quantity = 20;
+ const coinAmount = 450;
+ const chargeAmount = 3000;
+
+ // μν μΆκ°
+ cy.get(SELECTOR.PRODUCT_MENU).click();
+ cy.addProduct(name, price, quantity);
+ cy.addProduct("μ¬μ΄λ€", 1000, 10);
+
+ // μλ μΆ©μ
+ cy.get(SELECTOR.COIN_MENU).click();
+ cy.get(SELECTOR.COIN_CHARGE_INPUT).type(coinAmount);
+ cy.get(SELECTOR.COIN_CHARGE_BUTTON).click();
+
+ // κΈμ‘ ν¬μ
+ cy.get(SELECTOR.PURCHASE_MENU).click();
+ cy.get(SELECTOR.PURCHASE_CHARGE_INPUT).type(chargeAmount);
+ cy.get(SELECTOR.PURCHASE_CHARGE_BUTTON).click();
+
+ // when
+ cy.get("[data-product-name='μ½λΌ']")
+ .parent()
+ .find(SELECTOR.PURCHASE_ITEM_BUTTON)
+ .click();
+
+ // then
+ cy.get(SELECTOR.PURCHASE_CHARGE_AMOUNT).should(
+ "have.text",
+ chargeAmount - price
+ );
+ cy.get("[data-product-name='μ½λΌ']")
+ .parent()
+ .find(SELECTOR.PURCHASE_ITEM_QUANTITY)
+ .should("have.text", quantity - 1);
+ cy.get(SELECTOR.COIN_MENU).click();
+ cy.get(SELECTOR.COIN_100).should("have.text", "4κ°");
+ cy.get(SELECTOR.COIN_50).should("have.text", "1κ°");
+ });
+
+ it("μλͺ»λ μ
λ ₯κ°μΌλ‘ μλ μΆ©μ μ μλνλ κ²½μ° alertμ΄ νΈμΆλμ΄μΌ νλ€.", () => {
+ // given
+ const alertStub = cy.stub();
+ const invalidInput = -1;
+
+ cy.on("window:alert", alertStub);
+
+ // when
+ cy.get(SELECTOR.COIN_MENU).click();
+ cy.get(SELECTOR.COIN_CHARGE_INPUT).type(invalidInput);
+
+ // then
+ cy.get(SELECTOR.COIN_CHARGE_BUTTON)
+ .click()
+ .then(() => {
+ expect(alertStub).to.be.called;
+ });
+ });
+});